紙牌游戲有很多種玩法,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點這個小游戲中用不上,只是在剪裁紙牌圖片時需要.紙牌的圖片如下:
整 個一副牌都在一個圖片中,這兩個枚舉值等於提供了行列坐標,剪裁圖片時更方便些,用法在後面的代碼中,抽象方法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中的代碼,邏輯也比較簡單,水平所限程式也算完成了,不足之處還望高手能夠指出。