曾經使用C#控制台應用程序寫的一個2048,現在翻出來回顧一下

- Box類是2048中每一個小格子的相關信息,包括格子的橫縱坐標、格子的值和格子是否剛合並這些信息。
- Grid類是網格的相關信息,包括網格的長寬(默認是4X4,也可以改成其他形式的),分數等。
- Manager2048類是個大雜燴的類,寫的很亂,什么亂七八糟的方法都丟在了里面。
=================================賊好看的分割線=============
Program.CS
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace _031_test 8 { 9 /// <summary> 10 /// 2048 11 /// </summary> 12 class Program 13 { 14 static void Main(string[] args) 15 { 16 Manager2048 m2048 = new Manager2048(); 17 m2048.Strat(); 18 m2048.Control(); 19 20 21 Console.ReadLine(); 22 } 23 } 24 }
Box.CS
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace _031_test 8 { 9 /// <summary> 10 /// 格子 11 /// </summary> 12 class Box 13 { 14 //格子的坐標 15 int row; 16 int col; 17 public int Row { get { return row; } } 18 public int Col { get { return col; } } 19 //格子的值 20 public int Value { get; set; } 21 //是否已經合並 22 public bool IsMerge { get; set; } 23 24 public Box(int row,int col) 25 { 26 this.row = row; 27 this.col = col; 28 //初始化默認值為0 29 this.Value = 0; 30 this.IsMerge = false; 31 } 32 33 34 } 35 }
Grid.CS
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.IO; 7 8 namespace _031_test 9 { 10 /// <summary> 11 /// 網格 12 /// </summary> 13 class Grid 14 { 15 //網格的長寬 16 int rows; 17 int cols; 18 public int Rows { get { return rows; } } 19 public int Cols { get { return cols; } } 20 21 public int score; 22 23 public int randomTimes = 0;//判斷游戲是否結束的標識位16結束 24 Random random; 25 //存放格子對象 26 public Box[,] bList; 27 //是否是第一次,第一次則出現兩個數,否則只出現一個數 28 bool isFirst = true; 29 30 public Grid(int rows, int cols) 31 { 32 this.random = new Random(); 33 this.rows = rows < 4 ? 4 : rows; 34 this.cols = cols < 4 ? 4 : cols; 35 bList = new Box[rows, cols]; 36 } 37 38 //初始化 39 public void InitGrid() 40 { 41 //對網格中的每一個格子進行初始化,並將每一個格子對象存入bList中 42 for (int i = 0; i < bList.GetLength(0); i++) 43 { 44 for (int j = 0; j < bList.GetLength(1); j++) 45 { 46 Box box = new Box(i, j); 47 bList[i, j] = box; 48 } 49 } 50 RandomNum(); 51 } 52 /////////////////////////////////// 53 //隨機---包括生成的數字和位置 54 public void RandomNum() 55 { 56 //count表示要生成的數字的個數,進行判斷,初始化時候生成兩個,否則就一個 57 int count; 58 if (isFirst) { count = 2; isFirst = false; } 59 else count = 1; 60 61 int i = 0; 62 while (i < count) 63 { 64 //隨機出現數字的下標 65 int r = random.Next(0, rows); 66 int c = random.Next(0, cols); 67 //若隨機到的位置已經有值了,則返回重新隨機 68 if (bList[r, c].Value != 0) continue; 69 //隨機2和4 出現幾率 80% 20% 70 int valuePercent = random.Next(1, 11); 71 //將出現的值 72 int value; 73 if (valuePercent < 9) value = 2; 74 else value = 4; 75 bList[r, c].Value = value; 76 i++; 77 //當randomTimes到16時說明所有格子都滿了 78 randomTimes++; 79 } 80 } 81 82 //顯示游戲界 83 public void DisPlay() 84 { 85 Console.WriteLine("==============================="); 86 for (var i = 0; i < bList.GetLength(0); i++) 87 { 88 for (var j = 0; j < bList.GetLength(1); j++) 89 { 90 Console.Write(bList[i, j].Value + "\t"); 91 } 92 Console.WriteLine("\n"); 93 } 94 Console.WriteLine("==============================="); 95 Console.WriteLine("當前分數:" + score + "歷史最高:" + Int32.Parse(File.ReadAllText("score.txt"))); 96 } 97 98 99 100 } 101 }
Manager2048.CS
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.IO; 7 8 namespace _031_test 9 { 10 /// <summary> 11 /// 控制器 12 /// </summary> 13 class Manager2048 14 { 15 Grid g; 16 17 public Manager2048() 18 { 19 g = new Grid(4, 4); 20 } 21 22 //開始游戲 23 24 public void Strat() 25 { 26 g.InitGrid(); 27 g.DisPlay(); 28 Console.WriteLine("游戲開始,請直接使用方向鍵進行操作"); 29 } 30 31 public void Control() 32 { 33 while (true) 34 { 35 //ConsoleKeyInfo可以直接接受一個字符不需要再按下回車鍵確認 36 ConsoleKeyInfo keyInfo = Console.ReadKey(); 37 switch (keyInfo.Key) 38 { 39 case ConsoleKey.UpArrow: Up(); break; 40 case ConsoleKey.DownArrow: Down(); break; 41 case ConsoleKey.LeftArrow: Left(); break; 42 case ConsoleKey.RightArrow: Right(); break; 43 default: Console.WriteLine("按錯了"); break; 44 } 45 if (g.randomTimes==g.Rows*g.Cols&&!CanWeMergeInFull()) 46 { 47 Console.WriteLine("游戲結束"); 48 break; 49 } 50 } 51 } 52 53 public void Up() 54 { 55 bool ismove=false; 56 //遍歷每一個box,檢測該box是否要移動 57 for (int i = 1; i < g.bList.GetLength(0); i++)//向上移動不需要考慮第一行的上移,所以直接i=1 58 { 59 for (int j = 0; j < g.bList.GetLength(1); j++) 60 { 61 //如果該box值不是0,說明該box需要移動,否則繼續遍歷下一個box 62 if (g.bList[i, j].Value != 0) 63 { 64 int temp = g.bList[i, j].Value; 65 //從該box的上一行開始一直遍歷到最頂上 66 int k = i - 1; 67 while (k >= 0) 68 { 69 if (g.bList[k, j].Value != 0 || k == 0) break; 70 else k--; 71 } 72 //如果碰到了和要移動的box值一樣的box,就要把他們合並(IsMerge:當這個box是這一輪合並來的box時,則不能合並) 73 if (temp == g.bList[k, j].Value && g.bList[k, j].IsMerge==false) 74 { 75 g.bList[i, j].Value = 0; 76 g.bList[k, j].Value = temp * 2; 77 g.score += temp * 2; 78 if (g.score > Int32.Parse(File.ReadAllText("score.txt"))) 79 { 80 File.WriteAllText("score.txt", g.score.ToString()); 81 } 82 g.bList[k, j].IsMerge = true; 83 g.randomTimes--; 84 ismove = true; 85 } 86 else if (temp == g.bList[k, j].Value && g.bList[k, j].IsMerge==true) 87 { 88 g.bList[i, j].Value = 0; 89 g.bList[k + 1, j].Value = temp; 90 //i=k+1表示該box並沒有移動 91 if (i == k + 1) ismove = false; 92 else ismove = true; 93 } 94 //值不一樣的時候,就把要移動的box放到這個box下面去 95 else if (g.bList[k, j].Value != 0) 96 { 97 g.bList[i, j].Value = 0; 98 g.bList[k + 1, j].Value = temp; 99 if (i == k + 1) ismove = false; 100 else ismove = true; 101 } 102 //這種情況是遍歷到最頂行的box且該box為0時,直接把要動的box移到這 103 else 104 { 105 g.bList[i, j].Value = 0; 106 g.bList[k, j].Value = temp; 107 if (i == k) ismove = false; 108 else ismove = true; 109 } 110 } 111 } 112 } 113 if (ismove && !IsFull()) g.RandomNum();//當所有格子都滿了時就不隨機生成數字 114 else Console.WriteLine("該方向無法移動"); 115 ResetIsMerge();//重置所有box的合並狀態為false 116 g.DisPlay(); 117 } 118 119 public void Down() 120 { 121 bool ismove = false; 122 //錯誤寫法:for (int i = 0; i < g.bList.GetLength(0) - 1; i++) 123 //以上寫法會導致上層的數先被遍歷從而導致先移動完畢,所以要從最后一個數開始遍歷 124 for (int i = g.bList.GetLength(0) - 2; i >= 0; i--) 125 { 126 for (int j = g.bList.GetLength(1) - 1; j >= 0; j--) 127 { 128 if (g.bList[i, j].Value != 0) 129 { 130 int temp = g.bList[i, j].Value; 131 int k = i + 1; 132 while (k <= g.bList.GetLength(0) - 1) 133 { 134 if (g.bList[k, j].Value != 0 || k == g.bList.GetLength(0) - 1) break; 135 else k++; 136 } 137 if (temp == g.bList[k, j].Value && g.bList[k, j].IsMerge == false) 138 { 139 g.bList[i, j].Value = 0; 140 g.bList[k, j].Value = temp * 2; 141 g.bList[k, j].IsMerge = true; 142 g.score += temp * 2; 143 if (g.score > Int32.Parse(File.ReadAllText("score.txt"))) 144 { 145 File.WriteAllText("score.txt", g.score.ToString()); 146 } 147 g.randomTimes--; 148 ismove = true; 149 } 150 else if (temp == g.bList[k, j].Value && g.bList[k, j].IsMerge == true) 151 { 152 g.bList[i, j].Value = 0; 153 g.bList[k - 1, j].Value = temp; 154 if (i == k - 1) ismove = false; 155 else ismove = true; 156 } 157 else if (g.bList[k, j].Value != 0) 158 { 159 g.bList[i, j].Value = 0; 160 g.bList[k - 1, j].Value = temp; 161 if (i == k - 1) ismove = false; 162 else ismove = true; 163 } 164 else 165 { 166 g.bList[i, j].Value = 0; 167 g.bList[k, j].Value = temp; 168 if (i == k) ismove = false; 169 else ismove = true; 170 } 171 } 172 } 173 } 174 if (ismove && !IsFull()) g.RandomNum(); 175 else Console.WriteLine("該方向無法移動"); 176 ResetIsMerge(); 177 g.DisPlay(); 178 } 179 180 public void Left() 181 { 182 bool ismove = false; 183 for (int i = 0; i < g.bList.GetLength(0); i++) 184 { 185 for (int j = 1; j < g.bList.GetLength(1); j++) 186 { 187 if (g.bList[i, j].Value != 0) 188 { 189 int temp = g.bList[i, j].Value; 190 int k = j - 1; 191 while (k >= 0) 192 { 193 if (g.bList[i, k].Value != 0 || k == 0) break; 194 else k--; 195 } 196 if (temp == g.bList[i, k].Value && g.bList[i, k].IsMerge == false) 197 { 198 g.bList[i, j].Value = 0; 199 g.bList[i, k].Value = temp * 2; 200 g.score += temp * 2; 201 if (g.score > Int32.Parse(File.ReadAllText("score.txt"))) 202 { 203 File.WriteAllText("score.txt", g.score.ToString()); 204 } 205 g.bList[k, j].IsMerge = true; 206 g.randomTimes--; 207 ismove = true; 208 } 209 else if (temp == g.bList[i, k].Value && g.bList[i, k].IsMerge == true) 210 { 211 g.bList[i, j].Value = 0; 212 g.bList[i, k + 1].Value = temp; 213 if (j == k + 1) ismove = false; 214 else ismove = true; 215 } 216 else if (g.bList[i, k].Value != 0) 217 { 218 g.bList[i, j].Value = 0; 219 g.bList[i, k + 1].Value = temp; 220 if (j == k + 1) ismove = false; 221 else ismove = true; 222 } 223 else 224 { 225 g.bList[i, j].Value = 0; 226 g.bList[i, k].Value = temp; 227 if (j == k) ismove = false; 228 else ismove = true; 229 } 230 } 231 } 232 } 233 if (ismove && !IsFull()) g.RandomNum(); 234 else Console.WriteLine("該方向無法移動"); 235 ResetIsMerge(); 236 g.DisPlay(); 237 } 238 239 public void Right() 240 { 241 bool ismove = false; 242 //錯誤寫法:for (int i = 0; i < g.bList.GetLength(0) - 1; i++) 243 //以上寫法會導致上層的數先被遍歷從而導致先移動完畢,所以要從最后一個數開始遍歷 244 for (int i = g.bList.GetLength(0) - 1; i >= 0; i--) 245 { 246 for (int j = g.bList.GetLength(1) - 2; j >= 0; j--) 247 { 248 if (g.bList[i, j].Value != 0) 249 { 250 int temp = g.bList[i, j].Value; 251 int k = j + 1; 252 while (k <= g.bList.GetLength(1) - 1) 253 { 254 if (g.bList[i, k].Value != 0 || k == g.bList.GetLength(1) - 1) break; 255 else k++; 256 } 257 if (temp == g.bList[i, k].Value && g.bList[i, k].IsMerge == false) 258 { 259 g.bList[i, j].Value = 0; 260 g.bList[i, k].Value = temp * 2; 261 g.score += temp * 2; 262 if (g.score > Int32.Parse(File.ReadAllText("score.txt"))) 263 { 264 File.WriteAllText("score.txt", g.score.ToString()); 265 } 266 g.bList[k, j].IsMerge = true; 267 g.randomTimes--; 268 ismove = true; 269 } 270 else if (temp == g.bList[i, k].Value && g.bList[i, k].IsMerge == true) 271 { 272 g.bList[i, j].Value = 0; 273 g.bList[i, k - 1].Value = temp; 274 if (j == k - 1) ismove = false; 275 else ismove = true; 276 } 277 else if (g.bList[i, k].Value != 0) 278 { 279 g.bList[i, j].Value = 0; 280 g.bList[i, k - 1].Value = temp; 281 if (j == k - 1) ismove = false; 282 else ismove = true; 283 } 284 else 285 { 286 g.bList[i, j].Value = 0; 287 g.bList[i, k].Value = temp; 288 if (j == k) ismove = false; 289 else ismove = true; 290 } 291 } 292 } 293 } 294 if (ismove && !IsFull()) g.RandomNum(); 295 else Console.WriteLine("該方向無法移動"); 296 ResetIsMerge(); 297 g.DisPlay(); 298 } 299 300 //判斷網格是否已滿 301 public bool IsFull() 302 { 303 for (int i = 0; i < g.Rows; i++) 304 { 305 for (int j = 0; j < g.Cols; j++) 306 { 307 if (g.bList[i, j].Value == 0) 308 { 309 return false; 310 } 311 } 312 } 313 return true; 314 } 315 316 //重置所有box合並狀態 317 public void ResetIsMerge() 318 { 319 for (int i = 0; i < g.Rows; i++) 320 { 321 for (int j = 0; j < g.Cols; j++) 322 { 323 g.bList[i, j].IsMerge = false; 324 } 325 } 326 } 327 328 //網格滿時是否還可以繼續合並 true表示還有能合並的 329 public bool CanWeMergeInFull() 330 { 331 for (int i = 0; i < g.Rows; i++) 332 { 333 for (int j = 0; j < g.Cols; j++) 334 { 335 //檢測上方向 336 if (i - 1 >= 0 && g.bList[i, j].Value == g.bList[i - 1, j].Value) 337 { 338 return true; 339 } 340 //檢測下方向 341 if (i + 1 < g.Rows && g.bList[i, j].Value == g.bList[i + 1, j].Value) 342 { 343 return true; 344 } 345 //檢測左方向 346 if (j - 1 >= 0 && g.bList[i, j].Value == g.bList[i, j - 1].Value) 347 { 348 return true; 349 } 350 //檢測右方向 351 if (j + 1 < g.Cols && g.bList[i, j].Value == g.bList[i, j + 1].Value) 352 { 353 return true; 354 } 355 } 356 } 357 return false; 358 } 359 360 } 361 }
=================================賊好看的分割線=============
最終效果:


