C++代碼實(shí)現(xiàn)掃雷游戲
前言
提示:本文是基于easyX圖形庫實(shí)現(xiàn)的,還有部分功能可以添加,僅適合新手參考。
提示:以下是本篇文章正文內(nèi)容,下面案例可供參考
一、掃雷游戲模式
在確定大小的矩形雷區(qū)中隨機(jī)布置一定數(shù)量的地雷,玩家需要盡快找出雷區(qū)中的所有不是地雷的方塊,而不許踩到地雷。
游戲的基本操作包括左鍵單擊和右鍵單擊。其中左鍵用于打開安全的格子,推進(jìn)游戲進(jìn)度;右鍵用于標(biāo)記地雷,以輔助判斷。
左鍵單擊:在判斷出不是雷的方塊上按下左鍵,可以打開該方塊。如果方塊上出現(xiàn)數(shù)字,則該數(shù)字表示其周圍3×3區(qū)域中的地雷數(shù)(一般為8個(gè)格子,對(duì)于邊塊為5個(gè)格子,對(duì)于角塊為3個(gè)格子。所以掃雷中最大的數(shù)字為8);如果方塊上為空(相當(dāng)于0),則可以遞歸地打開與空相鄰的方塊;如果不幸觸雷,則游戲結(jié)束。
右鍵單擊:在判斷為地雷的方塊上按下右鍵,可以標(biāo)記地雷(顯示為小紅旗)。重復(fù)一次或兩次操作可取消標(biāo)記。
二、代碼實(shí)現(xiàn)
1.繪制地圖場景
根據(jù)每一塊地區(qū)的數(shù)據(jù)進(jìn)行圖形輸出。
代碼如下(示例):
void drawmap(int map[][12],IMAGE *img)
{
int i, j;
for (i = 1; i <= 10; i++)
{
for (j = 0; j <= 10; j++)
{
int x = 50 * (i - 1);//得到位置
int y = 50 * (j - 1);
if (map[i][j]>25)
{
putimage(x, y, &img[9]);//標(biāo)記flag
}
else
{
switch (map[i][j])
{
case 9:
putimage(x, y, &img[11]);//輸出圖片雷
break;
case 10:
putimage(x, y, &img[0]);//0
break;
case 11:
putimage(x, y, &img[1]);//1
break;
case 12:
putimage(x, y, &img[2]);//2
break;
case 13:
putimage(x, y, &img[3]);//3
break;
case 14:
putimage(x, y, &img[4]);//4
break;
case 15:
putimage(x, y, &img[5]);//5
break;
case 16:
putimage(x, y, &img[6]);//6
break;
case 17:
putimage(x, y, &img[7]);//7
break;
case 18:
putimage(x, y, &img[8]);//8
break;
default:
putimage(x, y, &img[10]);//地圖
break;
}
}
}
}
}
2.鼠標(biāo)點(diǎn)擊
鼠標(biāo)左鍵點(diǎn)擊翻開格子,右鍵點(diǎn)擊標(biāo)記flag,再次點(diǎn)擊可以進(jìn)行取消。
sum記錄翻開格子的數(shù)量,點(diǎn)擊后對(duì)每個(gè)位置的數(shù)據(jù)進(jìn)行加減操作。
代碼如下(示例):
int mousedown(int map[][12])
{
MOUSEMSG m; //定義鼠標(biāo)消息變量
while (1)
{
//獲取鼠標(biāo)消息
m = GetMouseMsg();
int mi = m.x / 50 + 1;
int mj = m.y / 50 + 1;
//判斷鼠標(biāo)消息
switch (m.uMsg)
{
case WM_LBUTTONDOWN:
if (map[mi][mj] > 9) //已翻開的情況
{
continue;
}
if (map[mi][mj] == 0) //如果點(diǎn)擊為0,則翻開一片。
{
//使用遞歸函數(shù)
swap(map, mi, mj);
}
else
{
map[mi][mj] += 10;
sum += 1;
}
return map[mi][mj];
break;
case WM_RBUTTONDOWN:
if (map[mi][mj] > 9&& map[mi][mj] < 25) //已翻開的情況
{
continue;
}
if (map[mi][mj] > 25) //再次點(diǎn)擊取消flag
{
map[mi][mj] -= 30;
}
else
{
map[mi][mj] += 30;
}
return map[mi][mj];
break;
}
}
}
3.遞歸
當(dāng)我們點(diǎn)到為0的地區(qū)時(shí),將會(huì)打開周圍的部分地區(qū),外圍為非0數(shù)或到達(dá)邊界,內(nèi)部為0.
如圖:

