1. 程式人生 > >2048-控制檯版本

2048-控制檯版本

/最近修改2017/6/26/
/修改2017/7/4,修改之前各自填滿之後無法移動的錯誤,暫時未發現大的錯誤/
/最後修改2017/7/5,新增前景色,新增模式選擇,改善介面/
一.實現目標:
2048遊戲
二.要求:
1、在螢幕上顯示4*4的表格
2、隨機生成2、4數字及位置
3、顏色設定
三.執行環境和工具:
VC++6.0
四.實現步驟
0.遊戲邏輯:
把遊戲畫面想象成4*4的陣列,其中數值為0的位置表示空的格子,
有數值的位置代表對應的格子。然後對於每一行按列來遍歷,或者每一列按行來遍歷,實現每一行每一列的對應數字合併,直到出現2048的格子就勝利,否則就失敗.
1.編寫用於實現數字移動的方向函式


以向左移動為例:
把遊戲畫面想象成4*4的陣列,其中數值為0的位置表示空的格子,
先看其中一行,有四列,用一個變數k=0,從第一列開始,另一個變數j=1開始,代表k之後的列,開始遍歷。
如果第j列這個位置不為0的話,那麼之後可以分為3種情況:
第一種情況:第k列和第j列相同,這個時候就將第k列的數字加倍,第j列重置為0.
第二種情況:第k列為0,那麼就交換第k列和第j列的數字。
第三種情況:第k列和第j列都不為0,但是兩者不相等,這個時候,就把兩個數緊挨在一起,如果j和k原本就緊挨在一起,那麼什麼也不做。
而如果第j列為,也什麼也不做。
在向左移動的時候,每一行都向左移動,所以逐行相加,然後按列遍歷。
同理,向右移動,區別在於,向右是反向的按列遍歷,向上是逐列相加,按行遍歷,向右於向左移動是行列相反的遍歷。
每次移動,步數就+1,每次合併,就會加上當前合併的格子的數值。
2.編寫用於實現隨機數字和隨機位置的函式,以及遊戲結束函式,顯示格子函式,初始化函式,退出函式等

#define TARGET 2048
標記最終的目標,同時也是判斷遊戲是否結束的標誌之一,如果在格子中出現了2048的格子,玩家勝利,遊戲結束。另一種結束方式是,當所有的格子都被填滿的時候,同時不存在可以相互合併的格子,並且沒有2048的格子,遊戲結束,玩家失敗。
3.困難模式下隨機函式用來隨機出現數字2和4,使得出現的概率之比為1:10,保證遊戲時間不至於過短。
正常模式下隨機函式2和4出現概率之比為1:4
4.Begin()函式用來將陣列初始化為0,包括分數和步數的清零
但是這個只在遊戲開始的時候執行一次。
5.顯示格子函式:設定好列印顏色,以及格子間距
五.程式執行:
這裡寫圖片描述

這裡寫圖片描述
這裡寫圖片描述
六.以下為完整程式碼

#include<conio.h>
#include<time.h>
#include<Windows.h>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#define TARGET 2048         //最終目標
HANDLE myHandle;            //控制控制代碼,物件
const WORD FORE_BLUE    =FOREGROUND_BLUE;           //藍色文字
const WORD FORE_GREEN   =FOREGROUND_GREEN;          //綠色文字
const WORD FORE_RED     =FOREGROUND_RED;            //紅色文字  
const WORD FORE_YELLOW  =FORE_RED|FORE_GREEN;       //黃色文字,其他顏色用三原色搭配
const WORD FORE_GRAY    =FORE_BLUE|FORE_GREEN;      //紫色文字
const WORD BACK_BLUE    =BACKGROUND_BLUE;           //藍色背景
const WORD BACK_GREEN   =BACKGROUND_GREEN;          //綠色背景
const WORD BACK_RED     =BACKGROUND_RED;            //紅色背景  
const WORD BACK_YELLOW  =BACK_RED|BACK_GREEN;       //黃色背景,其他顏色用三原色搭配
const WORD BACK_GRAY    =BACK_BLUE|BACK_GREEN;      //紫色背景
int pass=0;                     //用來判斷是否需要返回
int Game;                       //標記遊戲是否結束
int ax[4][4];                   //控制的二維陣列
int score=0;                    //記錄分數
int step=0;                     //記錄所花費的步數
void Up();                      //向上移動數字,使其相同的合成,不同的緊湊
void Down();                    //向下
void Right();                   //向右    
void Left();                    //向左
void Movement();                //正常移動
void Movement_2();              //困難移動
void GAME_OVER();               //標記遊戲是否結束
void Exit();                    //退出函式
void Begin();                   //初始化陣列
void Run();                     //將隨機出現的數字放入隨機的座標當中,概率修改
void Run_2();                   //概率之比為1:10
void Show();                    //顯示格子
void Mode1();                   //正常模式
void Mode2();                   //困難模式
void Help();                    //幫助手冊
void choice();                  //選擇
void Menu();                    //選單

