导航

WinForm-简单21点纸牌小游戏

Posted on 2018-09-14 19:39  chonglang  阅读(2858)  评论(0编辑  收藏  举报

纸牌游戏有很多种玩法,C#代码写的纸牌游戏,网上也能找到不少,从中也能学习到不少知识,自己动手也写一个,算是记录下学习过程吧.

纸牌21点的玩法也比较简单,就是看谁手中的所有牌相加是21点,或是离21点的数字最近,最大者赢.照着这样思路开始编写代码.

牌面A到10按牌面数字算点数,J,Q,K,大小王都算10点;

定义一个纸牌父类PKFather

 1 public enum PokerColour
 2     {
 3         
 4         Diamond,//方块=0
 5         Club,   //梅花=1
 6         Heart,  //红桃=2
 7         Spade,  //黑桃=3
 8         Wang,
 9     }
10     public enum Rank //牌面点数
11     {
12         One = 1,
13         Two,
14         Three,
15         Four,
16         Five,
17         Six,
18         Seven,
19         Eight,
20         Nine,
21         Ten,
22         Jack,
23         Queen,
24         King,
25         XWang,
26         DWang,
27     }
28     public abstract class PKFather
29     {
30         public int X { get; set; }
31         public int Y { get; set; }
32         public int Width { get; set; }
33         public int Height { get; set; }
34         public Rank Rank { get; set; }//牌面点数
35         public PokerColour PkColour { get; set; }//牌面花色;红桃,黑桃,方片,梅花;
36         
37         public PKFather(int x,int y,int width,int height,Rank rank,PokerColour pkColour)
38         {
39             this.X = x;
40             this.Y = y;
41             this.Width = width;
42             this.Height = height;
43             this.Rank = rank;
44             this.PkColour = pkColour;
45             
46         }
47         public abstract void Draw(Graphics g);
48     }

父类中定义了两个枚举,Rank用做牌面点数,PokerColour用做牌的花色,其实牌的花色在21点这个小游戏中用不上,只是在剪裁纸牌图片时需要.纸牌的图片如下:

整 个一副牌都在一个图片中,这两个枚举值等于提供了行列坐标,剪裁图片时更方便些,用法在后面的代码中,抽象方法Draw在子类中实现。

 1 class RPoker:PKFather
 2     {
 3         Image image = Resources.card;//图片在资源文件中
 4         public RPoker(int x, int y, int width, int height, Rank rank, PokerColour pkcolour)
 5             : base(x, y, width, height, rank,pkcolour)
 6         {
 7 
 8         }
 9 
10         public override void Draw(System.Drawing.Graphics g)
11         {
12             Rectangle rect = new Rectangle(this.X, this.Y, Width, Height);//要裁切图片的位置大小
13             switch (this.PkColour)
14             {
15                 case PokerColour.Diamond:
16                     g.DrawImage(image, rect, new Rectangle(((int)Rank - 1) * Width, (int)(PkColour + 3) * Height, Width, Height), GraphicsUnit.Pixel);
17                     break;
18                 case PokerColour.Club:
19                     g.DrawImage(image, rect, new Rectangle(((int)Rank - 1) * Width, (int)(PkColour + 1) * Height, Width, Height), GraphicsUnit.Pixel);
20                     break;
21                 case PokerColour.Heart:
22                     g.DrawImage(image, rect, new Rectangle(((int)Rank - 1) * Width, (int)(PkColour - 1) * Height, Width, Height), GraphicsUnit.Pixel);
23                     break;
24                 case PokerColour.Spade:
25                     g.DrawImage(image, rect, new Rectangle(((int)Rank - 1) * Width, (int)(PkColour - 3) * Height, Width, Height), GraphicsUnit.Pixel);
26                     break;
27                 case PokerColour.Wang:
28                     g.DrawImage(image, rect, new Rectangle(((int)Rank - 14) * Width, (int)PkColour * Height, Width, Height), GraphicsUnit.Pixel);
29                     break;
30                 default:
31                     break;
32             }
33             
34         }
35     }

子类RPoker继承自PKFather,实现抽象方法Draw,用来绘制具体的纸牌。将纸牌的图片加入项目的资源文件步骤是,在解决方案资源管理器中,选中项目,依次点开 Properties->Resources.resx (双击该文件)->在打开的窗口中选菜单"添加资源"->添加现有文件;选中要加入的图片,点确定就成了。更简便的方法是当双击Resources.resx文件在vs中打开后,直接拖入图片,就可完成添加图片的步骤。Image image = Resources.card;将图片资源赋值给image,这样在后面的代码中,就可以对image中的纸牌图片进行剪裁,提取了。

生成54张牌

 1 private void GetCard()
 2         {
 3             for (int j = 0; j <= 4; j++)
 4             {
 5                 switch (j)
 6                 {
 7                     case 0:
 8                         for (int k = 1; k < 14; k++)
 9                         {
10                             allCard.Add(new RPoker(71 * k, j, 71, 96, (Rank)k, (PokerColour)j));
11                         }
12                         break;
13                     case 1:
14                         for (int k = 1; k < 14; k++)
15                         {
16                             allCard.Add(new RPoker(71 * k, j * 96, 71, 96, (Rank)k, (PokerColour)j));
17                         }
18                         break;
19                     case 2:
20                         for (int k = 1; k < 14; k++)
21                         {
22                             allCard.Add(new RPoker(71 * k, j * 96, 71, 96, (Rank)k, (PokerColour)j));
23                         }
24                         break;
25                     case 3:
26                         for (int k = 1; k < 14; k++)
27                         {
28                             allCard.Add(new RPoker(71 * k, j * 96, 71, 96, (Rank)k, (PokerColour)j));
29                         }
30                         break;
31                     case 4:
32                         for (int k = 1; k < 3; k++)
33                         {
34                             allCard.Add(new RPoker(71 * k, j * 96, 71, 96, (Rank)k + 13, (PokerColour)j));
35                         }
36                         break;
37                     default:
38                         break;
39                 }
40             }
41         }

其中固定的数值,都是在整张图片提取成单张牌时具体尺寸

洗牌代码;

           // 定义随机数  
            Random random = new Random();
            // 从数组的最后一个数开始递减  
            for (int i = allCard.Count - 1; i > 0; i--)
            {
                // 随机下标  
                int index = random.Next(0, i);
                // 随机出来的数与最后位置的数交换  
                RPoker temp = allCard[i];
                allCard[i] = allCard[index];
                allCard[index] = temp;
            }

这种随机打乱的洗牌方法可以有很多种,找到合适的方法就可。

 两个类完成后,其余的代码都写到到界面Form中,运行后的界面:

主要记录代码编写过程,界面就简单来了。

  1 /// <summary>
  2         /// allCard所有54张牌
  3         /// </summary>
  4         private List<RPoker> allCard = new List<RPoker>();//所有牌
  5         private int TopCard;//计数
  6         private int computerNumber;//计算机牌张数
  7 
  8         private int playerNumber;//玩家牌张数
  9         private int computerCount;//计算机牌点数
 10         private int playerCount;//玩家牌点数
 11 
 12  private void Form1_Load(object sender, EventArgs e)
 13         {
 14             
 15             GetCard();
 16             Shuffle();
 17         }
 18  private void button2_Click(object sender, EventArgs e)//玩家要牌
 19         {
 20             allCard[TopCard].X = 200 + 25 * playerNumber;
 21             allCard[TopCard].Y = 200;
 22             allCard[TopCard].Draw(this.CreateGraphics());
 23             if (allCard[TopCard].Rank > Rank.Ten)
 24             {
 25                 playerCount += 10;
 26                 playerNumber += 1;
 27             }
 28             else
 29             {
 30                 playerCount += (int)allCard[TopCard].Rank;
 31                 playerNumber += 1;
 32             }
 33             TopCard++;
 34             if (TopCard >= 54)
 35             {
 36                 Shuffle();
 37                 MessageBox.Show("新的一副牌!!");
 38             }
 39             label2.Text = playerCount.ToString();
 40             label2.Refresh();
 41             label3.Text = playerNumber.ToString();
 42             label3.Refresh();
 43             if (playerCount > 21)
 44             {
 45                 MessageBox.Show("玩家Player lose!");
 46                 button1.Enabled = true;
 47                 button2.Enabled = false;
 48                 button3.Enabled = false;
 49 
 50             }
 51         }
 52 
 53         private void button1_Click(object sender, EventArgs e)//开始游戏
 54         {
 55             this.Refresh();
 56             button1.Enabled = false;
 57             label1.Text = "";
 58             label2.Text = "";
 59             label1.Refresh();
 60             label2.Refresh();
 61             computerNumber = 0;
 62             playerNumber = 0;
 63             playerCount = 0;
 64             computerCount = 0;
 65             //画玩家第一张牌
 66             allCard[TopCard].X = 200;
 67             allCard[TopCard].Y = 200;
 68             allCard[TopCard].Draw(this.CreateGraphics());
 69             
 70             if (allCard[TopCard].Rank > Rank.Ten)
 71             {
 72                 playerCount += 10;
 73                 playerNumber += 1;
 74             }
 75             else
 76             {
 77                 playerCount += (int)allCard[TopCard].Rank;
 78                 playerNumber += 1;
 79             }
 80             TopCard++;
 81             if (TopCard >= 54)
 82             {
 83                 Shuffle();
 84                 MessageBox.Show("新的一副牌!!");
 85             }
 86             label2.Text = playerCount.ToString();
 87             label2.Refresh();
 88             label3.Text = playerNumber.ToString();
 89             label3.Refresh();
 90 
 91             //画计算机第一张牌
 92             allCard[TopCard].X = 200;
 93             allCard[TopCard].Y = 40;
 94             allCard[TopCard].Draw(this.CreateGraphics());
 95            
 96             if (allCard[TopCard].Rank > Rank.Ten)
 97             {
 98                 computerCount += 10;
 99                 computerNumber += 1;
100             }
101             else
102             {
103                 computerCount += (int)allCard[TopCard].Rank;
104                 computerNumber += 1;
105             }
106             TopCard++;
107             if (TopCard >= 54)
108             {
109                 Shuffle();
110                 MessageBox.Show("新的一副牌!!");
111             }
112             label1.Text = computerCount.ToString();
113             label1.Refresh();
114             label4.Text = computerNumber.ToString();
115             label4.Refresh();
116 
117             //画玩家第二张牌
118             allCard[TopCard].X = 225;
119             allCard[TopCard].Y = 200;
120             allCard[TopCard].Draw(this.CreateGraphics());
121           
122             if (allCard[TopCard].Rank > Rank.Ten)
123             {
124                 playerCount += 10;
125                 playerNumber += 1;
126             }
127             else
128             {
129                 playerCount += (int)allCard[TopCard].Rank;
130                 playerNumber += 1;
131             }
132             TopCard++;
133             if (TopCard >= 54)
134             {
135                 Shuffle();
136                 MessageBox.Show("新的一副牌!!");
137             }
138             label2.Text = playerCount.ToString();
139             label2.Refresh();
140             label3.Text = playerNumber.ToString();
141             label3.Refresh();
142 
143             //画计算机第二张牌
144             allCard[TopCard].X = 225;
145             allCard[TopCard].Y = 40;
146             allCard[TopCard].Draw(this.CreateGraphics());
147            
148 if (allCard[TopCard].Rank > Rank.Ten) 149 { 150 computerCount += 10; 151 computerNumber += 1; 152 } 153 else 154 { 155 computerCount += (int)allCard[TopCard].Rank; 156 computerNumber += 1; 157 } 158 TopCard++; 159 if (TopCard >= 54) 160 { 161 Shuffle(); 162 MessageBox.Show("新的一副牌!!"); 163 } 164 label1.Text = computerCount.ToString(); 165 label1.Refresh(); 166 label4.Text = computerNumber.ToString(); 167 label4.Refresh(); 168 button2.Enabled = true; 169 button3.Enabled = true; 170 } 171 172 private void button3_Click(object sender, EventArgs e)//玩家停牌 173 { 174 //玩家停牌 175 button2.Enabled = false; 176 button3.Enabled = false; 177 ComputerPlay(); 178 } 179 private void ComputerPlay()//电脑自行要牌 180 { 181 do 182 { 183 if (computerCount < 18) 184 { 185 allCard[TopCard].X = 200 + 25 * computerNumber; 186 allCard[TopCard].Y = 40; 187 allCard[TopCard].Draw(this.CreateGraphics()); 188 if (allCard[TopCard].Rank > Rank.Ten) 189 { 190 computerCount += 10; 191 computerNumber += 1; 192 } 193 else 194 { 195 computerCount += (int)allCard[TopCard].Rank; 196 computerNumber += 1; 197 } 198 TopCard++; 199 } 200 else 201 { 202 break; 203 } 204 } while (true); 205 label1.Text = computerCount.ToString(); 206 label1.Refresh(); 207 label4.Text = computerNumber.ToString(); 208 label4.Refresh(); 209 if (computerCount <= 21) 210 { 211 if (playerCount > computerCount) 212 { 213 MessageBox.Show("玩家Player win!"); 214 } 215 else 216 { 217 MessageBox.Show("电脑 win!"); 218 } 219 } 220 else 221 { 222 MessageBox.Show("玩家Player win!"); 223 } 224 button1.Enabled = true; 225 button2.Enabled = false; 226 button3.Enabled = false; 227 }

界面Form1中的代码,逻辑也比较简单,水平所限程序也算完成了,不足之处还望高手能够指出。

代码下载