游戲開發(fā) mine

mine開發(fā)

1.前期準(zhǔn)備

1.1工具:VC,easyx

基礎(chǔ)知識:循環(huán),數(shù)組,函數(shù)

1.2mine區(qū)地圖繪制

我們做一個9行9列的二維數(shù)組,-1和0代表有mine和無mine
這個數(shù)組最好是全局,這樣很多函數(shù)都可以訪問得到(注意全局?jǐn)?shù)組自動初始化為0)

需要的頭文件和宏定義如下:

#include<stdio.h>
#include<graphics.h>
#define ROW 9//9行9列的mine區(qū)表格
#define COL 9
#define MINE_WID 40//圖片寬度
int mine[ROW][COL];

1.3打印 printMap()函數(shù)

先做點簡單的工作,寫一個輸出數(shù)組的函數(shù),方便后面調(diào)用

void printMap()
{
    for(int i=0;i<ROW;i++)
    {
        for(int j=0;j<COL;j++)
        {
            printf("%3d",mine[i][j]); //格式控制一下,一個數(shù)字占3個
        }
        printf("\n");//每一行就輸出一個換行
    }
}

main()調(diào)用一下

int main()
{
    printMap();
    return 0;
}
image-20210205180152573

資源文件有數(shù)字標(biāo)記,空白格子,紅旗,地圖,以及mine,復(fù)制進入工程的當(dāng)前目錄

圖片定義一個數(shù)組,作為全局變量,這個數(shù)組可被各個函數(shù)訪問修改

IMAGE img[12];

1.4初始化

void gameInit()
{
    loadimage(&img[0],"./0.png",MINE_WID,MINE_WID);
    loadimage(&img[1],"./1.png",MINE_WID,MINE_WID);
    loadimage(&img[2],"./2.png",MINE_WID,MINE_WID);
    loadimage(&img[3],"./3.png",MINE_WID,MINE_WID);
//是不是沒完沒了?
}

比較繁瑣,需要簡化處理一下

//上面的代碼要復(fù)制12次,我們用循環(huán)處理簡化代碼
void gameInit()
{
    char temp[20]=" "; 
    for(int i=0;i<12;i++)
    {
        sprintf(temp,"%d.jpg",i);//把路徑+i吸入temp變量
        loadimage(&img[i],temp,MINE_WID,MINE_WID);
        
    }
}

資源加載完了,我們開始繪制圖片(貼圖)

void gameDraw()
{
    for(int i=0;i<ROW;i++)
    {
        for(int j=0;j<COL;j++)
        {
            if(mine[i][j]==0) //初始化開始為0的時候,全部填充空白磚塊
            {
                 putimage(i*MINE_WID,j*MINE_WID,&img[0]);
            }
        }
    }
}

現(xiàn)在主函數(shù)調(diào)用一下

int main()
{
    initgraph(MINE_WID*ROW,MINE_WID*COL,1); //參數(shù) 1,是同時繪圖與打開控制臺
    gameInit(); //資源初始化
    gameDraw();//繪制
    printMap();//控制臺作為后臺數(shù)據(jù)幫忙分析
    system("pause");//記得 #include<stdlib>
    
    return 0;
}
image-20210207121625293

1.5開始布mine

mine的數(shù)量做一個宏定義,方便后期修改

define MAX_MINE 9 //mine先少布置一點 方便分析

//在二維數(shù)組里面隨機獲取9個下標(biāo),賦值為-1
void gameInit()
{
    //隨機化給下標(biāo)為x,y的賦值為-1,標(biāo)記為mine區(qū),并且要判斷不要有 重合的下標(biāo)
    int x,y;
    for(int m=0;m<MAX_MINE;)//注意m++的操作,不在這里
    {
        //srand((unsigned int)time(0)); // 此語句要放在for 循環(huán)體之外
        //加上上一句srand函數(shù),同時和#include<time.h>即為真隨機,每次布mine不一樣
        x=rand()%9;
        y=rand()%9;
        //判斷是否重復(fù)
        if(mine[x][y]==0) //沒有mine的情況下,就埋mine,有mine就沒做這一步
        {
            mine[x][y]=-1;
            //當(dāng)布mine成功了,m才++
            m++;//放在判斷這里++,才會保證一定布滿9個mine
        }
    }
    char temp[20]=" "; 
    for(int i=0;i<12;i++)
    {
        sprintf(temp,"%d.jpg",i);//
        loadimage(&img[i],temp,MINE_WID,MINE_WID);
        
    }
}

布mine之后運行看一下

image-20210209102851067

多次運行,發(fā)現(xiàn)真隨機的mine區(qū)發(fā)生變化,由于我們在gameDraw()繪圖函數(shù)里面只定義了當(dāng)數(shù)值為0,沒有mine的時候繪制空白磚塊,所以當(dāng)數(shù)值為-1的時候,需要繪制地mine

1.6繪制mine

//根據(jù)后臺數(shù)據(jù),給出繪制mine區(qū)定義
//為-1布mine,增加 if else if分支,記住還要有數(shù)字選項的分支,所以不要只寫else
void gameDraw()
{
    for(int i=0;i<ROW;i++)
    {
        for(int j=0;j<COL;j++)
        {
            if(mine[i][j]==0) //初始化開始為0的時候,全部填充空白磚塊
            {
                 putimage(i*MINE_WID,j*MINE_WID,&img[0]);
            }
            else if(mine[i][j]==-1) //當(dāng)為-1的時候布mine
            {
                putimage(i*MINE_WID,j*MINE_WID,&img[9]); //新增一個else分支即可,mine是9.jgp,第10張圖
            }
        }
    }
}
image-20210209103711589

對比一下數(shù)據(jù),行列是顛倒的,將繪圖函數(shù)里面新增兩個變量,對應(yīng)起來

void gameDraw()
{
    for(int i=0;i<ROW;i++)
    {
        for(int j=0;j<COL;j++)
        {
            int x=j*MINE_WID;
            int y=i*MINE_WID;
            if(mine[i][j]==0) //初始化開始為0的時候,全部填充空白磚塊
            {
                 putimage(x,y,&img[0]);
            }
            else
            {
                putimage(x,y,&img[9]); // 注意到 if else 后面會更新為 if else if,防止條件空間不完備
            }
        }
    }
}

1.7布mine的數(shù)字

現(xiàn)在mine區(qū)有了,那么一個數(shù)字代表周圍有多少mine,那么有一個mine,周圍數(shù)字全部+1

注意,數(shù)字進行累加,但是不要把自己也是mine區(qū)的數(shù)字-1也給變化了,在gameInit()里面進行更改

void gameInit()
{
    //隨機化給下標(biāo)為x,y的賦值為-1,標(biāo)記為mine區(qū),并且要判斷不要有 重合的下標(biāo)
    int x,y;
    srand((unsigned int)time(0));
    for(int m=0;m<MAX_MINE;)//注意m++的操作,不在這里
    {

        x=rand()%9;
        y=rand()%9;
        //判斷是否重復(fù)
        if(mine[x][y]==0) //沒有mine的情況下,就埋mine,有mine就沒做了
        {
            mine[x][y]=-1;
            //當(dāng)布mine成功了,m才++
            m++;//放在判斷這里++,才會保證一定布滿9個mine
        }
    }
    // 遍歷數(shù)組,對mine九宮格進行+1操作
    for(int a=0;a<ROW;a++) // VC6在cpp文件不能重復(fù)定義i,j。所以避開一下
    {
        for(int b=0;b<COL;b++)
        {
            //首先要找到是mine的i,j
            if(mine[a][b]==-1) //再嵌套一個二層循環(huán)
            {
                for(int k=a-1;k<=a+1;k++)
                {
                    for(int q=b-1;q<=b+1;q++)
                    {
                        //周圍的遍歷,只對非mine區(qū)進行操作
                        if(mine[k][q]!=-1)
                        {
                            mine[k][q]++;
                        }
                    }
                }
                
            }
        }
    }
    
    char temp[20]=" "; 
    for(int i=0;i<12;i++)
    {
        sprintf(temp,"%d.jpg",i);//
        loadimage(&img[i],temp,MINE_WID,MINE_WID);
        
    }
}
image-20210209105554555

嘗試輸出一下,程序可能會假死,可能不會,取決于編譯器對數(shù)組上下限±1的嚴(yán)格程度,以及硬件反應(yīng)速度。

問題出在哪里?思考一下!

1.8mine區(qū)在邊界,-1,+1操作會越界,內(nèi)存會溢出,訪問不到!

小技巧:增加一個 ±1,作為輔助圈,在11*11格子里面的判斷。
#include<stdio.h>
#include<graphics.h>
#include<stdlib.h>
#include<time.h>
#define ROW 9//9行9列的mine區(qū)表格
#define COL 9
#define MINE_WID 40
#define MAX_MINE 9
int mine[ROW+2][COL+2]; //輔助圈,在這里+2了
IMAGE img[12];
那么,0行,10行與0列,11列成為輔助圈

判斷的數(shù)字增加的行列從a=1,到小于row+1(b=1到b<COL+1)

for(int a=1;a<ROW+1;a++) // VC6在cpp文件不能重復(fù)定義i,j。所以避開一下
    {
        for(int b=1;b<COL+1;b++)
        {
            //首先要找到是mine的i,j
            if(mine[a][b]==-1) //再嵌套一個二層循環(huán)
            {
                for(int k=a-1;k<=a+1;k++)
                {
                    for(int q=b-1;q<=b+1;q++)
                    {
                        //周圍的遍歷,只對非mine區(qū)進行操作
                        if(mine[k][q]!=-1)
                        {
                            mine[k][q]++;
                        }
                    }
                }
                
            }
        }
    }
image-20210209115651732

現(xiàn)在沒有內(nèi)存溢出的隱患了

我們先輸出輔助區(qū),printMap()里面的ROW、COL行列分別+2

void printMap()
{
    for(int i=0;i<ROW+2;i++) //更新輔助區(qū)  i,j循環(huán)變量最好是在最開始初始化,不要放在for循環(huán)體里隨用隨申請
    {
        for(int j=0;j<COL+2;j++)
        {
            printf("%3d",mine[i][j]);
        }
        printf("\n");
    }
}
image-20210209120119516

但是輔助圈現(xiàn)在作為不越界訪問幫忙計數(shù),是不能布mine的

輔助圈可以有數(shù)字,但是不能有-1布mine,我們修改rand功能 從1到9布mine

       
//x=rand()%9//從0到8
//y=rand()%9//從0到8
        x=rand()%9+1; //產(chǎn)生從1到9
        y=rand()%9+1;
//繪圖是mine數(shù)組里面的 1行到9行,1列到9列
void gameDraw()
{
    for(int i=1;i<ROW+1;i++)
    {
        for(int j=1;j<COL+1;j++)
        {
            int x=(j-1)*MINE_WID;//同步更新下標(biāo)
            int y=(i-1)*MINE_WID;
            if(mine[i][j]==0) //初始化開始為0的時候,全部填充空白磚塊
            {
                 putimage(x,y,&img[0]);
            }
            else if(mine[i][j]==-1) //當(dāng)為-1的時候布mine
            {
                putimage(x,y,&img[9]); // 之前的if else更新為多分支鏈
            }
        }
    }
}

void printMap() //數(shù)組作為儲存數(shù)據(jù),把外圈也繪制出來
{
    for(int i=0;i<ROW+2;i++)
    {
        for(int j=0;j<COL+2;j++)
        {
            printf("%3d",mine[i][j]);
        }
        printf("\n");
    }
}

現(xiàn)在前后臺就對應(yīng)上了

image-20210209131907167

1.9數(shù)字繪制

然后根據(jù)數(shù)組里面的數(shù)字,填充mine區(qū)標(biāo)記數(shù)字,在drawMap()函數(shù)里面修改一下

void gameDraw()
{
    for(int i=1;i<ROW+1;i++)
    {
        for(int j=1;j<COL+1;j++)
        {
            int x=(j-1)*MINE_WID;//同步更新下標(biāo)
            int y=(i-1)*MINE_WID;
            if(mine[i][j]>=0&&mine[i][j]<=8) //初始化開始為0的時候,全部填充空白磚塊
            {
                 putimage(x,y,&img[mine[i][j]]); //根據(jù)mine[i][j]的數(shù)字來繪制對應(yīng)的圖片,注意圖片的文件名要與自己顯示的東西相符合
            }
            else if(mine[i][j]==-1) //當(dāng)為-1的時候布mine
            {
                putimage(x,y,&img[9]);
            }
        }
    }
}

運行調(diào)試多次,驗證隨機性,并觀察數(shù)字與mine區(qū)是否對應(yīng)正確

image-20210209132307371
image-20210209132449688

tips:這里我們更新一下,完整代碼如下

#include<stdio.h>
#include<graphics.h>
#include<stdlib.h>
#include<time.h>
#define ROW 9//9行9列的mine區(qū)表格
#define COL 9
#define MINE_WID 40
#define MAX_MINE 9
int mine[ROW+2][COL+2];
IMAGE img[12];

void printMap() //數(shù)組作為儲存數(shù)據(jù),把外圈也繪制出來
{
    for(int i=0;i<ROW+2;i++)
    {
        for(int j=0;j<COL+2;j++)
        {
            printf("%3d",mine[i][j]);
        }
        printf("\n");
    }
}
//在二維數(shù)組里面隨機獲取9個下標(biāo),賦值為-1
void gameInit()
{
    //隨機化給下標(biāo)為x,y的賦值為-1,標(biāo)記為mine區(qū),并且要判斷不要有 重合的下標(biāo)
    int x,y,i,j;
    srand((unsigned int)time(0));
    for(int m=0;m<MAX_MINE;)//注意m++的操作,不在這里
    {

        x=rand()%9+1;
        y=rand()%9+1;
        //判斷是否重復(fù)
        
        if(mine[x][y]==0) //沒有mine的情況下,就埋mine,有mine就沒做了
        {
            mine[x][y]=-1;
            //當(dāng)布mine成功了,m才++
            m++;//放在判斷這里++,才會保證一定布滿9個mine
        }
        
    }
    // 遍歷數(shù)組,對mine九宮格進行+1操作.
for(int a=1;a<ROW+1;a++) // VC6在cpp文件不能重復(fù)定義i,j。所以避開一下
    {
        for(int b=1;b<COL+1;b++)
        {
            //首先要找到是mine的i,j
            if(mine[a][b]==-1) //再嵌套一個二層循環(huán)
            {
                for(int k=a-1;k<=a+1;k++)
                {
                    for(int q=b-1;q<=b+1;q++)
                    {
                        //周圍的遍歷,只對非mine區(qū)進行操作
                        if(mine[k][q]!=-1)
                        {
                            mine[k][q]++;
                        }
                    }
                }
                
            }
        }
    }



    
    
    char temp[20]=" "; 
    for( i=0;i<12;i++)
    {
        sprintf(temp,"%d.jpg",i);//
        loadimage(&img[i],temp,MINE_WID,MINE_WID);
        
    }
}
//繪圖是mine數(shù)組里面的 1行到9行,1列到9列
void gameDraw()
{
    for(i=1;i<ROW+1;i++) //遍歷數(shù)據(jù)區(qū)域
    {
        for(j=1;j<COL+1;j++)
        {
            int x=(j-1)*MINE_WID;//同步更新下標(biāo)
            int y=(i-1)*MINE_WID;
            if(mine[i][j]>=0&&mine[i][j]<=8) //初始化開始為0的時候,全部填充空白磚塊
            {
                 putimage(x,y,&img[mine[i][j]]); //根據(jù)mine[i][j]的數(shù)字來繪制對應(yīng)的圖片,注意圖片的文件名要與自己顯示的東西相符合
            }
            else if(mine[i][j]==-1) //當(dāng)為-1的時候布mine
            {
                putimage(x,y,&img[9]);
            }
        }
    }
}
 int main()
{
    initgraph(MINE_WID*ROW,MINE_WID*COL,1); //參數(shù) 1,是同時繪圖與打開控制臺
    gameInit(); //資源初始化
    gameDraw();//繪制
    printMap();//控制臺作為后臺數(shù)據(jù)幫忙分析
    system("pause");//記得 #include<stdlib>
    
    return 0;
}

2.游戲加密與交互操作

2.1加密

剛剛只是做好了數(shù)據(jù)系統(tǒng),現(xiàn)在我們要做加密掩蓋和交互,不然直接顯示最終的結(jié)果了。

加密格子,把數(shù)組里面(數(shù)據(jù)區(qū),不要包含輔助圈)每一個值+一個數(shù),這里為20

for(i=1;i<=ROW;i++) //  i,j循環(huán)變量需要在前面定義
{
    for(j=1;j<=COL;j++)
    {
        mine[i][j]+=20;
    }
}

我們更新一下gameInit()函數(shù),如果編譯器對臨時下標(biāo)i,j檢查嚴(yán)格,就不要在for循環(huán)里面反復(fù)int i=0,重復(fù)使用下標(biāo)也可以。

void gameInit()
{
    //隨機化給下標(biāo)為x,y的賦值為-1,標(biāo)記為mine區(qū),并且要判斷不要有 重合的下標(biāo)
    int x,y,i,j;
    srand((unsigned int)time(0));
    for(int m=0;m<MAX_MINE;)//注意m++的操作,不在這里
    {

        x=rand()%9+1;
        y=rand()%9+1;
        //判斷是否重復(fù)
        
        if(mine[x][y]==0) //沒有mine的情況下,就埋mine,有mine就沒做了
        {
            mine[x][y]=-1;
            //當(dāng)布mine成功了,m才++
            m++;//放在判斷這里++,才會保證一定布滿9個mine
        }
        
    }
    // 遍歷數(shù)組,對mine九宮格進行+1操作.
for(int a=1;a<ROW+1;a++) // VC6在cpp文件不能重復(fù)定義i,j。所以避開一下
    {
        for(int b=1;b<COL+1;b++)
        {
            //首先要找到是mine的i,j
            if(mine[a][b]==-1) //再嵌套一個二層循環(huán)
            {
                for(int k=a-1;k<=a+1;k++)
                {
                    for(int q=b-1;q<=b+1;q++)
                    {
                        //周圍的遍歷,只對非mine區(qū)進行操作
                        if(mine[k][q]!=-1)
                        {
                            mine[k][q]++;
                        }
                    }
                }
                
            }
        }
    }

for(i=1;i<=ROW;i++)
{
    for(j=1;j<=COL;j++)
    {
        mine[i][j]+=20;
    }
}



    
    
    char temp[20]=" "; 
    for(i=0;i<12;i++) //對于檢查嚴(yán)格的編譯器,臨時變量可重復(fù)使用了,不要再int i=0
    {
        sprintf(temp,"%d.jpg",i);//
        loadimage(&img[i],temp,MINE_WID,MINE_WID);
        
    }
}

加密之后,數(shù)據(jù)區(qū)+20,圖沒有貼了,未加密前數(shù)據(jù)最小是-1,最大是8

+20之后,最小是19,最大是28,增加分支判斷,在這個區(qū)域覆蓋掩蓋圖片(這個圖片可以仍然為空白,為了掩飾效果,我們換一個不一樣的圖)

image-20210209133324661

繪圖函數(shù)更新

void gameDraw()
{
    for(int i=1;i<ROW+1;i++)
    {
        for(int j=1;j<COL+1;j++)
        {
            int x=(j-1)*MINE_WID;//同步更新下標(biāo)
            int y=(i-1)*MINE_WID;
            if(mine[i][j]>=0&&mine[i][j]<=8) //初始化開始為0的時候,全部填充空白磚塊
            {
                 putimage(x,y,&img[mine[i][j]]); //根據(jù)mine[i][j]的數(shù)字來繪制對應(yīng)的圖片,注意圖片的文件名要與自己顯示的東西相符合
            }
            else if(mine[i][j]==-1) //當(dāng)為-1的時候布mine
            {
                putimage(x,y,&img[9]);
            }
            else if(mine[i][j]>=19&&mine[i][j]<=28) //所有的數(shù)字在-1到19范圍,+20之后在19到28貼掩蓋圖片
            {
                putimage(x,y,&img[10]); //貼掩蓋圖片

            }
        }
    }
}
image-20210209134100539

2.2鼠標(biāo)操作

開頭增加鼠標(biāo)消息定義 MOUSEMSG msg;
任務(wù):點擊之后,加密后的數(shù)據(jù)解密(實現(xiàn)方法??)
點擊之后,鼠標(biāo)消息一般配合 無限循環(huán)反復(fù)貼圖!

#include<stdio.h>
#include<graphics.h>
#include<stdlib.h>
#include<time.h>
#define ROW 9//9行9列的mine區(qū)表格
#define COL 9
#define MINE_WID 40
#define MAX_MINE 9
int mine[ROW+2][COL+2];
IMAGE img[12];
MOUSEMSG msg;
void gameMouse()
{
    if(MouseHit())
    {
        msg=GetMouseMsg(); //注意大小寫
        //掃mine有標(biāo)記功能,判斷鼠標(biāo)左右鍵。左鍵確定,右鍵標(biāo)記為紅旗
        if(msg.uMsg==WM_LBUTTONDOWN)
        {
           //加密的格子進行減操作
            mine[msg.y/MINE_WID+1][msg.x/MINE_WID+1]-=20;
            //這里的y和x對調(diào),是因為橫向是x,縱向是y,然后只繪制數(shù)據(jù)區(qū)
            
        }
        else if(msg.uMsg==WM_RBUTTONDOWN)
        {
            
        }
            
    }
    
            
}

現(xiàn)在我們在主函數(shù)調(diào)用試一下,要反復(fù)繪圖,記得主函數(shù)中把點擊操作與繪圖操作放入死循環(huán)中

 int main()
{
    initgraph(MINE_WID*ROW,MINE_WID*COL,1); //參數(shù) 1,是同時繪圖與打開控制臺
    gameInit(); //資源初始化
    while(1)//死循環(huán)重復(fù)繪圖
    
    {
        gameDraw();//繪制

        gameMouse();
    }
    printMap();//控制臺作為后臺數(shù)據(jù)幫忙分析
    system("pause");//記得 #include<stdlib>
    
    return 0;
}

image-20210209135154001

掃mine左鍵是做什么?
右鍵是做什么??

void gameMouse()
{
    if(MouseHit())
    {
        msg=GetMouseMsg(); //注意大小寫
        //掃mine有標(biāo)記功能,判斷鼠標(biāo)左右鍵。左鍵確定,右鍵標(biāo)記為紅旗
        if(msg.uMsg==WM_LBUTTONDOWN)
        {
           //加密的格子進行減操作
            mine[msg.y/MINE_WID+1][msg.x/MINE_WID+1]-=20;
            
        }
        else if(msg.uMsg==WM_RBUTTONDOWN)//判斷右鍵點擊進行標(biāo)記
        {
            if( mine[msg.y/MINE_WID+1][msg.x/MINE_WID+1]<30) //簡化處理,沒有放置標(biāo)記紅旗的都是在小于30
            {
                 mine[msg.y/MINE_WID+1][msg.x/MINE_WID+1]+=20;//直接+20,讓數(shù)字大于30,給放置紅旗做準(zhǔn)備(-1到8+了20,從19~28,大于30簡化)

            }
            else //否則什么? 否則就是 大于30,有紅旗了
            {
                 mine[msg.y/MINE_WID+1][msg.x/MINE_WID+1]-=20; //如果本來就有紅旗,就-20,取消紅旗標(biāo)記
                 //注意在 gameDraw ()里面更新  else if(mine[i][j]>30) putimage(x,y,&img[11]);
            

            }
            
        }
            
    }
    
            
}

gameDraw()更新一下

