服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C语言实现2048小游戏

C语言实现2048小游戏

2021-06-24 13:12毒初莱式鲨壁 C/C++

这篇文章主要为大家详细介绍了C语言实现2048小游戏,注释清晰,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了C语言实现2048游戏的具体代码,供大家参考,具体内容如下

滑块有颜色、有最高分(用到文件)

?
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
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
#include <stdio.h>
#include <stdlib.h>
#include <conio.h> /*使用getch()函数*/
#include <time.h>
#include <windows.h> /*使用Sleep()函数*/
 
void Menu();//菜单
void Rule_of_game();//游戏规则
void Begin(int max); //开始
void Table();//打印4×4方格
int Random_number1();//产生2或4的随机数
int Random_number2();//产生0、1、2、3的随机数
int Get(int *p_cnt, int score);//输入指令
void Move();//保留上一次的棋盘布局
int If_move();//判断是否移动
int Over();//判断是否结束
void Establish_game();//创建用于保存最高分的文件
void Write_max(int score);//向2048游戏-最高记录写入最高分
int Read_max();//读出最高分记录的文件
void Establish_file();//创建存档文件
void Write_file(int *p_cnt, int scort);//存档
int Read_file(int *p_cnt);//读档
void again();//是否继续游戏
int color(int c);//更改颜色
void box_color(int x);//不同数值对应不同颜色
 
int a[4][4] = {0};// 定义全局的二维数组
int A[4][4]; //保留上一步的棋局
char *name_max = "2048游戏-最高记录";
char *name_file = "[空白]-2048游戏";
 
int main() {
 system("mode con cols=90 lines=30");
 system("title 2048超级大大型游戏"); //程序标题
 system("color F0");//F 表示背景颜色,0表示前景颜色
 Menu();
 system("pause"); //暂停,输入任意键继续
 system("cls"); //清屏
 again(); //是否继续游戏
 return 0;
}
 
void Menu() //菜单
{
 printf("\t\t╔══════════════════════════════════════════════╗\n");
 printf("\t\t║ 欢迎使用由[空白]制作的2048超级大大型游戏 ║\n");
 printf("\t\t╟──────────────────────────────────────────────╢\n");
 printf("\t\t║请输入选项: ║\n");
 printf("\t\t║ ┌───┐ ║\n");
 printf("\t\t║ │ 1 │ 游戏规则 ║\n");
 printf("\t\t║ └───┘ ║\n");
 printf("\t\t║ ┌───┐ ║\n");
 printf("\t\t║ │ 2 │ 开始游戏 ║\n");
 printf("\t\t║ └───┘ ║\n");
 printf("\t\t║ ┌───┐ ║\n");
 printf("\t\t║ │ 3 │ 继续游戏 ║\n");
 printf("\t\t║ └───┘ ║\n");
 printf("\t\t║ ┌───┐ ║\n");
 printf("\t\t║ │ 4 │ 退出游戏 ║\n");
 printf("\t\t║ └───┘ ║\n");
 printf("\t\t╚══════════════════════════════════════════════╝\n");
 int x = 1, max = 0;
 while(x){
 switch(getch()){
 case '1':
 x = 0;
 Rule_of_game();//游戏规则
 Menu();
 break;
 case '2':
 x = 0;
 system("cls");//清屏
 Establish_game(name_file);//创建新的读档文件
 Establish_game(name_max);//创建新的保存最高记录的文件
 Begin(max); //开始游戏
 break;
 case '3':
 x = 0;
 system("cls");//清屏
 max = Read_max();//读取之前的最高记录
 Begin(max); //开始游戏
 break;
 case '4':
 exit(0);
 default:
 printf("输入了非法选项,请重新选择!\n");
 }
 }
}
 
void Rule_of_game()
{
 system("cls");//清屏
 printf("╔══════════════════════════════════════════════════════════════════════════════════╗\n");
 printf("║本游戏通过按键W、S、A、D(不区分大小写)四个键分别控制滑块上移、下移、左移和右移。║\n");
 printf("║滑块移动的过程中,如有相邻且相等数字的滑块将会相加,并获得相应的分数。 ║\n");
 printf("║当棋盘上的所有位置均有数字,且不能合成,则游戏结束。本游戏未设置游戏成功。 ║\n");
 printf("║游戏过程中输入I即为存档并退出游戏,输入O即为读档,输入P则退出游戏。 ║\n");
 printf("║“开始游戏”则清除最高记录及存档、“继续游戏”则保存之前的最高记录,且可以读档。 ║\n");
 printf("╚══════════════════════════════════════════════════════════════════════════════════╝\n");
 system("pause");//暂停
 system("cls");//清屏
}
 
