WinForm-简单21点纸牌小游戏
纸牌游戏有很多种玩法,C#代码写的纸牌游戏,网上也能找到不少,从中也能学习到不少知识,自己动手也写一个,算是记录下学习过程吧.
纸牌21点的玩法也比较简单,就是看谁手中的所有牌相加是21点,或是离21点的数字最近,最大者赢.照着这样思路开始编写代码.
牌面A到10按牌面数字算点数,J,Q,K,大小王都算10点;
定义一个纸牌父类PKFather
public enum PokerColour
{ Diamond,//方块=0
Club, //梅花=1
Heart, //红桃=2
Spade, //黑桃=3
Wang,
}
public enum Rank //牌面点数
{
One = ,
Two,
Three,
Four,
Five,
Six,
Seven,
Eight,
Nine,
Ten,
Jack,
Queen,
King,
XWang,
DWang,
}
public abstract class PKFather
{
public int X { get; set; }
public int Y { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public Rank Rank { get; set; }//牌面点数
public PokerColour PkColour { get; set; }//牌面花色;红桃,黑桃,方片,梅花; public PKFather(int x,int y,int width,int height,Rank rank,PokerColour pkColour)
{
this.X = x;
this.Y = y;
this.Width = width;
this.Height = height;
this.Rank = rank;
this.PkColour = pkColour; }
public abstract void Draw(Graphics g);
}
父类中定义了两个枚举,Rank用做牌面点数,PokerColour用做牌的花色,其实牌的花色在21点这个小游戏中用不上,只是在剪裁纸牌图片时需要.纸牌的图片如下:
整 个一副牌都在一个图片中,这两个枚举值等于提供了行列坐标,剪裁图片时更方便些,用法在后面的代码中,抽象方法Draw在子类中实现。
class RPoker:PKFather
{
Image image = Resources.card;//图片在资源文件中
public RPoker(int x, int y, int width, int height, Rank rank, PokerColour pkcolour)
: base(x, y, width, height, rank,pkcolour)
{ } public override void Draw(System.Drawing.Graphics g)
{
Rectangle rect = new Rectangle(this.X, this.Y, Width, Height);//要裁切图片的位置大小
switch (this.PkColour)
{
case PokerColour.Diamond:
g.DrawImage(image, rect, new Rectangle(((int)Rank - ) * Width, (int)(PkColour + ) * Height, Width, Height), GraphicsUnit.Pixel);
break;
case PokerColour.Club:
g.DrawImage(image, rect, new Rectangle(((int)Rank - ) * Width, (int)(PkColour + ) * Height, Width, Height), GraphicsUnit.Pixel);
break;
case PokerColour.Heart:
g.DrawImage(image, rect, new Rectangle(((int)Rank - ) * Width, (int)(PkColour - ) * Height, Width, Height), GraphicsUnit.Pixel);
break;
case PokerColour.Spade:
g.DrawImage(image, rect, new Rectangle(((int)Rank - ) * Width, (int)(PkColour - ) * Height, Width, Height), GraphicsUnit.Pixel);
break;
case PokerColour.Wang:
g.DrawImage(image, rect, new Rectangle(((int)Rank - ) * Width, (int)PkColour * Height, Width, Height), GraphicsUnit.Pixel);
break;
default:
break;
} }
}
子类RPoker继承自PKFather,实现抽象方法Draw,用来绘制具体的纸牌。将纸牌的图片加入项目的资源文件步骤是,在解决方案资源管理器中,选中项目,依次点开 Properties->Resources.resx (双击该文件)->在打开的窗口中选菜单"添加资源"->添加现有文件;选中要加入的图片,点确定就成了。更简便的方法是当双击Resources.resx文件在vs中打开后,直接拖入图片,就可完成添加图片的步骤。Image image = Resources.card;将图片资源赋值给image,这样在后面的代码中,就可以对image中的纸牌图片进行剪裁,提取了。
生成54张牌
private void GetCard()
{
for (int j = ; j <= ; j++)
{
switch (j)
{
case :
for (int k = ; k < ; k++)
{
allCard.Add(new RPoker( * k, j, , , (Rank)k, (PokerColour)j));
}
break;
case :
for (int k = ; k < ; k++)
{
allCard.Add(new RPoker( * k, j * , , , (Rank)k, (PokerColour)j));
}
break;
case :
for (int k = ; k < ; k++)
{
allCard.Add(new RPoker( * k, j * , , , (Rank)k, (PokerColour)j));
}
break;
case :
for (int k = ; k < ; k++)
{
allCard.Add(new RPoker( * k, j * , , , (Rank)k, (PokerColour)j));
}
break;
case :
for (int k = ; k < ; k++)
{
allCard.Add(new RPoker( * k, j * , , , (Rank)k + , (PokerColour)j));
}
break;
default:
break;
}
}
}
其中固定的数值,都是在整张图片提取成单张牌时具体尺寸
洗牌代码;
// 定义随机数
Random random = new Random();
// 从数组的最后一个数开始递减
for (int i = allCard.Count - ; i > ; i--)
{
// 随机下标
int index = random.Next(, i);
// 随机出来的数与最后位置的数交换
RPoker temp = allCard[i];
allCard[i] = allCard[index];
allCard[index] = temp;
}
这种随机打乱的洗牌方法可以有很多种,找到合适的方法就可。
两个类完成后,其余的代码都写到到界面Form中,运行后的界面:
主要记录代码编写过程,界面就简单来了。
/// <summary>
/// allCard所有54张牌
/// </summary>
private List<RPoker> allCard = new List<RPoker>();//所有牌
private int TopCard;//计数
private int computerNumber;//计算机牌张数 private int playerNumber;//玩家牌张数
private int computerCount;//计算机牌点数
private int playerCount;//玩家牌点数 private void Form1_Load(object sender, EventArgs e)
{ GetCard();
Shuffle();
}
private void button2_Click(object sender, EventArgs e)//玩家要牌
{
allCard[TopCard].X = + * playerNumber;
allCard[TopCard].Y = ;
allCard[TopCard].Draw(this.CreateGraphics());
if (allCard[TopCard].Rank > Rank.Ten)
{
playerCount += ;
playerNumber += ;
}
else
{
playerCount += (int)allCard[TopCard].Rank;
playerNumber += ;
}
TopCard++;
if (TopCard >= )
{
Shuffle();
MessageBox.Show("新的一副牌!!");
}
label2.Text = playerCount.ToString();
label2.Refresh();
label3.Text = playerNumber.ToString();
label3.Refresh();
if (playerCount > )
{
MessageBox.Show("玩家Player lose!");
button1.Enabled = true;
button2.Enabled = false;
button3.Enabled = false; }
} private void button1_Click(object sender, EventArgs e)//开始游戏
{
this.Refresh();
button1.Enabled = false;
label1.Text = "";
label2.Text = "";
label1.Refresh();
label2.Refresh();
computerNumber = ;
playerNumber = ;
playerCount = ;
computerCount = ;
//画玩家第一张牌
allCard[TopCard].X = ;
allCard[TopCard].Y = ;
allCard[TopCard].Draw(this.CreateGraphics()); if (allCard[TopCard].Rank > Rank.Ten)
{
playerCount += ;
playerNumber += ;
}
else
{
playerCount += (int)allCard[TopCard].Rank;
playerNumber += ;
}
TopCard++;
if (TopCard >= )
{
Shuffle();
MessageBox.Show("新的一副牌!!");
}
label2.Text = playerCount.ToString();
label2.Refresh();
label3.Text = playerNumber.ToString();
label3.Refresh(); //画计算机第一张牌
allCard[TopCard].X = ;
allCard[TopCard].Y = ;
allCard[TopCard].Draw(this.CreateGraphics()); if (allCard[TopCard].Rank > Rank.Ten)
{
computerCount += ;
computerNumber += ;
}
else
{
computerCount += (int)allCard[TopCard].Rank;
computerNumber += ;
}
TopCard++;
if (TopCard >= )
{
Shuffle();
MessageBox.Show("新的一副牌!!");
}
label1.Text = computerCount.ToString();
label1.Refresh();
label4.Text = computerNumber.ToString();
label4.Refresh(); //画玩家第二张牌
allCard[TopCard].X = ;
allCard[TopCard].Y = ;
allCard[TopCard].Draw(this.CreateGraphics()); if (allCard[TopCard].Rank > Rank.Ten)
{
playerCount += ;
playerNumber += ;
}
else
{
playerCount += (int)allCard[TopCard].Rank;
playerNumber += ;
}
TopCard++;
if (TopCard >= )
{
Shuffle();
MessageBox.Show("新的一副牌!!");
}
label2.Text = playerCount.ToString();
label2.Refresh();
label3.Text = playerNumber.ToString();
label3.Refresh(); //画计算机第二张牌
allCard[TopCard].X = ;
allCard[TopCard].Y = ;
allCard[TopCard].Draw(this.CreateGraphics());
if (allCard[TopCard].Rank > Rank.Ten)
{
computerCount += ;
computerNumber += ;
}
else
{
computerCount += (int)allCard[TopCard].Rank;
computerNumber += ;
}
TopCard++;
if (TopCard >= )
{
Shuffle();
MessageBox.Show("新的一副牌!!");
}
label1.Text = computerCount.ToString();
label1.Refresh();
label4.Text = computerNumber.ToString();
label4.Refresh();
button2.Enabled = true;
button3.Enabled = true;
} private void button3_Click(object sender, EventArgs e)//玩家停牌
{
//玩家停牌
button2.Enabled = false;
button3.Enabled = false;
ComputerPlay();
}
private void ComputerPlay()//电脑自行要牌
{
do
{
if (computerCount < )
{
allCard[TopCard].X = + * computerNumber;
allCard[TopCard].Y = ;
allCard[TopCard].Draw(this.CreateGraphics());
if (allCard[TopCard].Rank > Rank.Ten)
{
computerCount += ;
computerNumber += ;
}
else
{
computerCount += (int)allCard[TopCard].Rank;
computerNumber += ;
}
TopCard++;
}
else
{
break;
}
} while (true);
label1.Text = computerCount.ToString();
label1.Refresh();
label4.Text = computerNumber.ToString();
label4.Refresh();
if (computerCount <= )
{
if (playerCount > computerCount)
{
MessageBox.Show("玩家Player win!");
}
else
{
MessageBox.Show("电脑 win!");
}
}
else
{
MessageBox.Show("玩家Player win!");
}
button1.Enabled = true;
button2.Enabled = false;
button3.Enabled = false;
}
界面Form1中的代码,逻辑也比较简单,水平所限程序也算完成了,不足之处还望高手能够指出。
WinForm-简单21点纸牌小游戏的更多相关文章
- [Python3 练习] 007 简单的猜数字小游戏
题目:简单的猜数字小游戏 (1) 描述 程序随机生成一个数字,玩家用键盘输入所猜数字,在规定次数内猜对为胜. (2) 要求 程序随机生成一个 1 到 100 的自然数 有 7 次机会去猜 机会用尽之前 ...
- 如何开发一个简单的HTML5 Canvas 小游戏
原文:How to make a simple HTML5 Canvas game 想要快速上手HTML5 Canvas小游戏开发?下面通过一个例子来进行手把手教学.(如果你怀疑我的资历, A Wiz ...
- 一个简单的基于canvas小游戏
GDOI2016是我的退役战,不知道是题目画风不对,还是我自身的问题. 不过没关系啦,反正已经进过一次队OI生涯就没有什么遗憾的了. 这几天尝试着去做了个所谓的html5小游戏,略显简陋,但还是写个总 ...
- 简单的猜数字小游戏--Python
猜数字小游戏: #coding=utf-8 import random answer =random.randint(1,100) #生成随机数 n=int (input("Please ...
- UIDynamicBehavior的简单使用:接球小游戏
一.概念扩充: 1.在开发中,我们可以使用UIKit中提供的仿真行为,实现与现实生活中类似的物理仿真动画,UIKit动力学最大的特点是将现实世界动力驱动的动画引入了UIKit,比如重力,铰链连接,碰撞 ...
- JavaScript实践-简单的贪吃蛇小游戏
实现逻辑: //获取Html中的格子(行,列) //建立数组存储所有格子(x,y) //建立数组用于存储蛇身(x,y) //生成随机坐标(x,y)的函数 //随机创建蛇身并存储到蛇身数组 //创建食物 ...
- JavaScript小游戏实例:简单的键盘练习
键盘是一种常用的输入设备,灵活熟练地使用键盘进行输入是计算机用户需掌握的一门基本功.下面我们编写一个简单的键盘练习游戏. 1.刺破气泡交互式小动画 在编写简单的键盘练习游戏之前,先设计一个简单地刺破气 ...
- 拼图小游戏之计算后样式与CSS动画的冲突
先说结论: 前几天写了几个非常简单的移动端小游戏,其中一个拼图游戏让我郁闷了一段时间.因为要获取每张图片的位置,用`<style>`标签写的样式,直接获取计算后样式再用来交换位置,结果就悲 ...
- 制作动画或小游戏——CreateJS事件(二)
在Canvas中如果要添加事件,就需要计算坐标来模拟各种事件,而EaselJS中已经封装好了多个事件,只需调用即可. 一.事件 1)点击 事件是绑定在Shape类中的,click事件与DOM中的意思是 ...
随机推荐
- read读文件
FILE *fp=fopen("F:\\QQBrowser_Setup_DNF.exe", "rb"); fseek(fp, , SEEK_END); long ...
- python 将汉字转换为拼音
xpinyin提供把汉字转为汉语拼音的功能. 安装此模块 pip install xpinyin简单用例: from xpinyin import Pinyin pin = Pinyin() test ...
- NSArray NSMutableArray
NSArray 或者 NSMUtableArray 去除重复的数据: 原来集合操作可以通过valueForKeyPath来实现的,去重可以一行代码实现: [array valueForKeyPath: ...
- NSTimer应用
NSTimer应用 在参与项目开发中遇到了NSTimer的应用,虽然我负责的模块内只用到了一小部分,但我觉得还是有必要拿出来好好琢磨一下. 一.概念(来自官方描述) 官网上最新的定义是“A timer ...
- 微信小程序之点击列表的item带参数跳转界面
1.在js文件里写个界面跳转的事件处理函数gotableinfo,var index = parseInt(e.currentTarget.dataset.index); 为获取当前点击列表的下脚标, ...
- 构建之法 chapter1 心得
阅读完了<构建之法>第一章后,觉得我们平时使用的软件并不是自己想象中的那样简单,用的时候是觉得很方便,但从来没有考虑过一个软件的背后需要一个团队多少的付出才能换来一个获得用户频频好评的软件 ...
- 简述linux操作系统启动流程
Linux启动流程 POST-->BootSequence(BIOS)->Bootloader(MBR,grub)-->kernnel(ramdisk,initrd)-->ro ...
- Kali Linux Web后门工具、Windows操作系统痕迹清除方法
Kali Linux Web后门工具 Kali的web后门工具一共有四款,今天只介绍WebaCoo 首先介绍第一个WeBaCoo(Web Backdoor Cookie) WeBaCoo是一款隐蔽的脚 ...
- cordova插件新的窗口实例打开连接: cordova-plugin-inappbrowser
1. 添加插件:cordova plugin add cordova-plugin-inappbrowser : 2. InAppBrowser可以使用新的窗口实例打开连接,提供了地址栏的显示隐藏, ...
- EXCEL 批量添加单元格名称
在EXCEL单元格的值填入想为其设置的名称之后,调整下述代码的begin_line,begin_column,end_line,end_column的值,执行此宏,可用于批量为单元格设置名称. (注: ...