void Help()
{
    system("cls");
    HANDLE handle_out=GetStdHandle(STD_OUTPUT_HANDLE);      //獲取標準輸入裝置控制代碼
    CONSOLE_SCREEN_BUFFER_INFO csbi;                        //定義視窗緩衝區資訊結構體
    GetConsoleScreenBufferInfo(handle_out,&csbi);           //獲得視窗緩衝區資訊
    SetConsoleTextAttribute(handle_out,FORE_YELLOW);            //設定列印顏色為綠色
    printf("            --------------------------------------------\n");
    printf("            ********************************************\n\n");
    printf("            操作說明:\n↓:下   ←:左  ↑:上  →:右  ESC鍵:退出\n\n");
    printf("            遊戲介紹:每次選擇一個方向滑動,每次滑動,除了數字向該方向靠攏之外,系統會在空格處生成隨機數字2或者4,\n");
    printf("            相同數字可以相加。如果拼湊出“2048”這個數字,則遊戲勝利!\n");
    system("pause");
    system("cls");
}

void Left()
{
    int i,j,k;
    for(i=0;i<4;i++)            //行數
    {       
        for(j=1,k=0;j<4;j++)    //每一行按列來遍歷
        {
            if(ax[i][j]!=0)
            {
                if(ax[i][k]==ax[i][j])
                {
                    ax[i][k]<<=1;
                    score+=ax[i][k];
                    ax[i][j]=0;
                    k++;
                }
                else if(ax[i][k]==0)
                {
                    ax[i][k]=ax[i][j];
                    ax[i][j]=0;
                    k++;
                }
                else
                {
                    k++;
                    ax[i][k]=ax[i][j];
                    if(k!=j)
                    {
                        ax[i][j]=0;
                    }
                }
            }
        }
    }
    step++;
}

void Right()
{
    int i,j,k;
    for(i=0;i<4;i++)
    {
        for(j=2,k=3;j>=0;j--)
        {
            if(ax[i][j]!=0)
            {
                if(ax[i][j]==ax[i][k])
                {
                    ax[i][k]<<=1;
                    score+=ax[i][k];
                    ax[i][j]=0;
                    k--;
                }
                else if(ax[i][k]==0)
                {
                    ax[i][k]=ax[i][j];
                    ax[i][j]=0;
                    k--;
                }
                else 
                {
                    k--;
                    ax[i][k]=ax[i][j];
                    if(j!=k)
                    {
                        ax[i][j]=0;
                    }
                }
            }
        }
    }
    step++;
}

void Up()
{
    int n,i,j,k;
    for(n=0;n<4;n++)
    {
        k=0;
        for(i=0;i<4;i++)
        {
            if(ax[i][n]!=0)
            {
                for(j=i;j>k;j--)
                {
                    if(ax[j-1][n]==0)       //上一行沒有數字
                    {
                        ax[j-1][n]=ax[j][n];
                        ax[j][n]=0;
                    }
                    else if(ax[j-1][n]==ax[j][n])
                    {
                        ax[j-1][n]=2*ax[j-1][n];
                        score+=ax[j-1][n];
                        ax[j][n]=0;
                        k=j;
                        Sleep(1);
                        break;
                    }
                    else
                        break;
                }
            }
        }
    }
    step++;
}

