C++编写的2048小游戏
核心算法:
思考:当你按下左键时,如何让每一个行的数进行向左靠拢并叠加呢?
就一行来讲:每次我们都要从左向右判断相邻的两个数,是否相等,但是可能这两个数中间有一个是空白(也就是0)。所以首先我们先得把两个不等于0的数拉到左边来,如果相等就相加赋两个数中左边的,右边的那个数就赋为0。然后继续寻找下一对数。从下图来看,每行得判断3对数。
以下是当按下左键的代码(其他方向类似):
void mvdata(char a, int (*p)[4]) //靠拢叠加
{
int i,j,k; ///i是行,j是列
if(a==75 || a=='a') //左
{
for(i=0;i<4;i++)
for(j=0;j<3;j++)
{
if(p[i][j]==0) //把第一个数拉左边来
for(k=j+1;k<4;k++)
{
if(p[i][k]!=0)
{
p[i][j]=p[i][k];
p[i][k]=0;
break;
}
}
j++;
if(p[i][j]==0) //把第二个数拉左边来
for(k=j+1;k<4;k++)
{
if(p[i][k]!=0)
{
p[i][j]=p[i][k];
p[i][k]=0;
break;
}
}
j--;
if(p[i][j]==p[i][j+1])
{
p[i][j]*=2;
p[i][j+1]=0;
}
}
}
}
如果你以上的看懂了,就可开始动手了。
以下是整个游戏的代码(简单写了下):
#include <iostream>
#include <ctime> //设置随机数的time
#include <conio.h> //使用_kbhi(),_get函数ch()
#include <iomanip> //使用函数stew()控制数据输出宽度。
#include <windows.h> //指定位置输出
using namespace std;
void gotoxy(int x,int y) //将光标移动到坐标为(x,y)的地方
{
CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
HANDLE hConsoleOut;
hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hConsoleOut,&csbiInfo);
csbiInfo.dwCursorPosition.X = x;
csbiInfo.dwCursorPosition.Y = y;
SetConsoleCursorPosition(hConsoleOut,csbiInfo.dwCursorPosition);
}
void HideCursor() // 用于隐藏光标
{
CONSOLE_CURSOR_INFO cursor_info = {1, 0}; // 第二个值为0表示隐藏光标
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
/*
复制数组,并判断数组前后变化了没
*/
int change(const int (*p)[4],const int (*q)[4])
{
int i,j;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
{
if(p[i][j]!=q[i][j])
return 1; //改变返回1(真)
}
return 0; //没变返回0(假)
}
void copyroom(int (*p)[4],const int (*q)[4])
{
int i,j;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
p[i][j]=q[i][j];
}
/*
随机给空的地方出现2或4
*/
int getrand(void)
{
srand((unsigned)time(NULL));
return rand();
}
int getrandnumber(void)
{
return getrand()%2 ? 2 : 4 ;
}
int srandnumber(int (*p)[4])
{
int i,j;
while(1)
{
for(i=0;i<4;i++)
for(j=0;j<4;j++)
{
if( p[i][j]==0 ) //若为空白
if(rand() % 3==0) //且随机数是16的倍数 //考虑到程序运行的数据不大所以可以这么搞
{
p[i][j]=getrandnumber();
return 0; //结束
}
}
}
}
/*
接收敲击键盘的上下左右键,并作出相应的反应
*/
void mvdata(char a, int (*p)[4]) //靠拢叠加
{
int i,j,k; ///i是行,j是列
if(a==75 || a=='a') //左
{
for(i=0;i<4;i++)
for(j=0;j<3;j++)
{
if(p[i][j]==0) //把第一个数拉左边来
for(k=j+1;k<4;k++)
{
if(p[i][k]!=0)
{
p[i][j]=p[i][k];
p[i][k]=0;
break;
}
}
j++;
if(p[i][j]==0) //把第二个数拉左边来
for(k=j+1;k<4;k++)
{
if(p[i][k]!=0)
{
p[i][j]=p[i][k];
p[i][k]=0;
break;
}
}
j--;
if(p[i][j]==p[i][j+1])
{
p[i][j]*=2;
p[i][j+1]=0;
}
}
}
if(a==77 || a=='d') //右
{
for(i=0;i<4;i++)
for(j=3;j>0;j--)
{
if(p[i][j]==0) //把数拉右边来
for(k=j-1;k>=0;k--)
{
if(p[i][k]!=0)
{
p[i][j]=p[i][k];
p[i][k]=0;
break;
}
}
j--;
if(p[i][j]==0) //把数拉右边来
for(k=j-1;k>=0;k--)
{
if(p[i][k]!=0)
{
p[i][j]=p[i][k];
p[i][k]=0;
break;
}
}
j++;
if(p[i][j]==p[i][j-1])
{
p[i][j]*=2;
p[i][j-1]=0;
}
}
}
if(a==72 || a=='w') //上
{
for(j=0;j<4;j++)
for(i=0;i<3;i++)
{
if(p[i][j]==0) //把数拉上边来
for(k=i+1;k<4;k++)
{
if(p[k][j]!=0)
{
p[i][j]=p[k][j];
p[k][j]=0;
break;
}
}
i++;
if(p[i][j]==0) //把数拉上边来
for(k=i+1;k<4;k++)
{
if(p[k][j]!=0)
{
p[i][j]=p[k][j];
p[k][j]=0;
break;
}
}
i--;
if(p[i][j]==p[i+1][j])
{
p[i][j]*=2;
p[i+1][j]=0;
}
}
}
if(a==80 || a=='s') //下
{
for(j=0;j<4;j++)
for(i=3;i>0;i--)
{
if(p[i][j]==0) //把数拉下边来
for(k=i-1;k>=0;k--)
{
if(p[k][j]!=0)
{
p[i][j]=p[k][j];
p[k][j]=0;
break;
}
}
i--;
if(p[i][j]==0) //把数拉下边来
for(k=i-1;k>=0;k--)
{
if(p[k][j]!=0)
{
p[i][j]=p[k][j];
p[k][j]=0;
break;
}
}
i++;
if(p[i][j]==p[i-1][j])
{
p[i][j]*=2;
p[i-1][j]=0;
}
}
}
}
/*
判断输赢
*/
int score(const int (*p)[4]) //分数
{
int i,j,score=0;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
{
score=(score<p[i][j]? p[i][j]:score);
}
return score;
}
int judgelose(const int (*p)[4]) //判断输了没
{
int i,j,score=0;
for(i=0;i<4;i++)
for(j=0;j<3;j++)
{
if(p[i][j]==p[i][j+1] || p[i][j]==0 || p[i][j+1]==0)
return 0;
}
for(j=0;j<4;j++)
for(i=0;i<3;i++)
{
if(p[i][j]==p[i+1][j] || p[i][j]==0 || p[i+1][j]==0)
return 0; //是假输
}
return 1; ///是真输
}
int judgewin(const int (*p)[4]) //判断赢了没
{
if(score(p)==2048)
return 1; // 是真赢
return 0; //是假赢
}
void printmap(int (*p)[4]) //打印地图数据
{
int i,j;
gotoxy(0,0);
cout << "┌-----┬-----┬-----┬-----┐"<< endl;
for(i=0;i<4;i++)
{
cout << "│";
for(j=0;j<4;j++)
{
cout << setw(5) << p[i][j] << "│";
}
cout << endl;
if(i!=3)
{
cout << "├-----┼-----┼-----┼-----┤" << endl;
}
}
cout << "└-----┴-----┴-----┴-----┘"<< endl;
cout << "分数: " << score(p) << endl;
}
int main(){
char kbht;
int a[4][4]={0},b[4][4]={0}; //定义数组
srandnumber(a); //先给他随机两个数
srandnumber(a);
copyroom(b,a);
printmap(a);
HideCursor();
while(1)
{
if(_kbhit()) //获取键盘上按键的情况
{
kbht=_getch();
mvdata(kbht,a);
if(change(a,b))
{
srandnumber(a);
printmap(a);
if(judgewin(a))
{
cout << "好吧,你赢了,算你厉害!" << endl;
break;
}
if(judgelose(a))
{
cout << "你输了,再接再厉吧!" << endl;
break;
}
}
copyroom(b,a);
}
}
return 0;
}
新手小白刚学C++,有什么建议话,欢迎各位在以下给我留言。