先上效果图
大致思路
1.打印地图
老办法gotoxy函数
2.生成随机位置新数字
我在这部分加入了算法生成,因为随机生成通过时间改变来实现,因此如果当前位置有数字,时间改变坐标才变,若多次位置均有数字,界面就会停滞一段时间,算法使得很快就生成新的坐标
3.最麻烦的数字移动
首先使用键盘监听确定方向
然后我使用了3个大循环(1)移动,覆盖空格
(2)向当前方向合并一次(只有一次!!!)
(3)再次覆盖空格
为什么要有3个大循环?
首先(1)移动填补空格,这个毫无疑问
然后(2)合并一次!!!这个决对不可以循环,更不可以嵌套在(1)里面!!!举个例子,当前4 2 0 2,向左应该是4 4 0 0,如果按照上述错误方法,就会变成8 0 0 0
最后(3)也必不可少,由于(2)的特殊,不可以嵌套入(1),如下面这个例子:4 4 2 2
向左为8 4 0 0,但只有(1)(2)的话最后是8 0 4 0,这就需要再次移动覆盖
4.游戏结束
很简单,移动后无法生成新数字则结束游戏
代码
#include <iostream>
#include <ctime>
#include <windows.h>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <conio.h>
using namespace std;
int map[4][4] = {0}; //定义4*4地图
int g = 1; //主函数循环
int score = 0;
int move = 0; //排除无效方向
void gotoxy(short x, short y);
void start();
void newNumber();
void print();
void hide();
void toTop();
void toBottom();
void toLeft();
void toRight();
void changeMap();
void gameOver();
int main()
{
hide();
start();
newNumber();
while(g)
{
if (kbhit()!=0)
changeMap();
}
system("cls"); //打印分数
gotoxy(5,5);
cout << "your score: " << score;
return 0;
}
void hide() //隐藏光标
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(handle, &CursorInfo);//获取控制台光标信息
CursorInfo.bVisible = false; //隐藏控制台光标
SetConsoleCursorInfo(handle, &CursorInfo);
}
void gotoxy(short x, short y) //定位
{
COORD position = { x, y };
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOut, position);
}
void start() //初始化界面
{
gotoxy(20,3);
cout << "score: " << score;
for(int k=1;k<=7;)
{
for(int l=0;l<=16;)
{
gotoxy(l,k);
cout << "|";
l += 4;
}
k += 2;
}
for(int i=0;i<9;)
{
gotoxy(0,i);
cout << "+---+---+---+---+";
i += 2;
}
}
void print() //打印变化后的界面
{
system("cls");
start();
for(int i=0;i<4;i++)
{
for(int l=0;l<4;l++)
{
gotoxy(4*i+2,2*l+1);
if(map[i][l] != 0)
cout << map[i][l];
else
cout << " ";
}
}
gotoxy(20,3);
cout << "score: " << score;
}
void newNumber() //生成新数字坐标并打印
{
Sleep(500);
move = 0;
int f = 1;
while(f)
{
int h = 1;
srand((int)time(0));
int x = rand() % 4;
int y = rand() % 4;
int y2 = y;
if(map[x][y] != 0) //时间随机不行就算法生成
{
while(h)
{
x += 1;
y = y2;
if(x == 4)
x = 0;
for(int l=0;l<4;l++)
{
if(map[x][y] == 0)
{
h = 0;
break;
}
else
{
y += 1;
if(y == 4)
y = 0;
}
}
}
}
map[x][y] = 2;
f = 0;
gotoxy(4*x+2,2*y+1);
cout << map[x][y];
}
}
void toTop() //向上移动
{ //1.填补空位
for(int i=0;i<4;i++)
{
for(int l=1;l<=3;l++)
{
while(map[i][l] != 0 && map[i][l-1] == 0)
{
map[i][l-1] = map[i][l];
map[i][l] = 0;
if(l>1)
l--;
move = 1;
}
}
}
for(int m=0;m<4;m++) //2.合并相同
{
for(int n=0;n<3;n++)
{
if(map[m][n] != 0 && map[m][n+1] == map[m][n])
{
map[m][n] += map[m][n+1];
score += map[m][n+1];
map[m][n+1] = 0;
move = 1;
}
}
}
for(int j=0;j<4;j++) //再次填补空位
{
for(int k=1;k<=3;k++)
{
while(map[j][k] != 0 && map[j][k-1] == 0)
{
map[j][k-1] = map[j][k];
map[j][k] = 0;
if(k>1)
k--;
}
}
}
}
void toBottom() //向下移动
{
for(int i=0;i<4;i++)
{
for(int l=2;l>=0;l--)
{
while(map[i][l] != 0 && map[i][l+1] == 0)
{
map[i][l+1] = map[i][l];
map[i][l] = 0;
if(l<2)
l++;
move = 1;
}
}
}
for(int m=0;m<4;m++)
{
for(int n=3;n>=0;n--)
{
if(map[m][n] != 0 && map[m][n-1] == map[m][n])
{
map[m][n] += map[m][n-1];
score += map[m][n-1];
map[m][n-1] = 0;
move = 1;
}
}
}
for(int j=0;j<4;j++)
{
for(int k=2;k>=0;k--)
{
while(map[j][k] != 0 && map[j][k+1] == 0)
{
map[j][k+1] = map[j][k];
map[j][k] = 0;
if(k<2)
k++;
}
}
}
}
void toLeft() //向左移动
{
for(int i=1;i<4;i++)
{
for(int l=0;l<4;l++)
{
while(map[i][l] != 0 && map[i-1][l] == 0)
{
map[i-1][l] = map[i][l];
map[i][l] = 0;
if(i>1)
i--;
move = 1;
}
}
}
for(int m=0;m<3;m++)
{
for(int n=0;n<4;n++)
{
if(map[m][n] != 0 && map[m+1][n] == map[m][n])
{
map[m][n] += map[m+1][n];
score += map[m+1][n];
map[m+1][n] = 0;
move = 1;
}
}
}
for(int j=1;j<4;j++)
{
for(int k=0;k<4;k++)
{
while(map[j][k] != 0 && map[j-1][k] == 0)
{
map[j-1][k] = map[j][k];
map[j][k] = 0;
if(j>1)
j--;
}
}
}
}
void toRight() //向右移动
{
for(int i=2;i>=0;i--)
{
for(int l=0;l<4;l++)
{
while(map[i][l] != 0 && map[i+1][l] == 0)
{
map[i+1][l] = map[i][l];
map[i][l] = 0;
if(i<2)
i++;
move = 1;
}
}
}
for(int m=3;m>=0;m--)
{
for(int n=0;n<4;n++)
{
if(map[m][n] != 0 && map[m-1][n] == map[m][n])
{
map[m][n] += map[m-1][n];
score += map[m-1][n];
map[m-1][n] = 0;
move = 1;
}
}
}
for(int j=2;j>=0;j--)
{
for(int k=0;k<4;k++)
{
while(map[j][k] != 0 && map[j+1][k] == 0)
{
map[j+1][k] = map[j][k];
map[j][k] = 0;
if(j<2)
j++;
}
}
}
}
void changeMap() //键盘监听,组装函数
{
char key = getch();
switch (key)
{
case 'w':
case 'W':
toTop();
break;
case 's':
case 'S':
toBottom();
break;
case 'a':
case 'A':
toLeft();
break;
case 'd':
case 'D':
toRight();
break;
default:
break;
}
print();
gameOver();
if(move) //方向可移动进行下一步
newNumber();
}
void gameOver() //结束游戏(无法生成新数字)
{
g = 0;
for(int i=0;i<4;i++)
{
for(int l=0;l<4;l++)
{
if(map[i][l] == 0)
{
g = 1;
break;
break;
}
}
}
}
因为算法比较暴力所以后期出新数字会慢,所以增加了一个finish来显示状态