void gameDraw()
{
    for(int i=1;i<ROW+1;i++)
    {
        for(int j=1;j<COL+1;j++)
        {
            int x=(j-1)*MINE_WID;//同步更新下標(biāo)
            int y=(i-1)*MINE_WID;
            if(mine[i][j]>=0&&mine[i][j]<=8) //初始化開始為0的時候,全部填充空白磚塊
            {
                 putimage(x,y,&img[mine[i][j]]); //根據(jù)mine[i][j]的數(shù)字來繪制對應(yīng)的圖片,注意圖片的文件名要與自己顯示的東西相符合
            }
            else if(mine[i][j]==-1) //當(dāng)為-1的時候布mine
            {
                putimage(x,y,&img[9]);
            }
            else if(mine[i][j]>=19&&mine[i][j]<=28) //所有的數(shù)字在-1到19范圍,+20之后在19到28貼掩蓋圖片
            {
                putimage(x,y,&img[10]);

            }
            else if(mine[i][j]>30)
            {
                putimage(x,y,&img[11]);
            }

        }
    }
}

調(diào)試一下,驗證紅旗標(biāo)記,數(shù)字標(biāo)記,mine區(qū)標(biāo)記,與紅旗標(biāo)記,取消紅旗標(biāo)記功能

image-20210210094333553

2.3判斷游戲結(jié)束與勝利

什么是輸?
就是踩到mine了!踩mine之后,是點擊事件發(fā)生,已經(jīng)發(fā)生了數(shù)據(jù)解密,與-1進行比較,彈出一個窗口,彈出功能需要 在文件開頭加入
HWND hwnd=NULL;

void gameWinorLose()
{
    //復(fù)制一下鼠標(biāo)消息的代碼
  if(MouseHit())
    {
        msg=GetMouseMsg(); //注意大小寫
       if(mine[msg.y/MINE_WID+1][msg.x/MINE_WID+1]==-1) //注意點擊之后的判斷進行了解密操作,對-1進行判斷,有時候是對加密后的數(shù)據(jù)進行判斷,要自己學(xué)會區(qū)分
           //include加入對話框彈出結(jié)束游戲 #include<Windows.h>
       {
          MessageBox(hwnd,"中mine了!","Game Over",MB_OK); 
           //全局變量區(qū)加入 HWND hwnd=NULL;
          exit(0);
       
       }
  }
           
}

現(xiàn)在我們調(diào)用一下

int main()
{
    initgraph(MINE_WID*ROW,MINE_WID*COL,1); //參數(shù) 1,是同時繪圖與打開控制臺
    gameInit(); //資源初始化
    printMap();//控制臺作為后臺數(shù)據(jù)幫忙分析
    while(1)
    
    {
        
        gameDraw();//繪制
        gameMouse();
        gameDraw();//繪制二次,彈出窗口
        gameWinorLose();
    }
    
    system("pause");//記得 #include<stdlib>
    
    return 0;
}

當(dāng)然游戲還有更完善的功能,比如點擊空白區(qū)域,全部展開,我們需要更新一下代碼,將鼠標(biāo)坐標(biāo)作為全局坐標(biāo)方便傳遞參數(shù),將鼠標(biāo)消息的坐標(biāo)賦值給openx,openy,代碼會更簡潔

#include<stdio.h>
#include<graphics.h>
#include<Windows.h>
#include<stdlib.h>
#include<time.h>
#define ROW 9//9行9列的mine區(qū)表格
#define COL 9
#define MINE_WID 40
#define MAX_MINE 9
int mine[ROW+2][COL+2];
int openx,openy;
IMAGE img[12];
MOUSEMSG msg;
HWND hwnd=NULL;
//全局變量方便訪問,mine[openx][openy]更簡潔一些
void gameMouse()
{
    if(MouseHit())
    {
        msg=GetMouseMsg(); //注意大小寫
        //掃mine有標(biāo)記功能,判斷鼠標(biāo)左右鍵。左鍵確定,右鍵標(biāo)記為紅旗
        if(msg.uMsg==WM_LBUTTONDOWN)
        {
            openx=msg.y/MINE_WID+1;
            openy=msg.x/MINE_WID+1;
           //加密的格子進行減操作
            mine[openx][openy]-=20; 
            
        }
        else if(msg.uMsg==WM_RBUTTONDOWN) //判斷右鍵點擊進行標(biāo)記
        {
            if( mine[openx][openy]<30) //簡化處理,沒有放置標(biāo)記紅旗的都是在小于30
            {
                 mine[openx][openy]+=20;//直接+20,讓數(shù)字大于30,給放置紅旗做準(zhǔn)備

            }
            else
            {
                 mine[openx][openy]-=20; //如果本來就有紅旗,就-20,取消紅旗標(biāo)記
                 //注意在 drawMap()里面更新    else if(mine[i][j]>30) putimage(x,y,&img[11]);
            

            }
            
        }
            
    }
    
            
}
//同樣這里可以簡單的處理一下
void gameWinorLose()
{
    //復(fù)制一下鼠標(biāo)消息的代碼
  if(MouseHit())
    {
        msg=GetMouseMsg(); //注意大小寫
       if(mine[openx][openy]==-1) //注意點擊之后的判斷進行了解密操作,對-1進行判斷,有時候是對加密后的數(shù)據(jù)進行判斷,要自己學(xué)會區(qū)分
           //include加入對話框彈出結(jié)束游戲 #include<Windows.h>
       {
          MessageBox(hwnd,"中mine了!","Game Over",MB_OK); 
           //全局變量區(qū)加入 HWND hwnd=NULL;
          exit(0);
       
       }
  }
           
}

