0. 引子
无聊是第一生产力。实现一下以前玩过的一版修改版的2048,正好测试一下codeium
工具的效果。
Just for fun:)
1. 基本思想
2048的定义是这样的:
该游戏使用方向键让方块整体上下左右移动。如果两个带有相同数字的方块在移动中碰撞,则它们会合并为一个方块,且所带数字变为两者之和。每次移动时,会有一个值为2或者4的新方块出现,所出現的數字都是2的冪。
当值为2048的方块出现时,游戏即胜利,该游戏因此得名。
移动
对于移动的实现,我的想法大概是“拆分-合并-补位”,比如让方块向右移动:
- 拆分:向右移动的过程中,行与行之间相互独立,只需要实现单个行上的移动操作即可。
- 合并:从左往右合并方块。对于2 2 4 8这样的行,原版的2048会合并成0 4 4 8,我的代码将之合并成0 0 0 16,玩起来快一些。
- 补位:将方块都紧密地置于一边,即让4 0 8 16变成 0 4 8 16。
移动的代码大概如下:
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
| void RowMoveRight(int map[map_size][map_size], int index) { for(int i = 1; i < map_size; i++) { if(map[index][i] == map[index][i-1]) { map[index][i] = 2 * map[index][i]; map[index][i-1] = 0; } else if(map[index][i] == 0) { map[index][i] = map[index][i-1]; map[index][i-1] = 0; } }
for(int i = 1; i < map_size; i++) { if(map[index][i] == 0) { map[index][i] = map[index][i-1]; map[index][i-1] = 0; } } }
void MoveRight(int map[map_size][map_size]) { for(int i = 0; i < map_size; i++) { RowMoveRight(map, i); } GenerateTwo(map); }
|
输赢的判断
如果出现了任意一个2048方块,即为赢。大概的逻辑如下:
1 2 3 4 5 6 7 8 9 10 11
| int GameSuccess(int map[map_size][map_size]) { for(int row = 0; row < map_size; row++) { for(int col = 0; col < map_size; col++) { if(map[row][col] == 2048) { return success; } } } return not_success; }
|
若每个方块的值,都不等于右侧方块和下侧方块的值,并且,地图被占满,就是输。codeium
生成的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
| int GameFailed(int map[map_size][map_size]) { for(int i = 0; i < map_size - 1; i++) { for(int j = 0; j < map_size - 1; j++) { if(map[i][j] == 0) { return not_failed; } else if(map[i][j] == map[i+1][j] || map[i][j] == map[i][j+1]) { return not_failed; } } } return failed; }
|
挺对的,哈?No!对于最后一行来说,没法判断方块的值是否等于其右侧方块的值。所以要分开来比较。
输出相关
首先要输出的是地图、移动次数和分数,分数的计算规则很简单,2和2拼出4得4分。
接着,彩色输出方块里数字的值:
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
| #define ANSI_COLOR_RED "\x1b[31m" #define ANSI_COLOR_GREEN "\x1b[32m" #define ANSI_COLOR_YELLOW "\x1b[33m" #define ANSI_COLOR_BLUE "\x1b[34m" #define ANSI_COLOR_MAGENTA "\x1b[35m" #define ANSI_COLOR_CYAN "\x1b[36m" #define ANSI_COLOR_RESET "\x1b[0m"
void OutputDigit(int digit) { printf("|"); if(digit == 0) { printf("%6d", digit); return; } else if(digit <= 4) { printf(ANSI_COLOR_RED); } else if(digit <= 8) { printf(ANSI_COLOR_GREEN); } else if(digit <= 16) { printf(ANSI_COLOR_MAGENTA); } else if(digit <= 256) { printf(ANSI_COLOR_YELLOW); } else if(digit <= 512) { printf(ANSI_COLOR_CYAN); }else { printf(ANSI_COLOR_BLUE); } printf("%6d", digit);
printf(ANSI_COLOR_RESET); }
|
输出大概长这样:
在随便整个主菜单:
简陋版2048就做好了。