C++小游戏之2048

来源:互联网 发布:搜狐2016出品的网络剧 编辑:程序博客网 时间:2024/06/05 14:13

看了那么久的书,每次都是编点很基础的定义程序。前几天看到培训视频里面介绍编写简单的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++) {//判断当前数字与下一行同列的数字是否相等。如果相等该数字变为自身的两倍,相邻数字置为0for (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:9void random_place();//在为数值为0的区域随机产生数字void moveUp();//向上移动void moveDown();//向下移动void moveLeft();//向左移动void moveRight();//向右移动void main() {char ch;random_place();//开始时,随机两个位置产生2或4random_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++) {//判断当前数字与下一行同列的数字是否相等。如果相等该数字变为自身的两倍,相邻数字置为0for (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++) {//判断当前数字与下一列同行的数字是否相等。如果相等该数字变为自身的两倍,相邻数字置为0for (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();}




0 0