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;
}

資源文件有數(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;
}

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之后運行看一下

多次運行,發(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張圖
}
}
}
}

對比一下數(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);
}
}

嘗試輸出一下,程序可能會假死,可能不會,取決于編譯器對數(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]++;
}
}
}
}
}
}

現(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");
}
}

但是輔助圈現(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)上了

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)正確


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ū)域覆蓋掩蓋圖片(這個圖片可以仍然為空白,為了掩飾效果,我們換一個不一樣的圖)

繪圖函數(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]); //貼掩蓋圖片
}
}
}
}

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;
}

掃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)記功能

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;
}
報告要求: