您的位置:首页 > 编程语言 > C语言/C++

C++小游戏之2048

2017-01-22 14:23 344 查看
看了那么久的书,每次都是编点很基础的定义程序。前几天看到培训视频里面介绍编写简单的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越界,第二项是当前一位置为零是才置换,否则不换
t
c333
emp = 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();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++