设计思路
- 游戏地图和初始设置:
- 使用一个 4x4 的二维数组
map
来表示游戏地图。 - 初始时,所有位置的值均为 0。
score
记录玩家得分,move_num
记录移动次数。
- 随机生成数字:
- 在地图上随机选择一个空位置生成 2 或 4。
- 只有在地图发生变化时才会生成新数字。
- 游戏菜单:
- 使用
menu()
函数显示当前的游戏状态,包括地图、得分和移动次数。 - 提示玩家使用 W、A、S、D 键进行移动。
- 玩家移动:
- 使用
move()
函数读取玩家输入,并根据输入的方向调用相应的移动函数 (up()
、left()
、down()
、right()
)。 - 每个移动函数都负责处理特定方向的移动,并更新地图。
- 移动逻辑:
- 移动时首先合并相同的数字,然后将非零元素向目标方向移动填补空格。
change
变量用于记录地图是否发生变化,以决定是否生成新数字。
- 游戏结束判断:
- 使用
over()
函数检查游戏是否结束。 - 游戏结束的条件是:地图没有空位且没有相邻的相同数字。
- 若游戏结束,输出最终得分和移动次数。
细节分析
- 随机数生成:使用
rand()
函数生成随机位置和数字,但未处理随机数种子的初始化位置,可能会导致每次运行的结果相同。 - 输入处理:使用
getch()
函数获取用户输入,并根据输入调用相应的移动函数。 - 移动实现:每个方向的移动函数都按照特定的顺序检查并合并相同的数字,然后移动非零元素。
- 游戏结束检测:遍历整个地图,检查是否还有空位或相邻的相同数字。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h> int map[4][4] = {0};
int score = 0;
int move_num = -1;
int game_over = 1;
int change = 1;
char input;
void start();
void randIntNum();
void menu();
void move();
int up();
int left();
int down();
int right();
int over();
void randIntNum()
{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; move_num++; }
}
void menu()
{system("cls"); int i, j;printf(" 欢迎来到2048\n");printf(" ----------------------------------------\n");printf(" W——UP S——DOWN A——LEFT D——RIGHT\n");printf(" 请按0退出游戏。\n");printf(" MOVE:%d SCORE:%d\n", move_num, score);printf(" \n |-------------------------------------------|\n");for (i = 0; i <= 3; i++){for (j = 0; j <= 3; j++){printf(" ");if (map[i][j] == 0)printf("| ");elseprintf("|%5d", map[i][j]);}printf(" |\n |-------------------------------------------|\n");}
}
void move()
{char ch = getch(); change = 0; switch (ch){case '0': printf("确定要退出吗?(y/n)\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("无效输入,请重新输入!\n");break;}
}
int 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] = 2 * map[k][j];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 = 1 + i;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;
}
int 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;
}
int 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;
}
int 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;
}
int over()
{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){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);}
}
void start()
{srand((unsigned)time(NULL)); while (game_over) {randIntNum(); menu(); move(); over();}
}int main()
{start(); return 0;
}