void Begin(int max)
{
 int score = 0;
 int sign = 1;
 int h, l, cnt = 0;
 int *p_cnt = &cnt;
 while(1) {
 printf("\t\t╔══════════════════════════════════════════════╗\n");
 printf("\t\t║ 欢迎使用由[空白]制作的2048超级大大型游戏 ║\n");
 printf("\t\t╟──────────────────────────────────────────────╢\n");
 printf("\t\t║移动: ┌───┐ 存档: 读档: 退出: ║\n");
 printf("\t\t║ │ W │ ║\n");
 printf("\t\t║ ┌───┼───┼───┐ ┌───┐ ┌───┐ ┌───┐ ║\n");
 printf("\t\t║ │ A │ S │ D │ │ I │ │ O │ │ P │ ║\n");
 printf("\t\t║ └───┴───┴───┘ └───┘ └───┘ └───┘ ║\n");
 printf("\t\t╚══════════════════════════════════════════════╝\n");
 while(1){
 if(sign == 1){
 h = Random_number2();
 l = Random_number2();
 if(a[h][l] == 0){
 a[h][l] = Random_number1();
 cnt ++;
 break;
 }
 }
 else{
 break;
 }
 
 }
 Table();//打印棋盘
 printf("\t\t移动的步数:%d\t当前得分:%d\n\t\t最高记录:%d\n", cnt-1, score, max);
 Move();//保留棋盘
 score += Get(p_cnt, score);//得分
 sign = If_move();//判断棋盘是否有变动
 if(Over() == 0){
 if(max < score){//打破记录
 Establish_game(name_max);//清除之前的记录
 Write_max(score);//保存此次记录
 printf("\t\t恭喜您已打破记录!\n");
 }
 break;
 }
 system("cls"); //清屏
 }
}
 
void Table()
{
 int h, l;
 for(h = 0; h < 4; h ++){
 if(h == 0){
 printf("\t\t\t┏━━━━━━┳━━━━━━┳━━━━━━┳━━━━━━┓\n");
 }
 else {
 printf("\t\t\t┣━━━━━━╋━━━━━━╋━━━━━━╋━━━━━━┫\n");
 }
 printf("\t\t\t┃ ┃ ┃ ┃ ┃\n");
 for(l = 0; l < 4; l ++){
 if(a[h][l] == 0){//如果二维数组与棋盘对应的位置为零,则不放入数据
 if(l == 0){
 printf("\t\t\t┃ ");
 }
 else {
 printf("┃ ");
 }
 }
 else{//否则放入与二维数组对应的数据
 if(l == 0){
 printf("\t\t\t┃");
 box_color(a[h][l]);//判断滑块的数值,给对应颜色
 printf("%5d ", a[h][l]);
 color(0);//恢复白色背景
 }
 else {
 printf("┃");
 box_color(a[h][l]);//判断滑块的数值,给对应颜色
 printf("%5d ", a[h][l]);
 color(0);//恢复白色背景
 }
 }
 }
 printf("┃\n");
 printf("\t\t\t┃ ┃ ┃ ┃ ┃\n");
 }
 printf("\t\t\t┗━━━━━━┻━━━━━━┻━━━━━━┻━━━━━━┛\n");
}
 
int Random_number1()/*随机生成2 or 4*/
{
 int s;
 srand( time(NULL) );
 s = ((unsigned)rand() % 2);
 s = s == 0 ? 2 : 4;
 return s;
}
 
int Random_number2()/*随机生成二维数组的下标*/
{
 int x;
 x = ((unsigned)rand() % 4);
 return x;
}
 
