基于EasyX的掃雷游戲
一、預備知識
1.使用EasyX必須要知道的一些基礎函式
2.選擇結構 if , switch
3.回圈結構 for, while
4.多維陣列 arr1[N], arr2[N][N] , arr3[N][N][N]
5.函式封裝
二、游戲邏輯
想要寫出推箱子,首先要知道推箱子游戲都有哪些元素和規則
1.掃雷元素

主要可以分成三類
1.沒有打開個格子
2.打開的格子
3.被標記的格子
有了素材,先來一個加載資源函式Loadimg()
#define SIZE 25//圖片大小
IMAGE img[13];//存放圖片陣列
void Loadimg()
{
loadimage(&img[0] ,L"./images/0.jpg",SIZE,SIZE);
loadimage(&img[1] ,L"./images/1.jpg",SIZE,SIZE);
loadimage(&img[2] ,L"./images/2.jpg",SIZE,SIZE);
loadimage(&img[3] ,L"./images/3.jpg",SIZE,SIZE);
loadimage(&img[4] ,L"./images/4.jpg",SIZE,SIZE);
loadimage(&img[5] ,L"./images/5.jpg",SIZE,SIZE);
loadimage(&img[6] ,L"./images/6.jpg",SIZE,SIZE);
loadimage(&img[7] ,L"./images/7.jpg",SIZE,SIZE);
loadimage(&img[8] ,L"./images/8.jpg",SIZE,SIZE);
loadimage(&img[9] ,L"./images/9.jpg",SIZE,SIZE);
loadimage(&img[10],L"./images/10.jpg",SIZE,SIZE);
loadimage(&img[11],L"./images/11.jpg",SIZE,SIZE);
loadimage(&img[12],L"./images/12.jpg",SIZE,SIZE);
}
2.掃雷規則
1.左鍵點擊未被打開的格子,可以打開格子
2.右鍵點擊未被打開的格子,可以標記格子
3.被標記的格子不能被打開
3.被標記的格子再右鍵時,可以解除標記
4.如果打開后格子是空的,則自動打開周圍的八個格子
5.自動打開的格子也遵循規則4
6.如果打開的格子里面是雷,則游戲失敗
7.如果所有非雷格子均被打開,則游戲獲勝
(格子的數字代表它周圍九宮格內雷的數量)
三、游戲設計
知道游戲元素和規則就可以開始設計游戲了
1.地圖設計