代碼如下(示例):
void swap(int map[][12],int mi,int mj)
{
map[mi][mj] = 10;
sum += 1;
for (int i = mi - 1; i <= mi + 1; i++)
{
for (int j = mj - 1; j <= mj + 1; j++)
{
//數(shù)組下標(biāo)不能越界
if (i >= 1 && i <= 10 && j >= 1 && j <= 10)
{
//翻開的只能是數(shù)字
if (map[i][j] < 9)
{
//如果為0,則進(jìn)行遞歸。
if (map[i][j] == 0)
{
swap(map, i, j);
}
else
{
map[i][j] += 10;
sum += 1;
}
}
}
}
}
}
4.初始化游戲
代碼如下(示例):
void startgame()
{
initgraph(500, 500); //初始化地圖500x500
int map[12][12] = { 0 };
int i,j,m,n;
//隨機(jī)函數(shù)種子
srand((unsigned int)time(NULL));
//隨機(jī)生成10個(gè)雷
for (n = 0; n < 10;)
{
i = rand() % 10 + 1; //[1,10]
j = rand() % 10 + 1;
if (map[i][j] == 0) //排除本來就有雷的情況
{
map[i][j] = -1; //-1表示有雷
n++;
}
}
//產(chǎn)生數(shù)字
for (i = 1; i <= 10; i++)
{
for (j = 1; j <= 10; j++)
{
//排除是雷的情況
if (map[i][j] != -1)
{
for (m = i - 1; m <= i + 1; m++) //判斷周圍是否有雷
{
for (n = j - 1; n <= j + 1; n++)
{
if (map[m][n] == -1)
{
map[i][j]++;
}
}
}
}
}
}
IMAGE img[12]; //定義圖片變量
loadimage(&img[0], "E:\\C++ project\\minesweeping\\0.jpg", 50, 50);
loadimage(&img[1], "E:\\C++ project\\minesweeping\\1.gif", 50, 50);//加載圖片
loadimage(&img[2], "E:\\C++ project\\minesweeping\\2.gif", 50, 50);
loadimage(&img[3], "E:\\C++ project\\minesweeping\\3.gif", 50, 50);
loadimage(&img[4], "E:\\C++ project\\minesweeping\\4.gif", 50, 50);
loadimage(&img[5], "E:\\C++ project\\minesweeping\\5.gif", 50, 50);
loadimage(&img[6], "E:\\C++ project\\minesweeping\\6.gif", 50, 50);
loadimage(&img[7], "E:\\C++ project\\minesweeping\\7.gif", 50, 50);
loadimage(&img[8], "E:\\C++ project\\minesweeping\\8.gif", 50, 50);
loadimage(&img[9], "E:\\C++ project\\minesweeping\\flag.gif", 50, 50);
loadimage(&img[10], "E:\\C++ project\\minesweeping\\地圖.gif", 50, 50);
loadimage(&img[11], "E:\\C++ project\\minesweeping\\雷.gif", 50, 50);
while (1)
{
drawmap(map, img);
//點(diǎn)到地雷
if (mousedown(map)==9)
{
sum = 0; //重置判斷變量
drawmap(map, img);
MessageBox(hwnd,"你踩到雷了!","Game Over",MB_OK);
return;
}
//成功完成游戲
if (sum == 90)
{
sum = 0; //重置判斷變量
drawmap(map, img);
MessageBox(hwnd, "你成功完成了游戲!", "Game Over", MB_OK);
return;
}
}
}
5.main
代碼如下(示例):
#include<iostream>
#include<time.h>
#include<graphics.h> //圖形庫頭文件 easyx
#include <conio.h> //調(diào)用_getch函數(shù)
using namespace std;
HWND hwnd;
int sum = 0;//用于表示目前已經(jīng)點(diǎn)開的格子數(shù)
//聲明函數(shù)
void drawmap(int map[][12], IMAGE* img);
int mousedown(int map[][12]);
void swap(int map[][12], int mi, int mj);
//初始化游戲
//繪制地圖
//鼠標(biāo)點(diǎn)擊
//遞歸函數(shù)
int main()
{
while (1)
{
startgame();
if (MessageBox(hwnd, "再來一次", "結(jié)束游戲", MB_YESNO)==IDNO)
break;
}
//_getch(); //防止閃屏
closegraph();
return 0;
}
總結(jié)及運(yùn)行
提示:本代碼僅供參考,編譯器為visual studio
圖片資源可以在網(wǎng)上找找,將其放到對(duì)應(yīng)的目錄即可。
運(yùn)行結(jié)果如圖:


以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C語言編程數(shù)據(jù)在內(nèi)存中的存儲(chǔ)詳解
本篇文章是C語言編程篇,主要為大家介紹C語言編程中數(shù)據(jù)在內(nèi)存中存儲(chǔ)解析,有需要的朋友可以借鑒參考下,希望可以有所幫助2021-09-09
C++ GDI實(shí)現(xiàn)圖片格式轉(zhuǎn)換
GDI+(Graphics Device Interface Plus)是一種用于圖形繪制和圖像處理的應(yīng)用程序編程接口(API),在Windows平臺(tái)上廣泛使用,本文就來介紹一下如何使用GDI實(shí)現(xiàn)圖片格式轉(zhuǎn)換吧2023-12-12
在C語言中調(diào)用C++做的動(dòng)態(tài)鏈接庫
如果你有一個(gè)c++做的動(dòng)態(tài)鏈接庫.so文件,而你只有一些相關(guān)類的聲明,那么你如何用c調(diào)用呢,別著急,本文通過一個(gè)小小的例子,讓你能夠很爽的搞定.2016-05-05
C++設(shè)計(jì)模式之建造者模式(Builder)
這篇文章主要介紹了C++設(shè)計(jì)模式之建造者模式Builder的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03
C/C++雜記 虛函數(shù)的實(shí)現(xiàn)的基本原理(圖文)
這篇文章主要介紹了C/C++雜記 虛函數(shù)的實(shí)現(xiàn)的基本原理(圖文),需要的朋友可以參考下2016-06-06