然后我們來設(shè)計打開空白全部展開的函數(shù)

void openNull(int x,int y) //傳遞openx,openy進來
{
    if(mine[x][y]==0)//如果是空白(已經(jīng)解密了,對0進行操作)
    {
        for (int i=x-1;i<=x+1;i++)//二層遍歷周圍的方格子
        {
            for(int j=y-1;j<=y+1;j++)
            {
                if(mine[i][j]==20)//周圍的格子沒有點,沒有解密,與20進行判斷
                {
                    mine[i][j]-=20;//解密為空格0
                    openNull(i,j);//遞歸調(diào)用到周圍所有的空格全部一鍵打開退出
                }
            }
        }
    }
    
    
}

openNull()函數(shù),在鼠標(biāo)消息的左鍵點擊判斷里面調(diào)用,這樣就一次展開所有空格,部分代碼如下

 if(msg.uMsg==WM_LBUTTONDOWN)
        {
            openx=msg.y/MINE_WID+1;
            openy=msg.x/MINE_WID+1;
           //加密的格子進行減操作
            mine[openx][openy]-=20;
            openNull(openx,openy);//空白格子遞歸全展開
            
        }

3.結(jié)束完整代碼(有興趣的同學(xué),可以加入勝利消息)

#include<stdio.h>
#include<graphics.h>
#include<Windows.h>
#include<stdlib.h>
#include<time.h>
#define ROW 9//9行9列的數(shù)據(jù)表格
#define COL 9
#define MINE_WID 40
#define MAX_MINE 9
int mine[ROW+2][COL+2];
int openx,openy;
IMAGE img[12];
MOUSEMSG msg;
HWND hwnd=NULL;