地圖內的數字代表它周圍九宮格內雷的數量,看一下圖就應該可以理解了,這次采用地圖隨機生成(為了避免大家記雷的位置),需要用<time.h>里的生成亂數,先寫一個初始化地圖函式Initmap()
#define NUM 10//地圖行列數
int map[NUM][NUM]={0};
void Initmap()
{
//----------隨機設定雷----------
srand((unsigned)time(NULL));//根據時間設定亂數種子
for(int k=0;k<NUM; )
{
int x=rand()%NUM;//生成0 ~ 9的亂數
int y=rand()%NUM;//為避免產生相同的坐標,采用下面的方式
if(map[x][y]==0)
{//如果格子為空,則設定雷
map[x][y]=9;//雷是9
k++;
}
}
//如果是雷,則雷周圍九宮格內數字均+1
for(int i=0;i<NUM;i++)
{
for(int j=0;j<NUM;j++)
{
if(map[i][j]==9)
{//如果是雷
for(int a=i-1;a<=i+1;a++)
{//遍歷該雷周圍的九宮格
for(int b=j-1;b<=j+1;b++)
{
if(a>=0 && b>=0 && a<NUM && b<NUM && map[a][b]!=9)
{//判斷陣列是否越界
map[a][b]++;//不越界則+1
}
}
}
}
}
}
//蓋上格子 所有數字 +10,(點擊打開格子 數字-10)
for(int r=0;r<NUM;r++)
{
for(int c=0;c<NUM;c++)
{
map[r][c]+=10;
}
}
}
由上面的元素分類可以知道,游戲地圖資料分為三類
- 被打開的格子 0 ~ 9
- 未被打開的格子 10 ~ 19
- 被標記的格子 20 ~ 29
也就是,對格子進行+10處理,+10代表另一種狀態,現在可以根據狀態繪制地圖,寫一個Drawmap()函式
void Drawmap()
{
for(int i=0;i<NUM;i++)
{
for(int j=0;j<NUM;j++)
{
if(map[i][j]>=10 && map[i][j]<20)
{//如果圖還沒點開,且未被標記,貼格子
putimage(i*SIZE,j*SIZE,&img[10]);
}
else if(map[i][j]>=20)
{//如果被標記,貼標記
putimage(i*SIZE,j*SIZE,&img[11]);
}
else
{//剩下的按數值貼圖
putimage(i*SIZE,j*SIZE,&img[ map[i][j] ]);
}
}
}
}
2.點擊設計
上文提到
1.左鍵點擊未被打開的格子,可以打開格子
2.右鍵點擊未被打開的格子,可以標記格子
3.被標記的格子不能被打開
3.被標記的格子再右鍵時,可以解除標記
首先要找到滑鼠位置,然后根據滑鼠點擊的情況,左鍵還是右鍵,分寫不同的處理,所有內容寫在Hitimg()函式內
ExMessage m;//訊息全域變數
int ipos=-10,jpos=-10;//記錄滑鼠位置
int count=90;//總共非雷格子數
void Hitimg()
{
m = getmessage(EM_MOUSE);//得到滑鼠訊息
if(m.message == WM_LBUTTONDOWN)
{//如果滑鼠左鍵按下
ipos=m.x/SIZE;//換算滑鼠位置
jpos=m.y/SIZE;
if(map[ipos][jpos]>=10 && map[ipos][jpos]<20)
{//如果格子還沒被點開 且未被標記
count--;//非雷格子數減少
map[ipos][jpos]-=10;//打開
}
}
if(m.message == WM_RBUTTONDOWN)
{//如果滑鼠右鍵按下
ipos=m.x/SIZE;//換算滑鼠位置
jpos=m.y/SIZE;
if(map[ipos][jpos]>=10 && map[ipos][jpos]<20)
{//如果格子還沒被點開
map[ipos][jpos]+=10;//標記
}
else if(map[ipos][jpos]>=20)
{//如果格子被標記
map[ipos][jpos]-=10;//去掉標記
}
}
}
上文提到
4.如果打開后格子是空的,則自動打開周圍的八個格子
5.自動打開的格子也遵循規則4
這個就比較有趣了,仔細想想,這不就是遞回嗎,因為每次格子位置都不一樣,需要傳個 格子位置 引數,寫個Openmap(int ipos,int jpos)函式
void Openmap(int ipos,int jpos)
{//如果是空白則打開別打空白
if(map[ipos][jpos]==0)
{//如果是空格子
for(int a=ipos-1;a<=ipos+1;a++)
{ //遍歷格子周圍的九宮格
for(int b=jpos-1;b<=jpos+1;b++)
{
if(a>=0 && b>=0 && a<NUM && b<NUM)
{//判斷陣列是否越界
if(map[a][b]>=10 && map[a][b]<=18)
{//如果周圍是沒被打開的格子
map[a][b]-=10;//打開格子
count--;//非雷格子數減少
Openmap(a,b);//遞回打開 被打開格子周圍的格子
}
}
}
}
}
}
3.結束設計
上文提到
6.如果打開的格子里面是雷,則游戲失敗
7.如果所有非雷格子均被打開,則游戲獲勝
是不是很容易想到,
游戲失敗條件就是map[ipos][jpos]==9
游戲獲勝條件就是非雷格子數為靈count==0
如果游戲失敗也把別的雷顯示出來,并且點的雷是紅的,寫一個函式顯示所有雷Showallmines()
void Showallmines()
{
for(int i=0;i<NUM;i++)
{
for(int j=0;j<NUM;j++)
{
if(map[i][j]==19 && map[i][j]!=9)
putimage(i*SIZE,j*SIZE,&img[12]);
if(map[i][j]==9)
putimage(i*SIZE,j*SIZE,&img[9]);
}
}
}
4.整體設計
下面把上面的函陣列合起來就是推箱子游戲,再來點音樂
#include<stdio.h>
#include<time.h>
#include<easyx.h>//圖形庫
#include<mmsystem.h>//音樂
#pragma comment(lib,"winmm.lib")//庫檔案
int main()
{
initgraph(SIZE*10,SIZE*10);//創建視窗
Loadimg(); //加載圖片資源
Initmap();//初始化地圖
BeginBatchDraw();//批量繪圖開始
Drawmap();//貼圖
EndBatchDraw();//批量繪圖結束
//回圈播放背景音樂
mciSendString(L"open ./images/bg.mp3 ", 0, 0, 0);
mciSendString(_T("play ./images/bg.mp3 repeat"), 0, 0, 0);
while(true){
if(map[ipos][jpos]==9)
{//如果游戲失敗
Showallmines();//顯示所有雷
mciSendString(L"close ./images/bg.mp3 ", 0, 0, 0);//關閉背景音樂
PlaySound(L"./images/over.wav", nullptr, SND_FILENAME | SND_ASYNC);//播放失敗音樂
MessageBox(NULL,_T("游戲結束,你輸了,-_-||"),_T("游戲提示"),MB_OK);
break;
}
else if(count==0)
{//如果游戲勝利
Drawmap();
mciSendString(L"close ./images/bg.mp3 ", 0, 0, 0);//關閉背景音樂
PlaySound(L"./images/success.wav", nullptr, SND_FILENAME | SND_ASYNC);//播放勝利音樂
MessageBox(NULL,_T("游戲結束,恭喜你,你贏了!"),_T("游戲提示"),MB_OK) ;
break;
}
Drawmap();//更新地圖
Hitimg();//點擊格子圖片
Openmap(ipos,jpos);//遞回打開空格子
}
system("pause");
return 0;
}
把上面所有代碼復制到一個cpp檔案里,再把素材改好命名放到images檔案夾里,images檔案夾在cpp檔案旁邊,就可以編譯運行了!
圖片音樂素材及可執行程式都在我的資源中,需要的可以進行下載
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/291733.html
標籤:其他