int Get(int *p_cnt, int score)
{
 int h, l, t, sum = 0;
 char ch;
 ch = getch();//输入字符
 switch (ch){
 /*滑块向上移动*/
 case 'w':
 case 'W':
 /*向上聚集数字*/
 for(l = 0; l < 4; l ++){
 for(t = 0; t < 4; t ++){
 for(h = 3; h > 0; h --){
 if(a[h-1][l] == 0){
 a[h-1][l] = a[h][l];
 a[h][l] = 0;
 }
 }
 }
 }
 /*竖直方向上,相邻且相同的数字相加*/
 for(l = 0; l < 4; l ++){
 for(h = 0; h < 3; h ++){
 if(a[h][l] == a[h+1][l]){
 a[h][l] += a[h+1][l];
 a[h+1][l] = 0;
 sum += a[h][l];
 }
 }
 }
 /*向上聚集数字*/
 for(l = 0; l < 4; l ++){
 for(t = 0; t < 4; t ++){
 for(h = 3; h > 0; h --){
 if(a[h-1][l] == 0){
 a[h-1][l] = a[h][l];
 a[h][l] = 0;
 }
 }
 }
 }
 break;
 case 's':
 case 'S':
 for(l = 0; l < 4; l ++){
 for(t = 0; t < 4; t ++){
 for(h = 0; h < 3; h ++){
 if(a[h+1][l] == 0){
 a[h+1][l] = a[h][l];
 a[h][l] = 0;
 }
 }
 }
 }
 for(l = 0; l < 4; l ++){
 for(h = 3; h > 0; h --){
 if(a[h][l] == a[h-1][l]){
 a[h][l] += a[h-1][l];
 a[h-1][l] = 0;
 sum += a[h][l];
 }
 }
 }
 for(l = 0; l < 4; l ++){
 for(t = 0; t < 4; t ++){
 for(h = 0; h < 3; h ++){
 if(a[h+1][l] == 0){
 a[h+1][l] = a[h][l];
 a[h][l] = 0;
 }
 }
 }
 }
 break;
 case 'a':
 case 'A':
 for(h = 0; h < 4; h ++){
 for(t = 0; t < 4; t ++){
 for(l = 3; l > 0; l --){
 if(a[h][l-1] == 0){
 a[h][l-1] = a[h][l];
 a[h][l] = 0;
 }
 }
 }
 }
 for(h = 0; h < 4; h ++){
 for(l = 0; l < 3; l ++){
 if(a[h][l] == a[h][l+1]){
 a[h][l] += a[h][l+1];
 a[h][l+1] = 0;
 sum += a[h][l];
 }
 }
 }
 for(h = 0; h < 4; h ++){
 for(t = 0; t < 4; t ++){
 for(l = 3; l > 0; l --){
 if(a[h][l-1] == 0){
 a[h][l-1] = a[h][l];
 a[h][l] = 0;
 }
 }
 }
 }
 break;
 case 'd':
 case 'D':
 for(h = 0; h < 4; h ++){
 for(t = 0; t < 4; t ++){
 for(l = 0; l < 3; l ++){
 if(a[h][l+1] == 0){
 a[h][l+1] = a[h][l];
 a[h][l] = 0;
 }
 }
 }
 }
 for(h = 0; h < 4; h ++){
 for(l = 3; l > 0; l --){
 if(a[h][l] == a[h][l-1]){
 a[h][l] += a[h][l-1];
 a[h][l-1] = 0;
 sum += a[h][l];
 }
 }
 }
 for(h = 0; h < 4; h ++){
 for(t = 0; t < 4; t ++){
 for(l = 0; l < 3; l ++){
 if(a[h][l+1] == 0){
 a[h][l+1] = a[h][l];
 a[h][l] = 0;
 }
 }
 }
 }
 break;
 case 'i':
 case 'I': //存档当前游戏格局
 Establish_file();//创建用于存档的文件
 Write_file(p_cnt, score);//调用存档函数
 break;
 case 'o':
 case 'O':
 sum = Read_file(p_cnt);//读档
 break;
 case 'p':
 case 'P':
 exit(0);//退出程序
 default:
 break;
 }
 
 return sum;
}
 
void Move()
{
 int h, l;
 for(h = 0; h < 4; h ++){
 for(l = 0; l < 4; l ++){
 A[h][l] = a[h][l];
 }
 }
}
 
int If_move()
{
 int h, l, sign = 0;
 for(h = 0; h < 4; h ++){
 for(l = 0; l < 4; l ++){
 if(a[h][l] != A[h][l]){//未进入条件框,说明滑块没有发生移动
 sign = 1;
 goto out;
 }
 }
 }
 out:
 return sign;
}
 
int Over()
{
 int over = 0;
 int h, l;
 for(h = 0; h < 4; h ++){
 for(l = 0; l < 4; l ++){
 if(a[h][l] == 0){//有空格
 over = 1;//游戏继续
 return 1;
 }
 }
 }
 if(over == 0){//没有空格
 for(h = 0; h < 3; h ++){
 for(l = 0; l < 3; l ++){
 if(a[h][l] == a[h][l+1]){
 over = 1;//游戏继续
 break;
 }
 else if(a[h][l] == a[h+1][l]){
 over = 1;//游戏继续
 break;
 }
 }
 if(over == 1){
 break;
 }
 }
 }
 return over;//游戏结束
}
 
void Establish_game()//创建文件
{
 int h;
 if(h = fopen(name_max, "wb") == NULL){ //函数fopen()返回NULL则创建文件失败
 printf("\t\t创建文件失败!程序即将自动退出 . . .\n");
 Sleep(3000);//睡眠3000毫秒,即停留3秒钟
 exit(0); //退出程序
 }
}
 
void Write_max(int score)//写入文件
{
 /*FILE *fp是指向文件的指针*/
 FILE *fp=fopen(name_max,"at+");// at+读写打开或着建立一个文本文件;允许读写。
 if(fp==NULL) //函数fopen()返回NULL则创建文件失败
 {
 printf("\t\t保存最高分失败!程序即将自动退出 . . .");
 Sleep(3000);//睡眠3000毫秒,即停留3秒钟
 exit(0); //退出程序
 }
 else{
 fprintf(fp, "%d", score);//将score的值写入*pf指向的文件内
 }
 fclose(fp);//关闭*pf指向的文件
}
 
