本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
介绍
《2048》是一款比较流行的数字游戏,最早于2014年3月20日发行。原版2048首先在GitHub上发布,原作者是Gabriele Cirulli,后被移植到各个平台。这款游戏是基于《1024》和《小3传奇》的玩法开发而成的新型数字游戏。
游戏时,每次操作可以选择上下左右其中一个方向去滑动。每滑动一次,所有的数字方块都会往滑动的方向靠拢外,系统也会在空白的地方随机出现一个数字方块,保证出现的数字方块为 2 的正整数次幂,相同数字的方块在靠拢、相撞时会相加。不断的叠加最终拼凑出2048这个数字就算成功。但是,we never stop,我们可以继续进行游戏,来争取更大的胜利。
本文使用前文介绍的控制台小游戏编写思路和C语言、部分 C++ 函数以及 WindowsAPI 等知识,简单的编写了控制台版本的 2048 小游戏qwq
emmmmm……因为Ice的水平低下&编译器版本&笔记本自身问题&控制台游戏的表现形式……所以它的兼容性非常低……
根据自己的运行结果来调整界面和时间参数吧QAQ……
程序框图
思路
开始、初始化地图、获取用户输入等操作在其他文章中已经细说过,这里我们只着重介绍存储地图的信息该如何维护。
我们所有的操作都是对这个二维数组的数据的操作。分为上下左右四个方向。
由于数据量很小,我们可以每次操作都暴力模拟执行。
-
上移 上移操作的是列,首选需要取出各列元素,每列自上而下取出各列元素。
将 0 元素移到列的最后。
若存在相邻相同的元素,将上方的格子置为两者之和,下方的格子置为 0。
再次将 0 元素移到列的最后。
重复上述操作,最后将移动后的各元素重新给 的二维数组赋值。 -
下移 下移操作的是列,首选需要取出各列元素,每列自下而上取出元素。
将 0 元素移到列的最前。
若存在相邻相同的元素,将下方的格子置为两者之和,上方的格子置为 0。
再次将 0 元素移到列的最前。
重复上述操作,最后将移动后的各元素重新给 的二维数组赋值。 -
左移 左移操作的是行,首选需要取出各行元素,每行自左而右取出元素。
将 0 元素移到列的最右。
若存在相邻相同的元素,将左方的格子置为两者之和,右方的格子置为 0。
再次将 0 元素移到列的最右。
重复上述操作,最后将移动后的各元素重新给 的二维数组赋值。 -
右移 右移操作的是行,首选需要取出各行元素,每行自右而左取出元素。
将 0 元素移到列的最左。
若存在相邻相同的元素,将右方的格子置为两者之和,左方的格子置为 0。
再次将0元素移到列的最左。
重复上述操作,最后将移动后的各元素重新给 的二维数组赋值。
这样四种操作只是取元素的方向不同,其他的操作都是相同的,可以共用部分代码。
代码
#include <bits/stdc++.h>
using namespace std;
string member[6]={" ┌ ┬ ┬ ┬ ┬ ┐",
" ├ ┤",
" ├ ┤",
" ├ ┤",
" └ ┴ ┴ ┴ ┴ ┘"};
string pr="2048\n输入\"Start\"以开始游戏。\n输入\"Exit\"以结束游戏。\n";
int a[5][5],b[5][5];
void Exit();
void fengmian();
void print();
void game();
long long sum=0;
HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);
void gotoxy(HANDLE hOut, int x, int y);
void getxy(HANDLE hOut, int &xx, int &yy);
void gotoxy(HANDLE hOut, int x, int y)
{
COORD pos;
pos.X=x;
pos.Y=y;
SetConsoleCursorPosition(hOut,pos);
}
void getxy(HANDLE hOut,int &xx,int &yy)
{
CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info;
GetConsoleScreenBufferInfo(hOut, &screen_buffer_info);
xx=screen_buffer_info.dwCursorPosition.X;
yy=screen_buffer_info.dwCursorPosition.Y;
}
void hide()
{
HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(handle, &CursorInfo);
CursorInfo.bVisible=false;
SetConsoleCursorInfo(handle, &CursorInfo);
}
void ehide()
{
HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(handle, &CursorInfo);
CursorInfo.bVisible=true;
SetConsoleCursorInfo(handle, &CursorInfo);
}
void NEW()
{
memset(a,0,sizeof(a));
sum=0;
}
void Exit()
{
exit(0);
}
void copp()
{
for (int i=1;i<=4;++i)
for (int j=1;j<=4;++j) b[i][j]=a[i][j];
}
int zb[5][5][2]={ 0,0 , 0,0 , 0,0 , 0,0 , 0,0 ,
0,0 , 2,3 , 2,15 , 2,27 , 2,39 ,
0,0 , 7,3 , 7,15 , 7,27 , 7,39 ,
0,0 , 12,3 , 12,15 , 12,27 , 12,39 ,
0,0 , 17,3 , 17,15 , 17,27 , 17,39
};
void print()
{
for (int i=1;i<=4;++i)
for (int j=1;j<=4;++j)
if (a[i][j]!=b[i][j])
{
gotoxy(hOut,zb[i][j][1],zb[i][j][0]);
printf(" ");
gotoxy(hOut,zb[i][j][1],zb[i][j][0]);
if (a[i][j]) printf("%d",a[i][j]);
}
copp();
gotoxy(hOut,16,20);
printf(" %lld",sum);
}
bool qaq(int x)
{
if (x<1) return 0;
if (x>4) return 0;
return 1;
}
bool move(int x,int y)
{
for (int i=1;i<=4;++i)
for (int j=1;j<=4;++j)
if (a[i][j]&&qaq(i+x)&&qaq(j+y)&&a[i+x][j+y]==0) return 1;
for (int i=1;i<=4;++i)
for (int j=1;j<=4;++j)
if (a[i][j]&&qaq(i+x)&&qaq(j+y)&&a[i+x][j+y]==a[i][j]) return 1;
return 0;
}
int u,v,t;
void Move(char x)
{
if (x=='d')
for (int i=1;i<=4;++i)
{
t=bool(a[i][1])+bool(a[i][2])+bool(a[i][3])+bool(a[i][4]);
while (t>0&&!a[i][4]) a[i][4]=a[i][3],a[i][3]=a[i][2],a[i][2]=a[i][1],a[i][1]=0;
t--;
while (t>0&&!a[i][3]) a[i][3]=a[i][2],a[i][2]=a[i][1],a[i][1]=0;
t--;
while (t>0&&!a[i][2]) a[i][2]=a[i][1],a[i][1]=0;
if (a[i][4]==a[i][3]) a[i][4]+=a[i][3],a[i][3]=a[i][2],a[i][2]=a[i][1],a[i][1]=0;
if (a[i][3]==a[i][2]) a[i][3]+=a[i][2],a[i][2]=a[i][1],a[i][1]=0;
if (a[i][2]==a[i][1]) a[i][2]+=a[i][1],a[i][1]=0;
}
else if (x=='a')
for (int i=1;i<=4;++i)
{
t=bool(a[i][1])+bool(a[i][2])+bool(a[i][3])+bool(a[i][4]);
while (t>0&&!a[i][1]) a[i][1]=a[i][2],a[i][2]=a[i][3],a[i][3]=a[i][4],a[i][4]=0;
t--;
while (t>0&&!a[i][2]) a[i][2]=a[i][3],a[i][3]=a[i][4],a[i][4]=0;
t--;
while (t>0&&!a[i][3]) a[i][3]=a[i][4],a[i][4]=0;
t--;
if (a[i][1]==a[i][2]) a[i][1]+=a[i][2],a[i][2]=a[i][3],a[i][3]=a[i][4],a[i][4]=0;
if (a[i][2]==a[i][3]) a[i][2]+=a[i][3],a[i][3]=a[i][4],a[i][4]=0;
if (a[i][3]==a[i][4]) a[i][3]+=a[i][4],a[i][4]=0;
}
else if (x=='s')
for (int i=1;i<=4;++i)
{
t=bool(a[1][i])+bool(a[2][i])+bool(a[3][i])+bool(a[4][i]);
while (t>0&&!a[4][i]) a[4][i]=a[3][i],a[3][i]=a[2][i],a[2][i]=a[1][i],a[1][i]=0;
t--;
while (t>0&&!a[3][i]) a[3][i]=a[2][i],a[2][i]=a[1][i],a[1][i]=0;
t--;
while (t>0&&!a[2][i]) a[2][i]=a[1][i],a[1][i]=0;
t--;
if (a[4][i]==a[3][i]) a[4][i]+=a[3][i],a[3][i]=a[2][i],a[2][i]=a[1][i],a[1][i]=0;
if (a[3][i]==a[2][i]) a[3][i]+=a[2][i],a[2][i]=a[1][i],a[1][i]=0;
if (a[2][i]==a[1][i]) a[2][i]+=a[1][i],a[1][i]=0;
}
else if (x=='w')
for (int i=1;i<=4;++i)
{
t=bool(a[1][i])+bool(a[2][i])+bool(a[3][i])+bool(a[4][i]);
while (t>0&&!a[1][i]) a[1][i]=a[2][i],a[2][i]=a[3][i],a[3][i]=a[4][i],a[4][i]=0;
t--;
while (t>0&&!a[2][i]) a[2][i]=a[3][i],a[3][i]=a[4][i],a[4][i]=0;
t--;
while (t>0&&!a[3][i]) a[3][i]=a[4][i],a[4][i]=0;
t--;
if (a[1][i]==a[2][i]) a[1][i]+=a[2][i],a[2][i]=a[3][i],a[3][i]=a[4][i],a[4][i]=0;
if (a[2][i]==a[3][i]) a[2][i]+=a[3][i],a[3][i]=a[4][i],a[4][i]=0;
if (a[3][i]==a[4][i]) a[3][i]+=a[4][i],a[4][i]=0;
}
}
bool GG()
{
for (int i=1;i<=4;++i)
for (int j=1;j<=4;++j)
if (!a[i][j]) return 0;
return 1;
}
void qwq()
{
getch();
system("CLS");
printf("游戏结束!\n您的最终得分是%lld!\n",sum);
getch();
return;
}
char o;
void game()
{
while (1)
{
if (GG())
{
qwq();
getch();
break;
}
print();
Sleep(1000);
while (1)
{
u=rand()%4+1;
v=rand()%4+1;
if (!a[u][v])
{
a[u][v]=(rand()%2+1)*2;
sum+=a[u][v];
break;
}
}
print();
while (1)
{
o=getch();
if (o=='E') printf("E"),getchar(),getchar(),getchar(),getchar();
if (o=='N') printf("N"),getchar(),getchar(),getchar();
if (o=='w'&&move(-1,0)) {Move('w');break;}
if (o=='s'&&move(1,0)) {Move('s');break;}
if (o=='a'&&move(0,-1)) {Move('a');break;}
if (o=='d'&&move(0,1)) {Move('d');break;}
if ((!move(-1,0))&&(!move(0,-1))&&(!move(0,1))&&(!move(1,0))) break;
if (o=='E') Exit();
}
}
}
void fengmian()
{
NEW();
while (1)
{
system("CLS");
for (int i=0;pr[i];i++)
{
printf("%c",pr[i]);
if (pr[i]=='\n') Sleep(300);
Sleep(100);
}
string o;
cin>>o;
while (1)
{
if (o=="Start")
{
hide();
system("CLS");
for (int j=1;j<=4;++j)
for (int i=0;i<=4;++i)
cout<<member[i]<<member[i]<<member[i]<<member[i]<<endl;
gotoxy(hOut,0,20);
printf(" 您目前的得分是:%lld\n\n",sum);
printf(" 输入\"New\"以重新开始。\n\n");
printf(" 输入\"Exit\"以结束游戏。\n\n");
printf(" 通过'w','s','a','d'键,向上下左右方向合并数字。");
game();
ehide();
break;
}
if (o=="Exit") Exit();
cin>>o;
}
}
}
int main()
{
srand(time(0));
fengmian();
return 0;
}