游戲截圖:
看完之后有幫助記得點個贊和關注

目錄
一.實作原理:
二.素材:
三.源代碼
四.注意事項:
五.心得體會:
一.實作原理:
1.先通過https://easyx.cn/網址下載easyx方可開始使用(要有一點easxy的基礎)
2.原理:
首先掃雷的布局其實就是二維陣列,通過用不同的數字代替不同的效果來實作掃雷(如:-1代表雷,0代表空格,1就代表點開后的數字1,2代表數字2........),通過不同的數字來進行在對應的位置進行貼圖,
當我們想好原理之后,就可以開始理一下思路、我們要先創造一個大一點的二維陣列(初始值為0)這樣可以方便我們后續進行難度的提升(如:可以創造一個102*102的二維陣列這樣我們可以通過利用不同大小的陣列來進行掃雷難度的升級),接著我們可以寫一個函式隨機出n個雷(n為你自己想設計的,最好設定成為一個未知數,方便后續不同難度的不同雷數的修改),這個函式的核心是用srand()函式布下一個種子,然后再二維陣列中的不同位置隨機附上n個不同位置的-1,這樣的隨機雷的效果就做出來了,
接下來我們要計算每個位置(除開炸彈的位置,就是-1的位置)附近九宮格的雷數,這樣方便后續點開方塊后的貼圖,現在你所設定的游戲區域大小的數字都是-1到8的數字,接下用一個回圈把你所有的游戲區域的數字都加上20(原因后面代碼會體現出來),這樣游戲區域的數字就是19到28之間,
現在萬事大吉只差貼圖,先將所有的圖片loadimage函式加載好(圖片后面up主^(* ̄(oo) ̄)^會附上),但是記得圖片要放在代碼檔案的根目錄下,這樣寫相對路徑時候要方便一點,
最后一步就是我們要用一個while回圈來不斷地獲取用戶的滑鼠輸入(這里大家可以看一下getmousemsg函式),并且用一個函式來不斷地列印地圖,這樣就可以實作掃雷的實作,
剩下就是一些細節的添加(如:時間的跳動和雷數的顯示和笑臉點擊后會重新開始游戲及回傳界面按鈕)
二.素材:

