先上效果圖
大致思路
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來顯示狀態