2048游戏设计
2048设计文档
一. 游戏玩法
2048游戏共有16个格子,初始时初始数字由2或者4构成
- 手指(或键盘控制)向一个方向滑动,所有格子会向那个方向运动
- 相同数字的两个格子,相撞时数字会相加
- 每次滑动时,空白处会随机刷新出一个数字的格子
- 当界面不可运动时(当界面全部被数字填满时),游戏结束,或当界面中最大数字是2048时,游戏胜利
- 玩家通过合并得到1个数N,这个数就计分N,比如说,2个2合并得到4,就加4分,2个1024合并得到2048,就加2048分
二. 设计思路
游戏地图和初始设置:
使用一个 4x4 的二维数组 map 来表示游戏地图
初始时,所有位置的值均为0
score 记录玩家得分,move_num 记录移动次数
随机生成数字:
- 在地图上随机选择一个空位置生成 2 或 4
- 只有在地图发生变化时才会生成新数
游戏菜单:
使用 menu() 函数显示当前的游戏状态,包括地图、得分和移动次数
提示玩家使用 W、A、S、D 键进行移动
读取玩家输入,并根据输入的方向调用相应的移动函数 ( up()、left()、down()、right() )
每个移动函数都负责处理特定方向的移动,并更新地图
移动逻辑:
移动时首先合并相同的数字,然后将非零元素向目标方向移动填补空格
change 变量用于记录地图是否发生变化,以决定是否生成新数字
游戏结束判断:
- 使用 over() 函数检查游戏是否结束
游戏结束的条件:地图没有空位且没有相邻的相同数字
若游戏结束,输出最终得分和移动次数
三. 设计细节
随机数生成:使用 rand( ) 函数生成随机位置和数字
输入处理:使用 getch( ) 函数获取用户输入,并根据输入调用相应的移动函数
移动实现:每个方向的移动函数都按照特定的顺序检查并合并相同的数字,然后移动非零元素
游戏结束检测:遍历整个地图,检查是否还有空位或相邻的相同数字
四.代码实现
1. 引入头文件
1 |
2.初始化
1 | int map[4][4] = { 0 }; // 初始化地图 |
3. 玩法实现
数组中随机位置生成2或4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16srand((unsigned)time(NULL)); //初始化随机数生成器
while (game_over)
{
int i, j, n;
if (change == 1) //只有在地图变化时才生成新数字
{
do
{
i = rand() % 4; //随机行标
j = rand() % 4; //随机列标
} while (map[i][j] != 0);
n = rand() % 2;
map[i][j] = (n == 0) ? 2 : 4; //随机赋值2或4
move_num++; //移动计数增加
} //在随机位置生成初始数字打印游戏菜单
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16void menu()
{
system("cls");
int i, j;
printf("移动:%d 得分:%d\n", move_num, score);
for (i = 0; i <= 3; i++)
{
for (j = 0; j <= 3; j++)
{
if (map[i][j] == 0) printf(" ");
else printf("%5d", map[i][j]);
}
printf("\n");
}
printf(" 按q退出游戏");
}处理移动
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20char ch = getch(); //读取键盘
change = 0;
switch (ch)
{
case 'q': printf("是否退出游戏?(y/n)");
ch = getchar();
if (ch == 'y' || ch == 'Y')
exit(0);
break;
case 'w': // 上移
case 'W': up();break;
case 'a': // 左移
case 'A':left(); break;
case 's': // 下移
case 'S': down();break;
case 'd': // 右移
case 'D': right(); break;
default: printf("请使用WASD控制\n");
Sleep(500); break;
}向上移动
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
50int up()//向上移动
{
int now, next;
int i, j, k;
//先合并后移动
for (j = 0; j < 4; j++)
for (i = 0; i < 4; i++)
{
now = map[i][j];
k = i + 1;
while (k < 4)
{
next = map[k][j];
if (next != 0)
{
if (now == next)
{
change = 1;
score += map[k][j] * 2;
map[i][j] = map[k][j] * 2;
map[k][j] = 0;
}
k = 4;
}
k++;
}
}
for (j = 0; j < 4; j++)
for (i = 0; i < 4; i++)
{
now = map[i][j];
if (now == 0)
{
k = i + 1;
while (k < 4)
{
next = map[k][j];
if (next != 0)
{
change = 1;
map[i][j] = next;
map[k][j] = 0;
k = 4;
}
k++;
}
}
}
return change;//返回地图是否变化
}向下移动
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
52int down()//向下移动
{
int i, j;
int now, next, k;
for (j = 0; j < 4; j++)
for (i = 3; i >= 0; i--)
{
now = map[i][j];
if (now != 0)
{
k = i - 1;
while (k >= 0)
{
next = map[k][j];
if (next != 0)
{
if (now == next)
{
change = 1;
score += map[k][j] * 2;
map[i][j] = map[k][j] * 2;
map[k][j] = 0;
}
k = -1;
}
k--;
}
}
}
for (j = 0; j < 4; j++)
for (i = 3; i >= 0; i--)
{
now = map[i][j];
if (now == 0)
{
k = i - 1;
while (k >= 0)
{
next = map[k][j];
if (next != 0)
{
change = 1;
map[i][j] = map[k][j];
map[k][j] = 0;
k = -1;
}
k--;
}
}
}
return change;
}向左移动
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
49int left()//向左移动
{
int i, j;
int now, next, k;
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
{
now = map[i][j];
k = j + 1;
while (k < 4)
{
next = map[i][k];
if (next != 0)
{
if (now == next)
{
change = 1;
score += 2 * map[i][k];
map[i][j] = map[i][k] * 2;
map[i][k] = 0;
}
k = 4;
}
k++;
}
}
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
{
now = map[i][j];
if (now == 0)
{
k = j + 1;
while (k < 4)
{
next = map[i][k];
if (next != 0)
{
change = 1;
map[i][j] = map[i][k];
map[i][k] = 0;
k = 4;
}
k++;
}
}
}
return change;
}向右移动
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
49int right()//向右移动
{
int i, j;
int now, next, k;
for (i = 0; i < 4; i++)
for (j = 3; j >= 0; j--)
{
now = map[i][j];
k = j - 1;
while (k >= 0)
{
next = map[i][k];
if (next != 0)
{
if (next == now)
{
change = 1;
score += map[i][k] * 2;
map[i][j] = map[i][k] * 2;
map[i][k] = 0;
}
k = -1;
}
k--;
}
}
for (i = 0; i < 4; i++)
for (j = 3; j >= 0; j--)
{
now = map[i][j];
if (now == 0)
{
k = j - 1;
while (k >= 0)
{
next = map[i][k];
if (next != 0)
{
change = 1;
map[i][j] = map[i][k];
map[i][k] = 0;
k = -1;
}
k--;
}
}
}
return change;
}游戏结束判断
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22game_over = 0;
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
{
if (map[i][j] == 0) //判断地图里是否还有空位
{
game_over = 1;
break;
}
if (i > 1)//判断是否有相同的两个数字挨在一起,若有则gameover改为1,
{
if (map[i][j] == map[i - 1][j]) game_over = 1;
break;
}
if (j > 1)
if (map[i][j] == map[i][j - 1])
{
game_over = 1;
break;
}
if (game_over == 1) break;
}打印成绩
1
2
3
4
5if (game_over == 0) //游戏结束
{
printf("游戏结束!\n最终得分:%d\n", score);
printf("移动次数:%d\n", move_num);
}主函数
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
70int main()
{
srand((unsigned)time(NULL)); //初始化随机数生成器
while (game_over)
{
int i, j, n;
if (change == 1) //只有在地图变化时才生成新数字
{
do
{
i = rand() % 4; //随机行标
j = rand() % 4; //随机列标
} while (map[i][j] != 0);
n = rand() % 2;
map[i][j] = (n == 0) ? 2 : 4; //随机赋值2或4
move_num++; //移动计数增加
} //在随机位置生成初始数字
menu(); //显示内容
char ch = getch(); //读取键盘
change = 0;
switch (ch)
{
case 'q': printf("是否退出游戏?(y/n)");
ch = getchar();
if (ch == 'y' || ch == 'Y')
exit(0);
break;
case 'w': // 上移
case 'W': up();break;
case 'a': // 左移
case 'A':left(); break;
case 's': // 下移
case 'S': down();break;
case 'd': // 右移
case 'D': right(); break;
default: printf("请使用WASD控制\n");
Sleep(500); break;
}
game_over = 0;
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
{
if (map[i][j] == 0) //判断地图里是否还有空位
{
game_over = 1;
break;
}
if (i > 1)//判断是否有相同的两个数字挨在一起,若有则gameover改为1,
{
if (map[i][j] == map[i - 1][j]) game_over = 1;
break;
}
if (j > 1)
if (map[i][j] == map[i][j - 1])
{
game_over = 1;
break;
}
if (game_over == 1) break;
}
if (game_over == 0) //游戏结束
{
printf("游戏结束!\n最终得分:%d\n", score);
printf("移动次数:%d\n", move_num);
}
}
return 0;
}
4. 整体代码
1 |
|
五. 运行截图
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 山川不念旧!
评论