這里需要讀者自己截出想要的部分(要是懶得話也可以私信up^(* ̄(oo) ̄)^主獲取截好的圖片)
三.源代碼
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <graphics.h>
int grahight = 415;//實際畫布高
int grawidth = 340;//實際畫布寬
#define allhight 100//總陣列大小
#define allwidth 100//總陣列大小
//中級17*17:415*340,初級10*10:275*200,高級20*20:475*400
int hight = 17;//實際游戲區域大小
int width = 17;//實際游戲區域大小
int times = 0;//獲取總時間
int time1 = 0, time2 = 0, time3 = 0;//記錄時間的三位
int first = 1;//判斷第一次點擊
int bomb = 45;//炸彈數量
int runing = 1;//是否結束游戲
int smiles = 0;//笑臉圖的變化
int ture = 1;//判斷是否開始游戲
int a = 1;//不讓它一直彈出勝利的框
int map[allhight + 2][allwidth + 2] = { 0 };//布局戰場都出的兩行和兩個列用來輔助找出周圍炸彈數
clock_t start_t, end_t;//開始實際時間,結束時間算時間差
IMAGE block[13];//1-8和空格和炸彈圖片
IMAGE smile[4];//笑臉的各種狀態
IMAGE numbomb[10];//時間圖片
int numbombs = 0;//炸彈第一位數
int numbombss = 0;//炸彈第二位數
int win = 0;//判斷是否贏
int choice = 0;//看用戶是否選擇
void printfmap();//列印地圖
void updategame();//更新資料并且加密
int findbomb(int a, int b);//找正常方塊附近的炸彈數量
void theloadimage();//加載圖片
void playgame();//獲取用戶的點擊
void newgame();//重繪游戲
void whitchtouch2();//選擇 難度界面函式
void showbomb();//點擊炸彈后顯示所有炸彈
void openzero(int m, int n);//遇到空格打開,遞回思想
void whitchtouth();//開始界面的選擇函式
void printfmaps()
{
for (int i = 1; i <= hight; i++)
{
printf("第%d行:", i);
for (int j = 1; j <= width; j++)
{
int a = (j - 1) * 20;
int b = (i - 1) * 20 + 72;
printf("%3d", map[i][j]);
}
printf("\n");
}
}
//輸出后臺資料看炸彈在哪,外掛!!!!!
void before();
int main()
{
HWND hwnd = initgraph(grawidth, grahight);
setbkcolor(RGB(189, 189, 189));
cleardevice();
//準備程序
while (ture)
{
settextcolor(BLACK);
rectangle(80, 50, 250, 120);
outtextxy(130, 80, L"開始游戲");
rectangle(80, 150, 250, 220);
outtextxy(130, 180, L"難度設定");
outtextxy(30, 280, L"游戲說明:");
outtextxy(105, 280, L"點擊笑臉可以重新開始,開始");
outtextxy(105, 305, L"游戲默認中級難度,可以選擇");
outtextxy(105, 330, L"難度直接開始游戲,點擊回傳");
outtextxy(105, 355, L"回到界面");
whitchtouth();
}
cleardevice();
while (choice)
{
settextcolor(BLACK);
rectangle(80, 50, 250, 120);
outtextxy(130, 80, L"初級");
rectangle(80, 150, 250, 220);
outtextxy(130, 180, L"中級");
rectangle(80, 250, 250, 320);
outtextxy(130, 280, L"高級");
whitchtouch2();
}
initgraph(grawidth, grahight);
setbkcolor(RGB(189, 189, 189));
cleardevice();
//開始
numbombss = bomb % 10;
numbombs = bomb / 10;
theloadimage();
updategame();
printfmaps();
while (1)
{
printfmap();
playgame();
if (win == hight * width - bomb && a)
{
a = 0;
smiles = 3;
printfmap();
MessageBox(hwnd, L"you win the game!", L"", MB_OK);
}
if (smiles == 1)//點擊笑臉就會重新開始游戲
{
first = 1;
a = 1;
win = 0;
system("cls");
newgame();
printfmaps();
}
end_t = clock();
int q = (end_t - start_t) / 1000;
if (runing == 1 && first == 0 && win != hight * width - bomb)
{
time1 = q / 100;
time2 = q / 10 % 10;
time3 = q % 10;
}
if (first == 1)
{
time1 = time2 = time3 = 0;
}
}
closegraph();
return 0;
}
void printfmap()
{
outtextxy(grawidth / 2 - 25, 0, L"回傳");
putimage(grawidth / 2 - 20, 30, &smile[smiles]);//中間笑臉圖片
putimage(10, 10, &numbomb[numbombs]);//這個和下個都是顯示炸彈數量圖片
putimage(40, 10, &numbomb[numbombss]);
putimage(grawidth - 90, 10, &numbomb[time1]);//下面三個都是時間圖片
putimage(grawidth - 60, 10, &numbomb[time2]);
putimage(grawidth - 30, 10, &numbomb[time3]);
for (int i = 1; i <= hight; i++)
{
for (int j = 1; j <= width; j++)
{
int a = (j - 1) * 20;
int b = (i - 1) * 20 + 72;
if (map[i][j] <= 28 && map[i][j] >= 19)//19-28表示沒點開的所以都是方塊圖片,這就是為什么要加20的原因
putimage(a, b, &block[0]);
else if (map[i][j] <= 8 && map[i][j] >= -1)
{
switch (map[i][j])
{
case -1:
putimage(a, b, &block[9]);
break;
case 0:
putimage(a, b, &block[10]);
break;
case 1:
putimage(a, b, &block[1]);
break;
case 2:
putimage(a, b, &block[2]);
break;
case 3:
putimage(a, b, &block[3]);
break;
case 4:
putimage(a, b, &block[4]);
break;
case 5:
putimage(a, b, &block[5]);
break;
case 6:
putimage(a, b, &block[6]);
break;
case 7:
putimage(a, b, &block[7]);
break;
case 8:
putimage(a, b, &block[8]);
break;
}
}//
//上面這個if就是用來用戶點擊之后減去20就變成-1到8就顯示出對應圖片
else if (map[i][j] <= 48 && map[i][j] >= 39)//右鍵加20然后,就在39到48之間,這些都是鏢旗圖示
putimage(a, b, &block[11]);
else if (map[i][j] == -100)//這是點到的炸彈要變紅
putimage(a, b, &block[12]);
}
}
}
void updategame()
{
srand((unsigned int)time(NULL));
int n = 0;
while (n < bomb)
{
int x = rand() % hight + 1;
int y = rand() % width + 1;
if (map[x][y] == 0 && x != 0 && y != 0)
{
map[x][y] = -1;
n++;
}
}
//布置地雷
for (int i = 1; i <= hight; i++)
{
for (int j = 1; j <= width; j++)
{
if (map[i][j] == 0)
{
int sign = 0;
sign = findbomb(i, j);
map[i][j] = sign;
}
}
}
//查找不是雷的區域周圍的雷數
for (int i = 1; i <= hight; i++)
{
for (int j = 1; j <= width; j++)
{
map[i][j] += 20;
}
}
//加密
}
int findbomb(int a, int b)
{
int all = 0;
for (int i = a - 1; i <= a + 1; i++)
{
for (int j = b - 1; j <= b + 1; j++)
{
if (map[i][j] == -1)
{
all++;
}
}
}
return all;
}
void theloadimage()
{
//加載圖片
loadimage(&block[0], L"img/方塊.png", 20, 20);
loadimage(&block[1], L"img/11.png", 20, 20);
loadimage(&block[2], L"img/22.png", 20, 20);
loadimage(&block[3], L"img/33.png", 20, 20);
loadimage(&block[4], L"img/44.png", 20, 20);
loadimage(&block[5], L"img/55.png", 20, 20);
loadimage(&block[6], L"img/66.png", 20, 20);
loadimage(&block[7], L"img/77.png", 20, 20);
loadimage(&block[8], L"img/88.png", 20, 20);
loadimage(&block[9], L"img/bom.png", 20, 20);
loadimage(&block[10], L"img/方塊2.png", 20, 20);
loadimage(&block[11], L"img/flag.png", 20, 20);
loadimage(&block[12], L"img/red-bom.png", 20, 20);
loadimage(&smile[0], L"img/笑臉.png", 30, 30);
loadimage(&smile[1], L"img/笑臉2.png", 30, 30);
loadimage(&smile[2], L"img/dead.png", 30, 30);
loadimage(&smile[3], L"img/cool.png", 30, 30);
loadimage(&numbomb[0], L"img/0.png", 30, 50);
loadimage(&numbomb[1], L"img/1.png", 30, 50);
loadimage(&numbomb[2], L"img/2.png", 30, 50);
loadimage(&numbomb[3], L"img/3.png", 30, 50);
loadimage(&numbomb[4], L"img/4.png", 30, 50);
loadimage(&numbomb[5], L"img/5.png", 30, 50);
loadimage(&numbomb[6], L"img/6.png", 30, 50);
loadimage(&numbomb[7], L"img/7.png", 30, 50);
loadimage(&numbomb[8], L"img/8.png", 30, 50);
loadimage(&numbomb[9], L"img/9.png", 30, 50);
}
void playgame()
{
//獲取用戶的滑鼠輸入
if (MouseHit())//判讀有誤鍵盤輸入,沒有就跳過,免得影響時間的進行,如果沒有這個if它會等一下,導致時間是跳動的,讀者可以自己刪去if來看一下會發生什么
{
MOUSEMSG msg = GetMouseMsg();
int x = msg.x;
int y = msg.y;
switch (msg.uMsg)
{
case WM_LBUTTONDOWN:
if (x >= 0 && x <= grawidth && y >= 72 && y <= grahight && runing && smiles != 3)
{
if (first == 1)//判讀第一次點擊開始計時
{
start_t = clock();
first = 0;
}
x = x / 20 + 1;
y = (y - 72) / 20 + 1;
if (map[y][x] <= 28 && map[y][x] >= 19)
{
if (map[y][x] == 20)//如果點開的是0需要展開周圍8個,8個中有0就還要展開,同時保證自己展開的不是炸彈
{
openzero(y, x);
}
else
{
map[y][x] -= 20;//正常的就直接展開
win++;
if (map[y][x] == -1)
win--;//防止最后一個是雷變成又是贏,又有炸彈
}
}
if (map[y][x] == -1)
{
map[y][x] = -100;//點到的炸彈要標紅,所以單獨設定一個數字,來展示這張圖片
showbomb();//點到炸彈要把炸彈全部展開
smiles = 2;//輸了的話就變成哭臉
printfmap();
runing = 0;//輸了就不能點擊游戲區
}
}
else if (x >= grawidth / 2 - 20 && x <= grawidth / 2 + 10 && y >= 20 && y <= 55)
{
smiles = 1;
runing = 1;
}
else if (x >= grawidth / 2 - 25 && x <= grawidth / 2 + 10 && y >= 0 && y <= 19)
{
before();
printf("1\n");
}
break;
case WM_LBUTTONUP:
if (runing == 1 && win != hight * width - bomb)
smiles = 0;//除了輸贏和點擊否則都是笑臉
break;
case WM_RBUTTONDOWN:
if (x >= 0 && x <= grawidth && y >= 72 && y <= grahight && runing == 1)//右鍵鏢旗
{
if (first == 1)
{
start_t = clock();
first = 0;
}
x = x / 20 + 1;
y = (y - 72) / 20 + 1;
if (map[y][x] <= 28 && map[y][x] >= 19)
{
map[y][x] += 20;
}
else if (map[y][x] <= 48 && map[y][x] >= 39)
{
map[y][x] -= 20;
}
}
break;
}
}
}
void openzero(int m, int n)
{
map[m][n] -= 20;//打開本身
win++;
for (int i = m - 1; i <= m + 1; i++)
{
for (int j = n - 1; j <= n + 1; j++)
{
if (i >= 1 && i <= width && j >= 1 && j <= hight)//保證在游戲區
{
if (map[i][j] <= 28 && map[i][j] >= 19)//保證沒有翻開
{
if (map[i][j] != 20)//保證不是0
{
map[i][j] -= 20;
win++;
}
else
openzero(i, j);//遞回
}
}
}
}
}
void newgame()
{
for (int i = 1; i <= hight; i++)
{
for (int j = 1; j <= width; j++)
{
map[i][j] = 0;
}
}
updategame();
}
void whitchtouth()
{
MOUSEMSG msg = GetMouseMsg();
int x = msg.x;
int y = msg.y;
switch (msg.uMsg)
{
case WM_LBUTTONDOWN:
if (x >= 80 && x <= 250 && y >= 50 && y <= 120)
{
ture = 0;
}
else if (x >= 80 && x <= 250 && y >= 150 && y <= 220)
{
ture = 0;
choice = 1;
}
break;
}
}
void showbomb()
{
int i, j;
for (i = 1; i <= hight; i++)
{
for (j = 1; j <= width; j++)
{
if (map[i][j] == 19)
{
map[i][j] -= 20;
}
}
}
}
void whitchtouch2()
{
MOUSEMSG msg = GetMouseMsg();
int x = msg.x;
int y = msg.y;
switch (msg.uMsg)
{
case WM_LBUTTONDOWN:
if (x >= 80 && x <= 250 && y >= 50 && y <= 120)
{
choice = 0;
cleardevice();
hight = 10;
width = 10;
grahight = 275;
grawidth = 200;
bomb = 15;
}
else if (x >= 80 && x <= 250 && y >= 150 && y <= 220)
{
cleardevice();
choice = 0;
hight = 17;
width = 17;
grahight = 415;
grawidth = 340;
bomb = 45;
}
else if (x >= 80 && x <= 250 && y >= 250 && y <= 320)
{
cleardevice();
choice = 0;
hight = 20;
width = 20;
grahight = 475;
grawidth = 400;
bomb = 60;
}
break;
}
}
void before()
{
for (int i = 1; i <= hight; i++)
{
for (int j = 1; j <= width; j++)
{
map[i][j] = 0;
}
}
ture = 1;//重置引數
choice = 0;
first = 1;
smiles = 0;
runing = 1;
win = 0;
a = 1;
system("cls");
initgraph(340,415);
setbkcolor(RGB(189, 189, 189));
cleardevice();
//準備程序
while (ture)
{
settextcolor(BLACK);
rectangle(80, 50, 250, 120);
outtextxy(130, 80, L"開始游戲");
rectangle(80, 150, 250, 220);
outtextxy(130, 180, L"難度設定");
outtextxy(30, 280, L"游戲說明:");
outtextxy(105, 280, L"點擊笑臉可以重新開始,開始");
outtextxy(105, 305, L"游戲默認中級難度,可以選擇");
outtextxy(105, 330, L"難度直接開始游戲,點擊回傳");
outtextxy(105, 355, L"回到界面");
whitchtouth();
}
cleardevice();
while (choice)
{
settextcolor(BLACK);
rectangle(80, 50, 250, 120);
outtextxy(130, 80, L"初級");
rectangle(80, 150, 250, 220);
outtextxy(130, 180, L"中級");
rectangle(80, 250, 250, 320);
outtextxy(130, 280, L"高級");
whitchtouch2();
}
initgraph(grawidth, grahight);
setbkcolor(RGB(189, 189, 189));
cleardevice();
//開始
numbombss = bomb % 10;
numbombs = bomb / 10;
updategame();
printfmaps();
}
四.注意事項:
大家可以將我的代碼運行玩一下(但是必須先截圖,后保存在代碼的根目錄下面才可以運行,并且圖片的名字要和我一樣,因為我的代碼加載圖片使用的相對路徑的名字就是我圖片取得名字,如果不這樣就加載不了圖片,只有一片灰,還要就是要下載easyx!!!!!),這樣可以幫助各位理解代碼,up主用的是vs2019讀者盡量用2019及以上的版本,以免導致有些函式無法運行,


要用代碼圖片位置和名字必須一樣!!!!!!!!!!
五.心得體會:
這是up主第一次寫的文章,且up主只是一個大一的學生,代碼寫的不是很好,并且這次代碼是要交的作業,所以有點趕工,代碼的可能有些地方沒有優化,希望大家可以理解并且提出意見,有不會可以私信問!!!!!

愛你!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/280281.html
標籤:其他
上一篇:Contest 2050 and Codeforces Round #718 (Div. 1 + Div. 2)ABCDEFGH題解
下一篇:【Contest 2050 and Codeforces Round #718 (Div. 1 + Div. 2)】Codeforces-1517