void Down()
{
    int i,j,k;
    for(j=0;j<4;j++)
    {
        for(i=2,k=3;i>=0;i--)
        {
            if(ax[i][j]!=0)
            {
                if(ax[i][j]==ax[k][j])
                {
                    ax[k][j]<<=1;
                    score+=ax[k][j];
                    ax[i][j]=0;
                    k--;
                }
                else if(ax[k][j]==0)
                {
                    ax[k][j]=ax[i][j];
                    ax[i][j]=0;
                    k--;
                }
                else 
                {
                    k--;
                    ax[k][j]=ax[i][j];
                    if(k!=i)
                    {
                        ax[i][j]=0;
                    }
                }
            }
        }
    }
    step++;
}

void Movement()
{
    if(kbhit())
    {
        switch(getch())
        {
            case 27:
                Exit();
                break;
            case 75:        //向左
                Left();
                Run();
                Show();
                break;
            case 72:        //向上
                Up();
                Run();
                Show();
                break;
            case 77:        //向右
                Right();
                Run();
                Show();
                break;
            case 80:        //向下
                Down();
                Run();
                Show();
                break;
            default:
                break;
        }
    }
}
void Movement_2()
{
    if(kbhit())
    {
        switch(getch())
        {
            case 27:
                Exit();
                break;
            case 75:        //向左
                Left();
                Run_2();
                Show();
                break;
            case 72:        //向上
                Up();
                Run_2();
                Show();
                break;
            case 77:        //向右
                Right();
                Run_2();
                Show();
                break;
            case 80:        //向下
                Down();
                Run_2();
                Show();
                break;
            default:
                break;
        }
    }
}
void Exit()
{
    int i=0;
    printf("\n退出中");
    for(i=4;i>0;--i)
    {
        Sleep(200);
        printf(".");
    }
    exit(0);
}

void Begin()
{
    int i=0,j=0;
    score=0;        //分數清零
    Game=0;         //初始遊戲
    step=0;         //步數清零
    SetConsoleTitleA("遊戲:2048");
    for(i=0;i<4;i++)
    {
        for(j=0;j<4;j++)
        {
            ax[i][j]=0;
        }
    }
}

void Run()
{
    int x,y,temp,num;
    srand((int)time(0));
    while(1)
    {
        x=rand()%4;
        y=rand()%4;
        temp=rand()%5;      //概率之比為1:4
        if(temp==1)
            num=4;
        else
            num=2;
        if(ax[x][y]==0)
        {
            ax[x][y]=num;
            break;
        }
    }
}

void Run_2()
{
    int x,y,temp,num;
    srand((int)time(0));
    while(1)
    {
        x=rand()%4;
        y=rand()%4;
        temp=rand()%10;     //概率之比為1:10
        if(temp==1)
            num=4;
        else
            num=2;
        if(ax[x][y]==0)
        {
            ax[x][y]=num;
            break;
        }
    }
}

void GAME_OVER()
{
    int i,j;
    for(i=0;i<4;i++)
    {
        for(j=0;j<3;j++)
        {
            if(ax[i][j]==ax[i][j+1]||ax[j][i]==ax[j+1][i])
            {
                Game=0;//同列中的存在刻意繼續合併的數字,遊戲繼續
                return ;
            }
            else if(ax[i][j]==0||ax[i][j+1]==0||ax[j][i]==0||ax[j+1][i]==0)
            {
                Game=0;
                return ;
            }
            else if(ax[i][j]==TARGET||ax[i][j+1]==TARGET||ax[j][i]==TARGET||ax[j+1][i]==TARGET)
            {
                Game=2;
                return;         //存在2048,遊戲結束
            }
        }
    }
    Game =1;                    //不存在2048,但是同行同列中沒有能夠合併的數字,並且沒有空位置,遊戲結束
}


