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中的意思是 ...
随机推荐
- 关于jetbrains系列产品2018.1.5以后的使用(crack)方法
产品请一律官网下载:https://www.jetbrains.com/ 我这里以JetBrains GoLand 2018.2.1为例说明下非付费的使用方法(若资金允许,请点击https://www ...
- paddlepaddle
1. 训练过程中cost出现nan 可能是因为有脏数据,寻找脏数据的方法就是,设置batch_size=1, paddle.reader.shuffle 中buf_size=1 一条一条的进行训练,看 ...
- 计算python中对象的内存大小
一般的sys.getsizeof()显示不了复杂的字典. 查看类中的内容: def dump(obj): for attr in dir(obj):#dir显示类的所有方法 print(" ...
- hive 非等值连接, 设置hive为nonstrict模式
1 数据准备 create table stocks(id int, date string,price string, company string); insert into table stoc ...
- AssetBundle打包-----BuildPipeline的应用
打包思路:确定要打包资源的路径.和打包的输出路径(一般为S路径),把存放资源的路径使用递归进行遍历,获取所有资源,文件类型的资源可以通过File拷贝或IO写到输出路径,其他资源的打包通过AssetBu ...
- android app demo
package jczb.shoping.model; import java.io.Serializable; import android.R.string; //登录所需要的字段信息 publi ...
- 改变一下主要发博的方向吧...转scratch!
因为expression2实在是没什么好说的,BUI,水滴鱼大佬还有其他贴吧上的大佬,实在是多得不行,我一个小人物也说不了什么,然而scratch我却可以多发发脚本,思路,美工啊等等.所以以后我就主要 ...
- 引擎设计跟踪(九.14.3.3) Deferred shading的一些小细节
1.ambient light 之前的shader里面, 方向光会加上ambient 的计算. 但是如果没有方向光, 就没有ambient. 这是把全局方向光改为点光源之后发现的, 因为透明物体的fo ...
- Mac OS X L2TP Client Setup
原文链接:http://www.softether.org/4-docs/2-howto/9.L2TPIPsec_Setup_Guide_for_SoftEther_VPN_Server/5.Mac_ ...
- c# AutoMapper 使用方式和再封装
安装方式:使用vs自带的nuget管理工具,搜索AutoMapper ,选择第一个安装到你的项目即可. 我从网上找了一些资料, 参考网址:http://blog.csdn.net/csethcrm/a ...