2048小游戏
2048初始数字由2+2组成的基数4。游戏规则很简单,每次可以选择上下左右其中一个方向去滑动,每滑动一次,所有的数字方块都会往滑动的方向靠拢外,系统也会在空白的地方乱数出现一个数字方块,相同数字的方块在靠拢、相撞时会相加。系统给予的数字方块不是2就是4,玩家要想办法在这小小的16格范围中凑出"2048"这个数字方块。(来源于百科)
第一次写小游戏,出于兴趣在课余时间尝试了一下。由于代码比较简单,因此不做过多文字描述。
游戏面板使用一个外部静态全局变量。
static int board[4][4];
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef unsigned char boolean;
#define TRUE 1
#define FALSE 0
static int board[4][4]; //游戏面板;
先生成游戏界面,设计一个较为美观的界面。
表格可在搜狗输入法中右键选择表情&符号中的符号大全中选择。
生成界面如下:
void backBoard(int *score, int *bestScore, boolean *gameOver) {
int i;
int j;
int p;
system("cls");
printf("\n\n");
printf("\t\t\t\t\t\t GAME: 2048\n");
printf("\t\t\t\t\t\tSCORE: %4d BEST: %4d\n", *score, *bestScore);
printf("\t\t\t\t===================================================\n");
printf("\t\t\t\t\t\t┏━━━━┳━━━━┳━━━━┳━━━━┓\n");
for(i = 0; i < 4; i++) {
printf("\t\t\t\t\t\t┃");
for(j = 0; j < 4; j++) {
if(board[i][j] != 0) {
printf("%4d┃", board[i][j]);
} else {
printf(" ┃");
}
}
if(i < 3) {
printf("\n\t\t\t\t\t\t┣━━━━╋━━━━╋━━━━╋━━━━┫\n");
} else {
printf("\n\t\t\t\t\t\t┗━━━━┻━━━━┻━━━━┻━━━━┛\n");
}
}
printf("\t\t\t\t===================================================\n");
printf("\t\t\t\t 操作: ↑ W ← A → D ↓ S T退出\n");
p = getNullCount();
if(FALSE == p) {
judgeGameOver(gameOver);
if(*gameOver) {
printf("---------------------------------\n");
printf("游戏结束!");
printf("---------------------------------\n");
}
}
}
此游戏需要在空格处随机产生数字2或4,所以我们可以使用随机数函数。将随机数与4取余,那么最后的值可为0,1,2,3;0为假,非0为真;所以,2,4出现比例为3:1。
void generateRandNum() {
int i;
int j;
srand((unsigned)time(NULL));
while(TRUE){
i = rand() % 4;
j = rand() % 4;
if(board[i][j] == 0) {
board[i][j] = (rand() % 4 ? 2 : 4); //值可为0,1,2,3;0为假,非0为真;所以,2,4出现比例为3:1;
break;
} else
continue;
}
}
接下来是初始化游戏和键盘操作。在这里用w、a、s、d来执行上下左右的移动。
void startGame(int *score, int *bestScore, boolean *judgeAddNum, boolean *gameOver) {
char ch;
initGame(score, bestScore, judgeAddNum, gameOver);
while(1) {
ch = getch();
if(*gameOver) {
if(ch == 'y' || 'Y') {
initGame(score, bestScore, judgeAddNum, gameOver);
break;
} else if(ch == 'n' || 'N') {
return;
} else {
continue;
}
}
switch(ch) {
case 'a':
moveLeft(score, judgeAddNum);
break;
case 's':
moveDown(score, judgeAddNum);
break;
case 'w':
moveUp(score, judgeAddNum);
break;
case 'd':
moveRight(score, judgeAddNum);
break;
case 't':
return;
}
*score > *bestScore ? *bestScore = *score : 1; //更新最高分;
if(*judgeAddNum) {
generateRandNum();
backBoard(score, bestScore, gameOver);
}
}
}
void initGame(int *score, int *bestScore, boolean *judgeAddNum, boolean *gameOver) {
int i;
int j;
i = rand() % 4;
j = rand() % 4;
board[i][j] = 2;
generateRandNum();
backBoard(score, bestScore, gameOver);
}
我们还需要判断是否还有空的项以便于决定是否继续产生随机数,以及在此基础上通过比较任意相邻的数值以便判断游戏是否结束。
void judgeGameOver(boolean *gameOver) {
int i;
int j;
for(i = 0; i < 4; i++) {
for(j = 0; j < 3; j++) {
if(board[i][j] == board[i][j + 1] || board[j][i] == board[j + 1][i]) {
*gameOver = FALSE;
return;
}
}
}
*gameOver = TRUE;
}
int getNullCount() {
int n;
int i;
int j;
n = 0;
for(i = 0; i < 4; i++) {
for(j = 0; j < 4; j++) {
if(board[i][j] == 0) {
n++;
}
}
}
return n;
}
接下来就是移动了,其实上下左右移动的方式都是相似的,只用改变循环条件和部分数组下标的值即可。
void moveLeft(int *score, boolean *judgeAddNum) {
int i;
int j;
int index;
for(i = 0; i < 4; i++) {
for(j = 1, index = 0; j < 4; j++) {
if(board[i][j] > 0) { //index项后面第一个不为0的数;
if(board[i][j] == board[i][index]) {
*score += board[i][index++] <<= 1;
board[i][j] = 0;
*judgeAddNum = TRUE;
} else if(board[i][index] == 0) { //index项为空,把j项的值移动到index;
board[i][index] = board[i][j];
board[i][j] = 0;
*judgeAddNum = TRUE;
} else { //index项不为0,j项与index项不相等;
board[i][++index] = board[i][j];
if(j != index) {
board[i][j] = 0;
*judgeAddNum = TRUE;
}
}
}
}
}
}
void moveDown(int *score, boolean *judgeAddNum) {
int i;
int j;
int index;
for(i = 0; i < 4; i++) {
for(j = 2, index = 3; j >= 0; j--) {
if(board[j][i] > 0) {
if(board[j][i] == board[index][i]) {
*score += board[index--][i] <<= 1;
board[j][i] = 0;
*judgeAddNum = TRUE;
} else if(board[index][i] == 0) {
board[index][i] = board[j][i];
board[j][i] = 0;
*judgeAddNum = TRUE;
} else {
board[--index][i] = board[j][i];
if(j != index) {
board[j][i] = 0;
*judgeAddNum = TRUE;
}
}
}
}
}
}
void moveUp(int *score, boolean *judgeAddNum) {
int i;
int j;
int index;
for(i = 0; i < 4; i++) {
for(j = 1, index = 0; j < 4; j++) {
if(board[j][i] > 0) {
if(board[j][i] == board[index][i]) {
*score += board[index++][i] <<= 1;
board[j][i] = 0;
*judgeAddNum = TRUE;
} else if(board[index][i] == 0) {
board[index][i] = board[j][i];
board[j][i] = 0;
*judgeAddNum = TRUE;
} else {
board[++index][i] = board[j][i];
if(j != index) {
board[j][i] = 0;
*judgeAddNum = TRUE;
}
}
}
}
}
}
void moveRight(int *score, boolean *judgeAddNum) {
int i;
int j;
int index;
for(i = 0; i < 4; i++) {
for(j = 2, index = 3; j >= 0; j--) {
if(board[i][j] > 0) {
if(board[i][j] == board[i][index]) {
*score += board[i][index--] <<= 1;
board[i][j] = 0;
*judgeAddNum = TRUE;
} else if(board[i][index] == 0) {
board[i][index] = board[i][j];
board[i][j] = 0;
*judgeAddNum = TRUE;
} else {
board[i][--index] = board[i][j];
if(j != index) {
board[i][j] = 0;
*judgeAddNum = TRUE;
}
}
}
}
}
}