纸牌游戏有很多种玩法,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点纸牌小游戏的更多相关文章

  1. [Python3 练习] 007 简单的猜数字小游戏

    题目:简单的猜数字小游戏 (1) 描述 程序随机生成一个数字,玩家用键盘输入所猜数字,在规定次数内猜对为胜. (2) 要求 程序随机生成一个 1 到 100 的自然数 有 7 次机会去猜 机会用尽之前 ...

  2. 如何开发一个简单的HTML5 Canvas 小游戏

    原文:How to make a simple HTML5 Canvas game 想要快速上手HTML5 Canvas小游戏开发?下面通过一个例子来进行手把手教学.(如果你怀疑我的资历, A Wiz ...

  3. 一个简单的基于canvas小游戏

    GDOI2016是我的退役战,不知道是题目画风不对,还是我自身的问题. 不过没关系啦,反正已经进过一次队OI生涯就没有什么遗憾的了. 这几天尝试着去做了个所谓的html5小游戏,略显简陋,但还是写个总 ...

  4. 简单的猜数字小游戏--Python

    猜数字小游戏: #coding=utf-8 import random   answer =random.randint(1,100) #生成随机数 n=int (input("Please ...

  5. UIDynamicBehavior的简单使用:接球小游戏

    一.概念扩充: 1.在开发中,我们可以使用UIKit中提供的仿真行为,实现与现实生活中类似的物理仿真动画,UIKit动力学最大的特点是将现实世界动力驱动的动画引入了UIKit,比如重力,铰链连接,碰撞 ...

  6. JavaScript实践-简单的贪吃蛇小游戏

    实现逻辑: //获取Html中的格子(行,列) //建立数组存储所有格子(x,y) //建立数组用于存储蛇身(x,y) //生成随机坐标(x,y)的函数 //随机创建蛇身并存储到蛇身数组 //创建食物 ...

  7. JavaScript小游戏实例:简单的键盘练习

    键盘是一种常用的输入设备,灵活熟练地使用键盘进行输入是计算机用户需掌握的一门基本功.下面我们编写一个简单的键盘练习游戏. 1.刺破气泡交互式小动画 在编写简单的键盘练习游戏之前,先设计一个简单地刺破气 ...

  8. 拼图小游戏之计算后样式与CSS动画的冲突

    先说结论: 前几天写了几个非常简单的移动端小游戏,其中一个拼图游戏让我郁闷了一段时间.因为要获取每张图片的位置,用`<style>`标签写的样式,直接获取计算后样式再用来交换位置,结果就悲 ...

  9. 制作动画或小游戏——CreateJS事件(二)

    在Canvas中如果要添加事件,就需要计算坐标来模拟各种事件,而EaselJS中已经封装好了多个事件,只需调用即可. 一.事件 1)点击 事件是绑定在Shape类中的,click事件与DOM中的意思是 ...

随机推荐

  1. 【Concurrency-ScheduledExecutorService】

    简介 线程池执行者在ThreadPoolExecutor的基础上给我们提供了延时(delay)执行和周期执行的功能.性能会优于Timer包. 继承结构 参考: ThreadPoolExecutor E ...

  2. python-文件锁

    文件锁(fcntl) fcntl这个模块是Python自带的,但Windows没有,可以手工下载fcntl.py文件,然后保存到python的Lib目录下 锁类型(fcntl.flock函数的第二个参 ...

  3. Spring+Mybatis+SpringMVC+Maven+MySql搭建实例(转)

    http://blog.csdn.net/evankaka/article/details/48785513?spm=5176.100239.blogcont28591.10.9Fdj9R

  4. python基础(五)

    一.os模块 import os# os.rename(old,new)#重命名# os.remove(f)#删除文件 # os.mkdir('china/beijing') #创建文件夹# os.m ...

  5. 19.python的序列化

    自定制序列化 import json from datetime import datetime class JsonCustomEncoder(json.JSONEncoder): #自定制序列化类 ...

  6. Mybatis根据List批量查询List结果

    https://blog.csdn.net/qq_36688928/article/details/82783392

  7. 学习笔记CB001:NLTK库、语料库、词概率、双连词、词典

    聊天机器人知识主要是自然语言处理.包括语言分析和理解.语言生成.机器学习.人机对话.信息检索.信息传输与信息存储.文本分类.自动文摘.数学方法.语言资源.系统评测. NLTK库安装,pip insta ...

  8. camelcase-hankerrank

    int camelcase(string s) { int cnt=0; int a; for(int i=0;i<s.size();i++) { a=s[i]; if(65<=a& ...

  9. javascript中缺少分号结尾的情况

    首先看一段代码 function* fib (max) { let a = 0 let b = 1 let n = 1 while (n < max) { yield a; [a, b] = [ ...

  10. C++——STL内存清除

    1.vector元素的清除 看代码.在vector中添加若干元素,然后clear() #include<iostream> #include<list> #include< ...