C# 之 380行代码写出命令行版-2048
【摘要】 C# 之 380行代码写出命令行版2048
游戏规则:
游戏的规则很简单,你需要控制所有方块向同一个方向运动,两个相同数字方块撞在一起之后合并成为他们的和,每次操作之后会随机生成一个2或者4,最终得到一个“2048”的方块就算胜利了。
主要逻辑:
4*4的数组, 然后遍历里面的元素,统计所有的0,放到一个list里面,然后Random.next(0,list...
C# 之 380行代码写出命令行版2048
游戏规则:
游戏的规则很简单,你需要控制所有方块向同一个方向运动,两个相同数字方块撞在一起之后合并成为他们的和,每次操作之后会随机生成一个2或者4,最终得到一个“2048”的方块就算胜利了。
主要逻辑:
- 4*4的数组, 然后遍历里面的元素,统计所有的0,放到一个list里面,然后Random.next(0,list.count)随机一个赋成2.
- 循环开始,初始化命令行.
- 键盘输入上下左右 对应四种操作的函数 操作之后先遍历一下有没有空格 如果有就继续 没有空格还得再判断一下能不能再动了 如果不能就死了
- 如果有任何一个元素是2048 即获胜
看看效果:
using System;
using System;
using System.Collections.Generic;
// 4*4的数组, 然后遍历里面的元素,统计所有的0,放到一个list里面,然后Random.next(0,list.count)随机一个赋成2.
// 循环开始.
// 键盘输入上下左右 对应四种操作的函数 操作之后先遍历一下有没有空格 如果有就继续 没有空格还得再判断一下能不能再动了 如果不能就死了
// 如果有任何一个元素是2048 即获胜
namespace CSharp_2048
{ class Program { static void Main(string[] args) { Class2048 class2048 = new Class2048(); class2048.GameStart(); } /// <summary> /// 游戏类2048 /// </summary> class Class2048 { public int[,] arr = new int[4, 4]; public Random rd = new Random(); public List<CoordinateTools> listOfCoo = new List<CoordinateTools>(); /// <summary> /// 输出当前状态 /// </summary> public void Output() { string str = " "; Console.Clear(); Console.WriteLine("┏┉┉┉┉┉┉┉┉┳┉┉┉┉┉┉┉┉┳┉┉┉┉┉┉┉┉┳┉┉┉┉┉┉┉┉┓"); Console.WriteLine("┋ ┋ ┋ ┋ ┋"); Console.WriteLine("┋ {0} ┋ {1} ┋ {2} ┋ {3} ┋", arr[0, 0] == 0 ? str : arr[0, 0].ToString().PadLeft(4, ' '), arr[0, 1] == 0 ? str : arr[0, 1].ToString().PadLeft(4, ' '), arr[0, 2] == 0 ? str : arr[0, 2].ToString().PadLeft(4, ' '), arr[0, 3] == 0 ? str : arr[0, 3].ToString().PadLeft(4, ' ')); Console.WriteLine("┋ ┋ ┋ ┋ ┋"); Console.WriteLine("┣┉┉┉┉┉┉┉┉╋┉┉┉┉┉┉┉┉╋┉┉┉┉┉┉┉┉╋┉┉┉┉┉┉┉┉┫"); Console.WriteLine("┋ ┋ ┋ ┋ ┋"); Console.WriteLine("┋ {0} ┋ {1} ┋ {2} ┋ {3} ┋", arr[1, 0] == 0 ? str : arr[1, 0].ToString().PadLeft(4, ' '), arr[1, 1] == 0 ? str : arr[1, 1].ToString().PadLeft(4, ' '), arr[1, 2] == 0 ? str : arr[1, 2].ToString().PadLeft(4, ' '), arr[1, 3] == 0 ? str : arr[1, 3].ToString().PadLeft(4, ' ')); Console.WriteLine("┋ ┋ ┋ ┋ ┋"); Console.WriteLine("┣┉┉┉┉┉┉┉┉╋┉┉┉┉┉┉┉┉╋┉┉┉┉┉┉┉┉╋┉┉┉┉┉┉┉┉┫"); Console.WriteLine("┋ ┋ ┋ ┋ ┋"); Console.WriteLine("┋ {0} ┋ {1} ┋ {2} ┋ {3} ┋", arr[2, 0] == 0 ? str : arr[2, 0].ToString().PadLeft(4, ' '), arr[2, 1] == 0 ? str : arr[2, 1].ToString().PadLeft(4, ' '), arr[2, 2] == 0 ? str : arr[2, 2].ToString().PadLeft(4, ' '), arr[2, 3] == 0 ? str : arr[2, 3].ToString().PadLeft(4, ' ')); Console.WriteLine("┋ ┋ ┋ ┋ ┋"); Console.WriteLine("┣┉┉┉┉┉┉┉┉╋┉┉┉┉┉┉┉┉╋┉┉┉┉┉┉┉┉╋┉┉┉┉┉┉┉┉┫"); Console.WriteLine("┋ ┋ ┋ ┋ ┋"); Console.WriteLine("┋ {0} ┋ {1} ┋ {2} ┋ {3} ┋", arr[3, 0] == 0 ? str : arr[3, 0].ToString().PadLeft(4, ' '), arr[3, 1] == 0 ? str : arr[3, 1].ToString().PadLeft(4, ' '), arr[3, 2] == 0 ? str : arr[3, 2].ToString().PadLeft(4, ' '), arr[3, 3] == 0 ? str : arr[3, 3].ToString().PadLeft(4, ' ')); Console.WriteLine("┋ ┋ ┋ ┋ ┋"); Console.WriteLine("┗┉┉┉┉┉┉┉┉┻┉┉┉┉┉┉┉┉┻┉┉┉┉┉┉┉┉┻┉┉┉┉┉┉┉┉┛");
Console.WriteLine("\n<<命令行版2048>> 请按上下左右(↑←↓→)方向键操作"); } /// <summary> /// 遍历非零元素 随机把一个赋为2 /// </summary> public void Add2() { listOfCoo.Clear(); for (int i = 0; i < 4; i++) //遍历所有零元素的坐标 { for (int j = 0; j < 4; j++) { if (arr[i, j] == 0) { CoordinateTools coo = new CoordinateTools(i, j); //把遍历到的坐标 当成参数 实例化 listOfCoo.Add(coo); //把实例化的结果add到list里 } } } if (listOfCoo.Count == 0) //如果列表里一个元素都没存进来 说明表里没有空格了 直接退出 { return; } int cooPlus = rd.Next(0, listOfCoo.Count); //从表里随机取一个位置
arr[listOfCoo[cooPlus].x, listOfCoo[cooPlus].y] = 2; // 把这个位置赋值改写为2 } /// <summary> /// 游戏开始 /// </summary> public void GameStart() { Add2(); Add2(); Output(); while (true) { bool flag = false; //用于遍历检测按下按键之后和之前有没有区别用的bool型变量 foreach (int item in arr) //胜利条件 遍历 { if (item == 2048) { Console.WriteLine("\n(ノ´▽`)ノ♪ ------ 游戏胜利 ------ (ノ´▽`)ノ♪"); Last(); } } int[,] arrtmp = new int[4, 4]; //这是用于检测按下按键之后和之前有没有区别用的备份数组
for (int i = 0; i < 4; i++) //遍历给备份数组赋值 { for (int j = 0; j < 4; j++) { arrtmp[i, j] = arr[i, j]; } }
ConsoleKeyInfo info = Console.ReadKey(true); //选择功能 switch (info.Key) { case ConsoleKey.UpArrow: MoveUp(); break; case ConsoleKey.DownArrow: MoveDown(); break; case ConsoleKey.LeftArrow: MoveLeft(); break; case ConsoleKey.RightArrow: MoveRight(); break; }
for (int i = 0; i < 4; i++) //遍历检测 按下方向键前的状态 和 按下方向键之后的状态是不是完全一样的 { for (int j = 0; j < 4; j++) { if (arrtmp[i, j] != arr[i, j]) { flag = true; //一旦有任意一个元素在之前之后不一样 那么falg改为TRUE } } } if (flag) { Add2(); //如果falg是true 说明变了, 如果变了 就刷一个2出来, 反之就什么也不干 } Output(); //输出
if (!End()) //检测按下方向键之后死没死 { Console.WriteLine("\n(;´д`)ゞ ------ 游戏失败 ------ (;´д`)ゞ"); Last(); } } }
#region 核心逻辑 --> 向四个方向移动的控制 //向下 非0数向下移动,遇到非0数,相同则累加,不同则保存到当前位置 public void MoveDown() { for (int j = 0; j < 4; j++) { for (int i = 2; i >= 0; i--) { if (arr[i, j] == 0) continue; for (int k = i + 1; k < 4; k++) { if (arr[k, j] != 0) { if (arr[i, j] == arr[k, j]) { arr[k, j] += arr[i, j]; arr[i, j] = 0; break; } else if (arr[i, j] != arr[k, j] && k - 1 != i) { arr[k - 1, j] = arr[i, j]; arr[i, j] = 0; break; } else if (arr[i, j] != arr[k, j] && k - 1 == i) { break; } } if (k == 3) { arr[k, j] = arr[i, j]; arr[i, j] = 0; break; } } } } } //向上移动: 先把数组上下翻转 然后向下移动 移动完了再翻转回来 public void MoveUp() { for (int i = 0; i < 2; i++) { for (int j = 0; j < 4; j++) { int tmp = 0; tmp = arr[i, j]; arr[i, j] = arr[3 - i, j]; arr[3 - i, j] = tmp; } } MoveDown(); for (int i = 0; i < 2; i++) { for (int j = 0; j < 4; j++) { int tmp = 0; tmp = arr[i, j]; arr[i, j] = arr[3 - i, j]; arr[3 - i, j] = tmp; } } } //向左移动 public void MoveLeft() { for (int i = 0; i < 4; i++) { for (int j = 1; j < 4; j++) { if (arr[i, j] == 0) continue; for (int k = j - 1; k >= 0; k--) { if (arr[i, k] != 0) { if (arr[i, j] == arr[i, k]) { arr[i, k] += arr[i, j]; arr[i, j] = 0; break; } else if (arr[i, j] != arr[i, k] && k + 1 != j) { arr[i, k + 1] = arr[i, j]; arr[i, j] = 0; break; } else if (arr[i, j] != arr[i, k] && k + 1 == j) { break; } } if (k == 0) { arr[i, k] = arr[i, j]; arr[i, j] = 0; break; } }
} } } //向右移动: 先把数组左右翻转 然后向左移动 移动完了再翻转回来 public void MoveRight() { for (int j = 0; j < 2; j++) { for (int i = 0; i < 4; i++) { int tmp = 0; tmp = arr[i, j]; arr[i, j] = arr[i, 3 - j]; arr[i, 3 - j] = tmp; } } MoveLeft(); for (int j = 0; j < 2; j++) { for (int i = 0; i < 4; i++) { int tmp = 0; tmp = arr[i, j]; arr[i, j] = arr[i, 3 - j]; arr[i, 3 - j] = tmp; } }
} #endregion /// <summary> /// 判断是否失败 /// </summary> /// <returns></returns> public bool End() { //遍历数组 有任何一个空元素都说明不可能死 foreach (int item in arr) { if (item == 0) return true; }
//从2开始到2048进行遍历 目的是检测 每一个数字 他上下左右相邻有没有和他一样的数字 for (int num = 2; num <= 2048; num *= 2) {
List<CoordinateTools> listOfget2 = new List<CoordinateTools>();
for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (arr[i, j] == num) { CoordinateTools coo = new CoordinateTools(i, j); //先把所有值为NUM的元素的下标 存到list里 listOfget2.Add(coo); } } }
if (listOfget2 == null) //如果这个list 是空的 就说明当前表里没有num 回到FOR继续 { continue; }
//从列表里的第一个元素开始 (每一个元素存的都是一组下标x,y) foreach (CoordinateTools item in listOfget2) { foreach (CoordinateTools item2 in listOfget2) {
if ((item.y == item2.y && Math.Abs(item.x - item2.x) == 1) || (item.x == item2.x && Math.Abs(item.y - item2.y) == 1)) //判断 同一行的是不是列坐标差的绝对值是1 同一列的是不是行坐标差的绝对值是1 { return true; //如果有一个 就不用再循环了 肯定没死 } } } } return false; //全遍历完了还一个TURE都没有 就说明已经死了 返回false } /// <summary> /// 胜利或失败之后的选择 /// </summary> public void Last() { Console.WriteLine("\n输入X退出 输入R重新开始\n"); while (true) { string str = Console.ReadLine(); if (str == "x") { Environment.Exit(0); } //重新开始 --> 初始化 if (str == "r") { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { arr[i, j] = 0; } } GameStart(); } } } } /// <summary> /// 工具类 用于存储搜索到的数组的下标 /// </summary> class CoordinateTools { public int x { set; get; } public int y { set; get; } public CoordinateTools(int i, int j) { this.x = i; this.y = j; } } }
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256
- 257
- 258
- 259
- 260
- 261
- 262
- 263
- 264
- 265
- 266
- 267
- 268
- 269
- 270
- 271
- 272
- 273
- 274
- 275
- 276
- 277
- 278
- 279
- 280
- 281
- 282
- 283
- 284
- 285
- 286
- 287
- 288
- 289
- 290
- 291
- 292
- 293
- 294
- 295
- 296
- 297
- 298
- 299
- 300
- 301
- 302
- 303
- 304
- 305
- 306
- 307
- 308
- 309
- 310
- 311
- 312
- 313
- 314
- 315
- 316
- 317
- 318
- 319
- 320
- 321
- 322
- 323
- 324
- 325
- 326
- 327
- 328
- 329
- 330
- 331
- 332
- 333
- 334
- 335
- 336
- 337
- 338
- 339
- 340
- 341
- 342
- 343
- 344
- 345
- 346
- 347
- 348
- 349
- 350
- 351
- 352
- 353
- 354
- 355
- 356
- 357
- 358
- 359
- 360
- 361
- 362
- 363
- 364
- 365
- 366
- 367
- 368
- 369
- 370
- 371
- 372
- 373
- 374
- 375
- 376
- 377
- 378
- 379
- 380
文章来源: czhenya.blog.csdn.net,作者:陈言必行,版权归原作者所有,如需转载,请联系作者。
原文链接:czhenya.blog.csdn.net/article/details/105009540
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)