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中的意思是 ...
随机推荐
- 学习java一个月的进展
作为一个阶段性总结,有很多的东西需要说明,有细节的,有架构的,且听我细细说来. java和php最大的区别不止是类型的强制定义,而是在设计思路上有着非常重大的偏差(虽然SY3框架已经开始借鉴JAVA的 ...
- Windows下Redis安装过程
1.去github下载Redis-x64-2.8.2402.zip压缩包 2.将压缩包解压到你要安装的目录下 3.将redis设置为开机自启动服务 redis-server --service-ins ...
- npm install详解
package.json中dependencies和devDependencies的部分都会被安装,区别在于前者用于生产环境,后者用于开发环境-g 表示全局安装,通常用于安装脚手架等工具–save(- ...
- adb+monkey压力测试入门
一.ADB安装步骤及ADB环境配置 1.ADB安装步骤 1)adb工具安装地址:http://www.wmzhe.com/soft-39913.html 2)下载安装包后,解压,将adb安装在根目录下 ...
- 关于jstl中碰到的Property 'username' not found on type java.lang.String异常
在jstl的forEach循环的时候总是有异常,刚开始以为是把类的属性名打错了,因为显示的是Property not found,但就算从类文件里面复制属性名过来依然显示的是Property not ...
- 简述at和crontab命令
at 在指定时间执行相关命令 用法:at [option] TIME 常用选项: -l:查询等待运行作业的队列 -d:删除作业,加作业号 -q QUEVE: -c :查看具体作业任务: -f /pat ...
- IS基础(函数片)
函数基本介绍 为什么需要函数 之所以需要函数,是因为函数可以实现对代码的复用.相同的代码,我们不需要再重复书写,只需要书写一次就足够了.函数有些时候可以看做是一个暗箱.我们不需要知道函数内部是怎么实现 ...
- 11. IDS (Intrusion detection systems 入侵检测系统 6个)
Snort该网络入侵检测和防御系统擅长于IP网络上的流量分析和数据包记录. 通过协议分析,内容研究和各种预处理器,Snort可以检测到数千个蠕虫,漏洞利用尝试,端口扫描和其他可疑行为. Snort使用 ...
- Linux第六节课学习笔记
if条件测试语句可以让脚本根据实际情况自动执行相应的命令,可以分为单分支.双分支与多分支. /dev/null为无回收功能的垃圾箱. read是用来读取用户输入信息的命令,-p用来显示提示信息. fo ...
- Tenka 1 Computer Contest C-Align
C - Align Time limit : 2sec / Memory limit : 1024MB Score : 400 points Problem Statement You are giv ...