void Show()
{
    int i,j;
    HANDLE handle_out=GetStdHandle(STD_OUTPUT_HANDLE);      //獲取標準輸入裝置控制代碼
    CONSOLE_SCREEN_BUFFER_INFO csbi;                        //定義視窗緩衝區資訊結構體
    GetConsoleScreenBufferInfo(handle_out,&csbi);           //獲得視窗緩衝區資訊
    system("cls");
    SetConsoleTextAttribute(handle_out,FORE_GREEN);         //設定列印顏色為綠色
    printf("            --------------------------------------------\n");
    printf("            ********************************************\n");       

    //上界
    SetConsoleTextAttribute(handle_out,FORE_RED);           //設定列印顏色為紅色
    printf("                      |----|----|----|----|\n");            

        //格子上半部分
    for(i=0;i<4;i++)
    {
        SetConsoleTextAttribute(handle_out,FORE_RED);       //設定列印顏色為紅色
        printf("                      |");
        for(j=0;j<4;j++)
        {
            if(ax[i][j]!=0)
            {
                SetConsoleTextAttribute(handle_out,FORE_YELLOW);        //設定列印顏色為黃色
                printf("%4d|",ax[i][j]);
            }
            else
            {
                SetConsoleTextAttribute(handle_out,FORE_YELLOW);        //設定列印顏色為黃色
                printf("    |");
            }
        }
        printf("\n");
        SetConsoleTextAttribute(handle_out,FORE_RED);                   //設定列印顏色為紅色
        printf("                      |----|----|----|----|\n");
    }
                    //格子下半部分        
    SetConsoleTextAttribute(handle_out,FORE_GREEN);                     //設定列印顏色為綠色
    printf("            --------------------------------------------\n");
    printf("            ********************************************\n");   
    printf("            ↓:下   ←:左  ↑:上  →:右  ESC鍵:退出\n\n");
    SetConsoleTextAttribute(handle_out,FORE_RED);                       //設定列印顏色為紅色
    printf("            ■▲□■○□■○□            ■○□■○□■○□\n");
    printf("            ▲▲");
    SetConsoleTextAttribute(handle_out,FORE_YELLOW);                    //設定答應顏色為黃色
    printf("分數:%-3d ",score);
    SetConsoleTextAttribute(handle_out,FORE_RED);
    printf("▲□             ■○"); 
    SetConsoleTextAttribute(handle_out,FORE_YELLOW);
    printf("步數:%-3d ",step);
    SetConsoleTextAttribute(handle_out,FORE_RED);
    printf("○□\n");
    printf("            ■▲          ○□            ■○          ○□\n");
    printf("            ■▲▲■▲□■○□            ■○□■○□■○□\n");

    //下界
    if(Game==1)                             //遊戲結束,失敗
    {   printf("\n            Sorry,you losed!!!!!!!!!!!!!!!!!!!!!!\n");
        system("pause");
        Exit();
    }
     if(Game==2)                            //遊戲成功,勝利
    {       
        printf("\n            Good!YOU  WIN!!!!!!!!!!!!!!!!!!!!!!!!\n");
        system("pause");
        Exit();
    }
}

void Mode1()
{
    Begin();                    //遊戲初始化
    Run();                      //隨機一個數字
    Run();
    Show();
    while(1)
    {       
        GAME_OVER();            //每次都判斷一次遊戲是否結束
        if(Game==1||Game==2)
        {
            break;
        }
        Movement();
    }
    Show();
    return ;
}

void Mode2()
{
    Begin();
    Run_2();
    Run_2();
    Show();
    while(1)
    {
        GAME_OVER();
        if(Game==1||Game==2)
        {
            break;
        }
        Movement_2();
    }
    Show();
    return ;
}

void Menu()
{
    SetConsoleTitleA("遊戲:2048");
    HANDLE handle_out=GetStdHandle(STD_OUTPUT_HANDLE);      //獲取標準輸入裝置控制代碼
    SetConsoleTextAttribute(handle_out,FORE_GREEN);         //設定列印顏色為綠色
    printf("            --------------------------------------------\n");
    printf("            ********************************************\n");
    SetConsoleTextAttribute(handle_out,FORE_YELLOW);            //設定列印顏色為綠色
    printf("                              選單\n");
    SetConsoleTextAttribute(handle_out,FORE_GREEN|FORE_YELLOW);         //設定列印顏色為青色
    printf("                          a.正常模式\n");
    printf("                          b.困難模式\n");
    printf("                          c.幫助手冊\n");
    printf("                          d.遊戲結束\n");
    printf("                          請輸入你的選擇\n");
}

void choice()
{
    char ch='0';
    scanf(" %c",&ch);
        switch(ch)
        {
        case 'a':
            Mode1();
            break;
        case'b':
            Mode2();
            break;
        case'c':
            Help();
            break;
        case'd':
            exit(0);
            break;
        default:
            break;
        }
}

int main(void)
{
    while(1)
    {
        Menu();
        choice();
    }
    return 0;
}