int Read_max()//读出文件
{
 int max_score = 0;
 FILE *fp=fopen(name_max,"at+");// at+读写打开或着建立一个文本文件;允许读写。
 if(fp==NULL)
 {
 printf("\t\t读取失败!程序即将自动退出 . . .");
 Sleep(3000);//睡眠3000毫秒,即停留3秒钟
 exit(0); //退出程序
 }
 else{
 fscanf(fp, "%d", &max_score);//从*pf指向的文件内数值赋值给max_score
 }
 fclose(fp);//关闭*pf指向的文件
 
 return max_score;//返回最高记录的值
}
 
void Establish_file()//创建文件
{
 int h;
 if(h = fopen(name_file, "wb") == NULL){ //函数fopen()返回NULL则创建文件失败
 printf("\t\t创建文件失败!程序即将自动退出 . . .\n");
 Sleep(3000);//睡眠3000毫秒,即停留3秒钟
 exit(0); //退出程序
 }
}
 
void Write_file(int *p_cnt, int score)
{
 int h, l;
 FILE *fp=fopen(name_file,"at+");// at+读写打开或着建立一个文本文件;允许读写。
 if(fp==NULL)
 {
 printf("\t\t存档失败!程序即将自动退出 . . .\n");
 Sleep(3000);//睡眠3000毫秒,即停留3秒钟
 exit(0);
 }
 else{
 for(h = 0; h < 4; h ++){
 for(l = 0; l < 4; l ++){
 fprintf(fp, "%d ", a[h][l]);
 }
 }
 }
 fprintf(fp, "%d ", score);
 fprintf(fp, "%d ", *p_cnt-1);
 printf("\t\t存档成功!游戏即将自动退出 . . .\n");
 Sleep(3000); //睡眠3000毫秒,即停留3秒钟
 exit(0);
 fclose(fp);//关闭文件
}
 
int Read_file(int *p_cnt)
{
 int h, l, score = 0;
 FILE *fp=fopen(name_file,"at+");// at+读写打开或着建立一个文本文件;允许读写。
 if(fp==NULL)
 {
 printf("\t\t读档失败!程序即将自动退出 . . .\n");
 Sleep(3000); //睡眠3000毫秒,即停留3秒钟
 exit(0);
 }
 else{
 for(h = 0; h < 4; h ++){
 for(l = 0; l < 4; l ++){
 fscanf(fp, "%d ", &a[h][l]);
 }
 }
 }
 fscanf(fp, "%d ", &score);
 fscanf(fp, "%d ", p_cnt);
 fclose(fp); //关闭文件
 
 return score;
}
 
void again()//是否继续游戏
{
 printf("\t\t╔══════════════════════════════════════════════╗\n");
 printf("\t\t║ 您已失败 ║\n");
 printf("\t\t╟──────────────────────────────────────────────╢\n");
 printf("\t\t║是否继续: ║\n");
 printf("\t\t║ ┌───┐ ║\n");
 printf("\t\t║ │ 1 │ 扶我起来,我还能再来一局! ║\n");
 printf("\t\t║ └───┘ ║\n");
 printf("\t\t║ ┌───┐ ║\n");
 printf("\t\t║ │ 2 │ 不了不了,我要学习! ║\n");
 printf("\t\t║ └───┘ ║\n");
 printf("\t\t╚══════════════════════════════════════════════╝\n");
 if(_getch() == '1'){
 system("cls");//清屏
 int h, l;
 for(h = 0; h < 4; h ++){
 for(l = 0; l < 4; l ++){
 a[h][l] = 0;
 A[h][l] = 0;
 }
 }
 Menu();//回到菜单
 }
 else {
 printf("\t\t游戏结束!\n");
 }
}
 
int color(int c)
{
 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
 BACKGROUND_INTENSITY |
 BACKGROUND_BLUE |
 BACKGROUND_RED |
 BACKGROUND_GREEN |
 c);
 return 0;
}
 
void box_color(int x)
{
 switch(x){
 case 2:
 color(8);
 break;
 case 4:
 color(0);
 break;
 case 8:
 color(2);
 break;
 case 16:
 color(6);
 break;
 case 32:
 color(10);
 break;
 case 64:
 color(3);
 break;
 case 128:
 color(9);
 break;
 case 256:
 color(11);
 break;
 case 512:
 color(5);
 break;
 case 1024:
 color(13);
 break;
 case 2048:
 color(12);
 break;
 default :
 color(4);
 break;
 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/qq_41799219/article/details/79477253

延伸 · 阅读

精彩推荐