C++小游戏之2048

看了那么久的书,每次都是编点很基础的定义程序。前几天看到培训视频里面介绍编写简单的2048小游戏,顿时手痒想写一个程序练练手。视频看到随机数就看不下去了,觉得算了,还是我自己网上查点资料,自己动脑子写一个吧,期间还是走了不少弯路!我写的这个比较简陋,没有得分记录,没有失败判断,主要把这个核心写出来。

效果如下:


界面我就随便整了,对于我而言,命令行看着才是最舒心的。下面我就主要的介绍2048实现的思路。


2048的游戏规则

(1)开始时,随机两个位置出现数字2或4,而且2和4出现的概率比为9:1.
(2)可以向上,下,左,右四个方向移动,移动过程中相同数字合并,不能连续合并,合并后实现分数累积。
(3)当出现2048数字,判为胜利,如果数字填满方块,且没有数字能实现合并,判为失败。

2048实现的思路

(1)因为2048是一个4X4的小方块集合,所以用一个二维数组就可以满足要求。
(2)用头文件ctime 里的随机函数产生随机数。
(3)当上移动时,进行一次紧凑(偶数上移,0下移)。判断相邻位置的数字是否相等,如果相等实现合并。再进行一次紧凑。其它方向类似。
(4)对屏幕实现清屏,再一次打印数组。

产生随机数的函数:
int random_num() {
	srand((unsigned int)time(NULL));	//随机数
	int num = rand() % 10;		
	return num < 1 ? 4 : 2;
}
rand()函数产生的数字除去10取余数,得到0-9的数字,小于1成立时返回数字4,不成立返回数字2。这样实现了2和4出现的比例为9:1.

随机位置出现数字的函数:
void random_place() {
	int row, col;
	row = rand() % 4;
	col = rand() % 4;
	while (map[row][col] != 0) {
		row = rand() % 4;
		col = rand() % 4;
	}
	map[row][col] = random_num();
}

向上移动的函数:
void moveUp() {			//进行紧凑将数字上移,相加,再一次进行紧凑
	int flag, temp;
	//进行紧凑(偶数上移,数字0下移)	
	/*思路是:对同列不同行的数字进行循环,当遇到第一个不为0的数字的时候,将该值的行数值赋给flag.在对flag进行回溯,目的是把非零数字上移*/
	for (int col = 0; col < 4; col++) {		
		for (int row = 0; row < 4; row++) {		
			if (map[row][col] != 0) {
				flag = row;
				while (flag != 0 && map[flag - 1][col] == 0) {			//第一项避免flag-1越界,第二项是当前一位置为零是才置换,否则不换
					temp = map[flag - 1][col];
					map[flag - 1][col] = map[flag][col];
					map[flag][col] = temp;
					flag--;
				}
			}
		}
	}
	for (int col = 0; col < 4; col++) {		//判断当前数字与下一行同列的数字是否相等。如果相等该数字变为自身的两倍,相邻数字置为0
		for (int row = 0; row < 3; row++) {
			if (map[row][col] == map[row + 1][col]) {
				map[row][col] *= 2;
				map[row + 1][col] = 0;
			}
		}
	}
	for (int col = 0; col < 4; col++) {		//再一次进行紧凑(偶数上移,数字0下移)	
		for (int row = 0; row < 4; row++) {
			if (map[row][col] != 0) {
				flag = row;
				while (flag != 0 && map[flag - 1][col] == 0) {
					temp = map[flag - 1][col];
					map[flag - 1][col] = map[flag][col];
					map[flag][col] = temp;
					flag--;
				}
			}
		}
	}
	random_place();
}
代码注释里面简要的写了一下思路,下面我详细的解释一下:
   定义两个for循环,这样可以在同一列上比较不同行的数字,图示如下:


这样实现了偶数上移,0下移。继续对数组进行循环操作,判断当前数字与同列下一行的数字是否相等。如果相等该数字变为自身的两倍,相邻数字置为0。再一次进行紧凑,这样就不会连续合并。其它方向的紧凑过程类似,就不在详细多说了。


完整代码:
#include<iostream>
#include<ctime>
using namespace std;
int map[4][4] = { 0 };		//因为2048是一个4X4的小方块集合,所以定义一个二维数组与之对应
void print();				//打印数组里的数字
int random_num();			//产生随机数字4和2,产生几率为1:9
void random_place();			//在为数值为0的区域随机产生数字
void moveUp();			//向上移动
void moveDown();		//向下移动
void moveLeft();		//向左移动
void moveRight();		//向右移动

void main() {
	char ch;
	random_place();	//开始时,随机两个位置产生2或4
	random_place();
	while (1) {
		system("cls");
		print();
		cin >> ch;
		switch (ch) {
		case 'w':moveUp(); break;
		case 's':moveDown(); break;
		case 'a':moveLeft(); break;
		case 'd':moveRight(); break;
		case 'p':exit(0); break;
		default:cout << "输入错误,请重新输入!" << endl; break;
		}
	}
	system("pause");
}
void print() {
	cout << "************************************************" << endl;
	cout << "*     " << map[0][0] << "       	 " << map[0][1] << "           " << map[0][2] << "      	  " << map[0][3] << "    *" << endl;
	cout << "************************************************" << endl;
	cout << "*     " << map[1][0] << "       	 " << map[1][1] << "           " << map[1][2] << "      	  " << map[1][3] << "    *" << endl;
	cout << "************************************************" << endl;
	cout << "*     " << map[2][0] << "       	 " << map[2][1] << "           " << map[2][2] << "      	  " << map[2][3] << "    *" << endl;
	cout << "************************************************" << endl;
	cout << "*     " << map[3][0] << "       	 " << map[3][1] << "           " << map[3][2] << "      	  " << map[3][3] << "    *" << endl;
	cout << "************************************************" << endl;
	cout << "操作详情:(输入后,按回车键结束)" << endl;
	cout << "w :	向上移动		s :		向下移动" << endl;
	cout << "a :	向左移动		s :		向右移动" << endl;
	cout << "p :	退出" << endl;
}
int random_num() {
	srand((unsigned int)time(NULL));	//随机数
	int num = rand() % 10;
	return num < 1 ? 4 : 2;
}

void random_place() {
	int row, col;
	row = rand() % 4;
	col = rand() % 4;
	while (map[row][col] != 0) {
		row = rand() % 4;
		col = rand() % 4;
	}
	map[row][col] = random_num();
}

