2048小游戏

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;
					}
				}
			}
		}
	}
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值