void printMap() //數(shù)組作為儲存數(shù)據(jù),把外圈也繪制出來
{
    for(int i=0;i<ROW+2;i++)
    {
        for(int j=0;j<COL+2;j++)
        {
            printf("%3d",mine[i][j]);
        }
        printf("\n");
    }
}
//在二維數(shù)組里面隨機獲取9個下標(biāo),賦值為-1
void gameInit()
{
    //隨機化給下標(biāo)為x,y的賦值為-1,標(biāo)記為mine區(qū),并且要判斷不要有 重合的下標(biāo)
    int x,y;
    srand((unsigned int)time(0));
    for(int m=0;m<MAX_MINE;)//注意m++的操作,不在這里
    {

        x=rand()%9+1;// 1-9 有9個格子
        y=rand()%9+1;
        //判斷是否重復(fù)
        
        if(mine[x][y]==0) //沒有mine的情況下,就埋mine,有mine就沒做了
        {
            mine[x][y]=-1;
            //當(dāng)布mine成功了,m才++
            m++;//放在判斷這里++,才會保證一定布滿9個mine
        }
        
    }
for(int a=1;a<ROW+1;a++) // VC6在cpp文件不能重復(fù)定義i,j。所以避開一下
    {
        for(int b=1;b<COL+1;b++)
        {
            //首先要找到是mine的i,j
            if(mine[a][b]==-1) //再嵌套一個二層循環(huán)
            {
                for(int k=a-1;k<=a+1;k++)
                {
                    for(int q=b-1;q<=b+1;q++)
                    {
                        //周圍的遍歷,只對非mine區(qū)進行操作
                        if(mine[k][q]!=-1)
                        {
                            mine[k][q]++;
                        }
                    }
                }
                
            }
        }
    }
for(int i=1;i<=ROW;i++)
{
    for(int j=1;j<=COL;j++)
    {
        mine[i][j]+=20;
    }
}


    
    
    char temp[20]=" "; 
    for(i=0;i<12;i++)
    {
        sprintf(temp,"%d.jpg",i);//
        //loadimage(&img[i],temp,MINE_WID,MINE_WID);
        loadimage(img+i,temp,MINE_WID,MINE_WID);
    
        
    }
}
//繪圖是mine數(shù)組里面的 1行到9行,1列到9列
//根據(jù)后臺數(shù)據(jù),給出繪制mine區(qū)定義
//為-1布mine,增加 if else if分支,切忌還要有數(shù)字選項,所以不要只寫else
//繪圖是mine數(shù)組里面的 1行到9行,1列到9列
void gameDraw()
{
    for(int i=1;i<ROW+1;i++)
    {
        for(int j=1;j<COL+1;j++)
        {
            int x=(j-1)*MINE_WID;//同步更新下標(biāo)
            int y=(i-1)*MINE_WID;
            if(mine[i][j]>=0&&mine[i][j]<=8) //初始化開始為0的時候,全部填充空白磚塊
            {
                 putimage(x,y,&img[mine[i][j]]); //根據(jù)mine[i][j]的數(shù)字來繪制對應(yīng)的圖片,注意圖片的文件名要與自己顯示的東西相符合
            }
            else if(mine[i][j]==-1) //當(dāng)為-1的時候布mine
            {
                putimage(x,y,&img[9]);
            }
             else if(mine[i][j]>=19&&mine[i][j]<=28) //所有的數(shù)字在-1到8范圍,+20之后在19到28貼掩蓋圖片
            {
                putimage(x,y,&img[10]); //貼掩蓋圖片

            }
             else if(mine[i][j]>30) 
             {
                 putimage(x,y,&img[11]);
             }
        }
    }
}
void openNull(int x,int y);
//全局變量方便訪問,mine[openx][openy]更簡潔一些
void gameMouse()
{
    int rx,ry;
    if(MouseHit())
    {
        msg=GetMouseMsg(); //注意大小寫
        //掃mine有標(biāo)記功能,判斷鼠標(biāo)左右鍵。左鍵確定,右鍵標(biāo)記為紅旗
        if(msg.uMsg==WM_LBUTTONDOWN)
         {
            openx=msg.y/MINE_WID+1;
            openy=msg.x/MINE_WID+1;
           //加密的格子進行減操作
            mine[openx][openy]-=20;
            openNull(openx,openy);//空白格子遞歸全展開
            
        }
        else if(msg.uMsg==WM_RBUTTONDOWN) //判斷右鍵點擊進行標(biāo)記
        { rx=msg.y/MINE_WID+1; //左鍵坐標(biāo)因為有兩個函數(shù)需要用到,openNull和GameMouse,右鍵只有紅旗
         //防止死循環(huán)中先點擊左鍵全局變量的干擾, 右鍵的坐標(biāo)單獨判斷
            ry=msg.x/MINE_WID+1;
            
            if( mine[rx][ry]<30) //簡化處理,沒有放置標(biāo)記紅旗的都是在小于30
            {
                 mine[rx][ry]+=20;//直接+20,讓數(shù)字大于30,給放置紅旗做準(zhǔn)備

            }
            else
            {
                 mine[rx][ry]-=20; //如果本來就有紅旗,就-20,取消紅旗標(biāo)記
                 //注意在 drawMap()里面更新    else if(mine[i][j]>30) putimage(x,y,&img[11]);
            

            }
            
        }
            
    }
    
            
}
void openNull(int x,int y) //傳遞openx,openy進來
{
    if(mine[x][y]==0)//如果是空白(已經(jīng)解密了,對0進行操作)
    {
        for (int i=x-1;i<=x+1;i++)//二層遍歷周圍的方格子
        {
            for(int j=y-1;j<=y+1;j++)
            {
                if(mine[i][j]==20)//周圍的格子沒有點,沒有解密,與20進行判斷
                {
                    mine[i][j]-=20;//解密為空格0
                    openNull(i,j);//遞歸調(diào)用到周圍所有的空格全部一鍵打開退出
                }
            }
        }
    }
    
    
}
void gameWinorLose()
{
    //復(fù)制一下鼠標(biāo)消息的代碼

    gameMouse();
       
       if(mine[openx][openy]==-1) //注意點擊之后的判斷進行了解密操作,對-1進行判斷,有時候是對加密后的數(shù)據(jù)進行判斷,要自己學(xué)會區(qū)分
           //include加入對話框彈出結(jié)束游戲 #include<Windows.h>
       {

           gameDraw(); //踩mine之后再調(diào)用一次貼圖,此處貼出mine的照片
          MessageBox(hwnd,"中mine了!","Game Over",MB_OK); 
           //全局變量區(qū)加入 HWND hwnd=NULL;
          exit(0);
       
       }
  
           
}

 int main()
{
    initgraph(MINE_WID*ROW,MINE_WID*COL,1); //參數(shù) 1,是同時繪圖與打開控制臺
    gameInit(); //資源初始化
    while(1)//死循環(huán)重復(fù)繪圖
    
    {
        gameDraw();//繪制

        gameMouse(); 
        gameWinorLose();//調(diào)用順序優(yōu)化
    }
    printMap();//控制臺作為后臺數(shù)據(jù)幫忙分析
    system("pause");//記得 #include<stdlib>
    
    return 0;
}


報告要求:

1. 請分別對 99數(shù)據(jù)區(qū)cmd窗口, 偽隨機貼圖窗口,帶輔助圈的1111數(shù)據(jù)區(qū)cmd窗口,真隨機貼圖窗口,游戲貼圖數(shù)字1-8及mine的靜態(tài)圖,加密后鼠標(biāo)左鍵功能的實現(xiàn)、加密后鼠標(biāo)右鍵功能的實現(xiàn)、游戲失敗提示彈出窗口進行截圖 (遞歸清零不做要求)

2. 請總結(jié)函數(shù)定義、調(diào)用、及聲明的基本方式

3. 請以偽代碼的形式簡要分析 布mine算法、mine數(shù)字標(biāo)記掃描算法

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容