void moveUp() {			//进行紧凑将数字上移,相加,再一次进行紧凑
	int flag, temp;
	//进行紧凑(偶数上移,数字0下移)	
	/*思路是:对同列不同行的数字进行循环,当遇到第一个不为0的数字的时候,将该值的行数值赋给flag.在对flag进行回溯,目的是把非零数字上移*/
	for (int col = 0; col < 4; col++) {		
		for (int row = 0; row < 4; row++) {		
			if (map[row][col] != 0) {
				flag = row;
				while (flag != 0 && map[flag - 1][col] == 0) {			//第一项避免flag-1越界,第二项是当前一位置为零是才置换,否则不换
					temp = map[flag - 1][col];
					map[flag - 1][col] = map[flag][col];
					map[flag][col] = temp;
					flag--;
				}
			}
		}
	}
	for (int col = 0; col < 4; col++) {		//判断当前数字与下一行同列的数字是否相等。如果相等该数字变为自身的两倍,相邻数字置为0
		for (int row = 0; row < 3; row++) {
			if (map[row][col] == map[row + 1][col]) {
				map[row][col] *= 2;
				map[row + 1][col] = 0;
			}
		}
	}
	for (int col = 0; col < 4; col++) {		//再一次进行紧凑(偶数上移,数字0下移)	
		for (int row = 0; row < 4; row++) {
			if (map[row][col] != 0) {
				flag = row;
				while (flag != 0 && map[flag - 1][col] == 0) {
					temp = map[flag - 1][col];
					map[flag - 1][col] = map[flag][col];
					map[flag][col] = temp;
					flag--;
				}
			}
		}
	}
	random_place();
}
void moveDown() {
	int flag, temp;
	//进行紧凑(偶数下移,数字0上移)	
	for (int col = 0; col < 4; col++) {
		for (int row = 3; row >= 0; row--) {
			if (map[row][col] != 0) {
				flag = row;
				while (flag != 3 && map[flag + 1][col] == 0) {			//第一项避免flag+1越界,第二项是当后一位置为零是才置换,否则不换
					temp = map[flag + 1][col];
					map[flag + 1][col] = map[flag][col];
					map[flag][col] = temp;
					flag++;
				}
			}
		}
	}
	for (int col = 0; col < 4; col++) {		
		for (int row = 3; row > 0; row--) {
			if (map[row][col] == map[row - 1][col]) {
				map[row][col] *= 2;
				map[row - 1][col] = 0;
			}
		}
	}
	for (int col = 0; col < 4; col++) {				//再一次进行紧凑(偶数下移,数字0上移)	
		for (int row = 3; row >= 0; row--) {
			if (map[row][col] != 0) {
				flag = row;
				while (flag != 3 && map[flag + 1][col] == 0) {			
					temp = map[flag + 1][col];
					map[flag + 1][col] = map[flag][col];
					map[flag][col] = temp;
					flag++;
				}
			}
		}
	}
	random_place();
}
void moveLeft() {
	int flag, temp;
	//进行紧凑(偶数左移,数字0右移)	
	for (int row = 0; row < 4; row++) {
		for (int col = 0; col < 4; col++) {
			if (map[row][col] != 0) {
				flag = col;
				while (flag != 0 && map[row][flag-1] == 0) {			//第一项避免flag-1越界,第二项是当前一位置为零是才置换,否则不换
					temp = map[row][flag - 1];
					map[row][flag - 1] = map[row][flag];
					map[row][flag] = temp;
					flag--;
				}
			}
		}
	}
	for (int row = 0; row < 4; row++) {		//判断当前数字与下一列同行的数字是否相等。如果相等该数字变为自身的两倍,相邻数字置为0
		for (int col = 0; col < 3; col++) {
			if (map[row][col] == map[row][col+1]) {
				map[row][col] *= 2;
				map[row][col+1] = 0;
			}
		}
	}
	for (int row = 0; row < 4; row++) {		//再一次进行紧凑(偶数左移,数字0右移)	
		for (int col = 0; col < 4; col++) {
			if (map[row][col] != 0) {
				flag = col;
				while (flag != 0 && map[row][flag-1] == 0) {		
					temp = map[row][flag - 1];
					map[row][flag - 1] = map[row][flag];
					map[row][flag] = temp;
					flag--;
				}
			}
		}
	}
	random_place();
}
void moveRight() {
	int flag, temp;
	//进行紧凑(偶数右移,数字0左移)	
	for (int row = 0; row < 4; row++) {
		for (int col = 3; col >= 0; col--) {
			if (map[row][col] != 0) {
				flag = col;
				while (flag != 3 && map[row][flag+1] == 0) {			//第一项避免flag+1越界,第二项是当后一位置为零是才置换,否则不换
					temp = map[row][flag + 1];
					map[row][flag + 1] = map[row][flag];
					map[row][flag] = temp;
					flag++;
				}
			}
		}
	}
	for (int row = 0; row < 4; row++) {		
		for (int col = 3; col > 0; col--) {
			if (map[row][col] == map[row][col - 1]) {
				map[row][col] *= 2;
				map[row][col - 1] = 0;
			}
		}
	}
	for (int row = 0; row < 4; row++) {		//再一次进行紧凑(偶数右移,数字0左移)	
		for (int col = 3; col >= 0; col--) {
			if (map[row][col] != 0) {
				flag = col;
				while (flag != 3 && map[row][flag+1] == 0) {			
					temp = map[row][flag + 1];
					map[row][flag + 1] = map[row][flag];
					map[row][flag] = temp;
					flag++;
				}
			}
		}
	}
	random_place();
}




  • 10
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值