c++控制檯小程序——2048(新手簡易版)

先上效果圖

在這裏插入圖片描述

大致思路

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來顯示狀態

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章