欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

WinForm-简单21点纸牌小游戏

程序员文章站 2023-04-07 08:28:54
纸牌游戏有很多种玩法,C#代码写的纸牌游戏,网上也能找到不少,从中也能学习到不少知识,自己动手也写一个,算是记录下学习过程吧. 纸牌21点的玩法也比较简单,就是看谁手中的所有牌相加是21点,或是离21点的数字最近,最大者赢.照着这样思路开始编写代码. 牌面A到10按牌面数字算点数,J,Q,K,大小王 ......

纸牌游戏有很多种玩法,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点这个小游戏中用不上,只是在剪裁纸牌图片时需要.纸牌的图片如下:

WinForm-简单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中,运行后的界面:

WinForm-简单21点纸牌小游戏

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

  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中的代码,逻辑也比较简单,水平所限程序也算完成了,不足之处还望高手能够指出。

代码下载