前言
每日雞湯
?不為模糊不清的未來過分擔憂,只為清清楚楚的現(xiàn)在奮發(fā)圖強。
基本思路
銜接基礎班掃雷
?如果思路不是特別清晰的兄弟,建議多看一下基礎版掃雷:數(shù)組之實戰(zhàn)篇——帶你從0到1實現(xiàn)掃雷(簡易版)
?如果EasyX圖形庫不是特別明白:可以看一下這篇文章:入門EasyX圖形庫(帶你進入不一樣的程序窗口,超詳解)
或者B站我自己找的教程:史上最詳細的easyx圖形庫入門講解
?這一篇與上一章的部分思路相同:放置雷與初始化雷盤,不過由于我們的游戲界面為圖形化界面我們的雷盤只需設置一個存放信息(雷和雷周圍的信息),而且放雷的時候可以直接將雷的信息放在雷的周圍更加方便,由于存放信息的雷盤只有一個,因此我們設置整形的數(shù)組會更加方便一些!
準備階段
所需圖片:
圖片資源: 百度云盤,點擊即可進去
提取碼: 6666
防止字符集出現(xiàn)問題:
為了更好的理解下文我們先把頭文件先給出:
#define _CRT_SECURE_NO_WARNINGS 1
#define ROWS 11//行
#define COLS 11//列
#define COL (ROWS-2)//打印的列,括號是為了防止運算沖突4
#define ROW (COLS-2)//打印的行
#define MINE 10
#include <graphics.h>//要包含在SIZE的前面,防止與里面的SIZE沖突。EasyX要用
#define SIZE 50
#include <stdio.h>
#include <time.h>//time函數(shù)的頭文件,c++只能用這個
#include <stdlib.h>//srand和rand函數(shù)的頭文件,c++只能用這個
#include <mmsystem.h>//播放音樂所用的頭文件,是系統(tǒng)自帶的
#pragma comment(lib,"winmm.lib")//加載靜態(tài)庫
//初始化函數(shù)
void Initboard(int board[ROWS][COLS],int rows, int cols,int m);
//打印函數(shù)
void Printboard(int board[ROWS][COLS], int row, int col);
//設置雷的函數(shù)
void Setmine(int board[ROWS][COLS], int row, int col);
//加載圖片的函數(shù)
void loadimages();
//放圖片的函數(shù)
void putimages(int board[ROWS][COLS], int row, int col);
//加密的函數(shù)
void password(int board[ROWS][COLS], int rows, int cols);
//鼠標信息的函數(shù)
void mouseimages(int board[ROWS][COLS]);
//判斷輸贏的函數(shù)
void judge(int mine[ROWS][COLS]);
正文
說明:我們先在實現(xiàn)的邏輯的源文件實現(xiàn)函數(shù)的功能,,最后我們再把功能匯總一下,這樣邏輯比較順。
一.雷盤信息的存儲
1.設置雷盤11*11與初始化
作用:防止在排查雷時,數(shù)組越界。
說明:數(shù)組已經(jīng)初始化,下面只是初始化雷盤的函數(shù)。
代碼:
//這里四個參數(shù)的功能與基礎篇相同
void Initboard(int board[ROWS][COLS], int rows, int cols, int m)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = 0;
}
}
}
2.放置雷
注意:
1.在.cpp后綴的文件中引用time函數(shù)時只能用time.h
2.在.cpp后綴的文件中引用srand函數(shù)和rand函數(shù)時只能用stdlib.h
說明:下面的代碼的隨機數(shù)起點已經(jīng)在項目開始時建立,下面是設置雷的函數(shù)
代碼:
void Setmine(int board[ROWS][COLS], int row, int col)
{
int count = 0;
while (count<MINE)
{
//隨機坐標
//橫坐標,行
int x = rand() % 9 + 1;//1——9
//縱坐標,列
int y = rand() % 9 + 1;
if (board[x][y] == 0)
{
board[x][y] = -1;
//在雷的周圍加1,下面的放置雷周圍的信息會有說明
mine_information(board,x,y);
count++;
}
}
}
3.放置雷周圍的信息
圖解:
注意:是在每次放一個雷后在周圍加一,到這就可理解上面的代碼了。
代碼:
//放置static的目的是將外部鏈接屬性改為內(nèi)部鏈接屬性,使此函數(shù)只能在實現(xiàn)邏輯的
//源文件中進行使用,更為安全。
static void mine_information(int board[ROWS][COLS], int x, int y)
{
int i = 0;
int j = 0;
for (i = x - 1; i <= x + 1; i++)
{
for (j = y - 1; j <= y + 1; j++)
{
if (i != x || j != y)//i與j不能同時為x和y
{
board[i][j] += 1;
}
}
}
}
二.圖形化界面
1.創(chuàng)建與初始化窗口
在main函數(shù)里面創(chuàng)建
int main()
{
//創(chuàng)建一個9*50(寬),10*50(高),并且展示控制臺窗口。
initgraph((ROW) * SIZE, (COL+1) * SIZE, SHOWCONSOLE);
//游戲的邏輯省去了,最后接上去
getchar();
closegraph();
retuen 0;
}
2.加載圖片
我們先把所需的圖片加載之后才能進行使用,否則使用不了。
代碼:
void loadimages()
{
char fill[50] = "";
int i = 0;
for (i = 0; i < 12; i++)
{
sprintf(fill, "./掃雷/%d.jpg", i);
loadimage(&image[i], fill,SIZE,SIZE);//設置50*50的大小
}
loadimage(&image[12], "./掃雷/12.jpg",SIZE*ROW,SIZE);//設置450*50的大小
}
3.放入圖片
如何放呢?
前九行放雷信息的圖片,最后一行放雷的個數(shù)的圖片。
尤其注意:行和列與橫坐標和縱坐標的關系,將行和列轉(zhuǎn)化成界面的縱坐標和橫坐標,再放進去。
代碼:
void putimages(int board[ROWS][COLS],int row, int col)
{
putimage(0, ROW * SIZE, &image[12]);
int i = 0;
int j = 0;
for (i = 1; i <= row; i++)
{
//行為縱坐標
for (j = 1; j <= col; j++)
{
//列為橫坐標
int n = board[i][j];//方便書寫
if (n == -1)
{
putimage((j - 1) * SIZE, (i - 1) * SIZE, &image[9]);
}
else if (n >= 0 && n <= 8)
{
putimage((j - 1) * SIZE, (i - 1) * SIZE, &image[n]);
}
//加密之后
else if (n >= 19 && n <= 28)
{
putimage((j - 1) * SIZE, (i - 1) * SIZE, &image[10]);//加密格子
}
else if (n >= 39 && n <= 48)
{
putimage((j - 1) * SIZE, (i - 1) * SIZE, &image[11]);//標記
}
}
}
}
4.加密格子
?將格子加上20之后就將格子加密了,當你點擊時,這個格子所對應的數(shù)組的元素減去二十,再把原來的圖片(這個位置存儲的信息)放上去即可。
代碼:
void password(int board[ROWS][COLS], int rows, int cols)
{
//將所有格子都加上20
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] +=20;
}
}
}
三.鼠標點擊
1.具體步驟
1.獲取鼠標信息
2.將鼠標信息轉(zhuǎn)化為數(shù)組下標
3.將鼠標信息進行分發(fā)
4.將情況分類進行解密與加密
2.代碼實現(xiàn)
void mouseimages(int board[ROWS][COLS])
{
if (MouseHit())
{
MOUSEMSG msg = GetMouseMsg();
//列對應橫坐標
int col = msg.x / SIZE + 1;
//行對應縱坐標
int row = msg.y / SIZE + 1;
int m = board[row][col];
switch (msg.uMsg)//分發(fā)鼠標信息
{
case WM_LBUTTONDOWN:
if (m >= 19 && m <= 48)//只有在這個范圍才執(zhí)行操作,否則會將這個格子弄沒
{
board[row][col] -= 20;
}
//遞歸展開省略了
break;
case WM_RBUTTONDOWN:
if (m >= 19 && m <= 28)
{
board[row][col] += 20;
}
break;
}
}
}
四.遞歸展開
1.具體步驟
1.在為空格時,將周圍的格子打開,且不為自身
2.打開的格子是加密的
3.加密的格子不是雷
4.如果為空繼續(xù)調(diào)用
2.代碼實現(xiàn)
static void Nullarround(int board[ROWS][COLS], int x, int y)
{
if (board[x][y] == 0)//判斷是否為空白
{
int i = 0;
int j = 0;
for (i = x - 1; i <= x + 1; i++)
{
for (j = y - 1; j <= y + 1; j++)
{
if (i != x || j != y)
{
if (board[i][j] != 19 && board[i][j] >= 9)
//比沒加密大就是加密的格子,且加密的格子不為雷
{
board[i][j] -= 20;
Nullarround(board, i, j);//繼續(xù)調(diào)用,為空格繼續(xù)展開。
}
}
}
}
}
}
五.判斷輸贏
1.具體步驟
?每次打開后都要判斷一下,遞歸展開中也是。說明,這里如果輸了或贏了,我們設置一個標志為flag為0,如果每次點擊不為雷,那就加一,輸了就設置為-1。
在贏或輸之后我們就提示一下,是否要繼續(xù)再開一把。
2.代碼實現(xiàn)
void judge(int mine[ROWS][COLS])
{
if (flag == -1)
{
//失敗
int isok = MessageBox(GetHWnd(), "很遺憾!你輸了!是否再來一把?", "提示", MB_OKCANCEL);
if (isok == IDOK)
{
flag = 0;
//將游戲初始化,意思就是再開一把
Initboard(mine, ROWS, ROWS, 0);
Setmine(mine, ROW, COL);
password(mine, ROWS, ROWS);
}
else
{
exit(5201314);//參數(shù)為隨機數(shù),退出程序。
}
}
if (flag == ROW * COL - MINE)
{
//勝利
int isok = MessageBox(GetHWnd(), "很高興!你贏了!是否再來一把?", "提示", MB_OKCANCEL);
if (isok == IDOK)
{
flag = 0;
//將游戲初始化
Initboard(mine, ROWS, ROWS, 0);
Setmine(mine, ROW, COL);
password(mine, ROWS, ROWS);
}
else
{
exit(5201314);//隨機數(shù)
}
}
}
六.設置音樂與點擊音效
入門EasyX的教程里面都有細說,如果不明白可以看一下教程,就在文章開頭,點擊即可進入。
1.播放音樂
代碼:
//初始化界面時要打開音樂
mciSendString("open ./掃雷/卡農(nóng).mp3", 0, 0, 0);
//打開音樂后要播放音樂
mciSendString("play ./掃雷/卡農(nóng).mp3 repeat", 0, 0, 0);
//游戲結束后要關閉音樂
mciSendString("close ./掃雷/卡農(nóng).mp3 repeat", 0, 0, 0);
2.播放音效
說明:每次點擊要播放,播放完或者下一次播放時關閉,要不然只會響一次。
mciSendString("close ./掃雷/點擊聲音.wav", 0, 0, 0);
mciSendString("open ./掃雷/點擊聲音.wav", 0, 0, 0);
mciSendString("play ./掃雷/點擊聲音.wav", 0, 0, 0);
七.總結代碼
1.運行邏輯的代碼:mine.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include "mine.h"
int flag = 0;
int main()
{
initgraph((ROW) * SIZE, (COL+1) * SIZE, SHOWCONSOLE);
setbkcolor(WHITE);
cleardevice();
srand((unsigned int)time(NULL));
int mine[ROWS][COLS] = { 0 };
Initboard(mine, ROWS, ROWS, 0);
Setmine(mine,ROW,COL);
password(mine, ROWS, ROWS);
Printboard(mine, ROW, COL);
mciSendString("open ./掃雷/卡農(nóng).mp3", 0, 0, 0);
mciSendString("play ./掃雷/卡農(nóng).mp3 repeat", 0, 0, 0);
loadimages();
//每次放圖片,鼠標點擊,與判斷是否結束是循環(huán)。
while (1)
{
BeginBatchDraw();//批量開始繪圖使圖形更加的穩(wěn)定
putimages(mine, ROW, COL);
FlushBatchDraw();//批量結束繪圖使圖形更加的穩(wěn)定
mouseimages(mine);
judge(mine);
//Printboard(mine, ROW, COL);
}
int ret = getchar();
closegraph();
}
2.頭文件代碼:mine.h
#define _CRT_SECURE_NO_WARNINGS 1
#define ROWS 11
#define COLS 11
#define COL (ROWS-2)
#define ROW (COLS-2)
#define MINE 10
#include <graphics.h>//要包含在SIZE的前面,防止與里面的SIZE沖突。
#define SIZE 50
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <mmsystem.h>
#pragma comment(lib,"winmm.lib")
void Initboard(int board[ROWS][COLS],int rows, int cols,int m);
void Printboard(int board[ROWS][COLS], int row, int col);
void Setmine(int board[ROWS][COLS], int row, int col);
void loadimages();
void putimages(int board[ROWS][COLS], int row, int col);
void password(int board[ROWS][COLS], int rows, int cols);
void mouseimages(int board[ROWS][COLS]);
void judge(int mine[ROWS][COLS]);
3.實現(xiàn)邏輯的代碼:源.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include "mine.h"
IMAGE image[13];
extern int flag;
static void Nullarround(int board[ROWS][COLS], int x, int y)
{
if (board[x][y] == 0)//判斷是否為空白
{
int i = 0;
int j = 0;
for (i = x - 1; i <= x + 1; i++)
{
for (j = y - 1; j <= y + 1; j++)
{
if (i != x || j != y)
{
if (board[i][j] != 19 && board[i][j] >= 9)//比沒加密大就是加密的格子
{
board[i][j] -= 20;
flag++;
Nullarround(board, i, j);//繼續(xù)調(diào)用,為空格繼續(xù)展開。
}
}
}
}
}
}
static void mine_information(int board[ROWS][COLS], int x, int y)
{
int i = 0;
int j = 0;
for (i = x - 1; i <= x + 1; i++)
{
for (j = y - 1; j <= y + 1; j++)
{
if ((i != x || j !=y)&&board[i][j]!=-1)
{
board[i][j] += 1;
}
}
}
}
void Initboard(int board[ROWS][COLS], int rows, int cols, int m)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = 0;
}
}
}
void Printboard(int board[ROWS][COLS], int row, int col)
{
system("cls");
int i = 0;
int j = 0;
for (i = 1; i <= row; i++)
{
for (j = 1; j <= col; j++)
{
printf("%2d ",board[i][j]);
}
printf("\n");
}
}
void Setmine(int board[ROWS][COLS], int row, int col)
{
int count = MINE;
while (count)
{
//隨機坐標
//橫坐標,行
int x = rand() % 9 + 1;//1——9
//縱坐標,列
int y = rand() % 9 + 1;
if (board[x][y] == 0)
{
board[x][y] = -1;
//在雷的周圍加1
mine_information(board,x,y);
count--;
}
}
}
void loadimages()
{
char fill[50] = "";
int i = 0;
for (i = 0; i < 12; i++)
{
sprintf(fill, "./掃雷/%d.jpg", i);
loadimage(&image[i], fill,SIZE,SIZE);
}
loadimage(&image[12], "./掃雷/12.png",SIZE*ROW,SIZE);
}
void putimages(int board[ROWS][COLS],int row, int col)
{
putimage(0, ROW * SIZE, &image[12]);
int i = 0;
int j = 0;
for (i = 1; i <= row; i++)
{
//行為縱坐標
for (j = 1; j <= col; j++)
{
//列為橫坐標
int n = board[i][j];
if (n == -1)
{
putimage((j - 1) * SIZE, (i - 1) * SIZE, &image[9]);
}
else if (n >= 0 && n <= 8)
{
putimage((j - 1) * SIZE, (i - 1) * SIZE, &image[n]);
}
//加密之后
else if (n >= 19 && n <= 28)
{
putimage((j - 1) * SIZE, (i - 1) * SIZE, &image[10]);//加密格子
}
else if (n >= 39 && n <= 48)
{
putimage((j - 1) * SIZE, (i - 1) * SIZE, &image[11]);//標記
}
}
}
}
//加密
void password(int board[ROWS][COLS], int rows, int cols)
{
//將所有格子都加上20
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] +=20;
}
}
}
void mouseimages(int board[ROWS][COLS])
{
if (MouseHit())
{
MOUSEMSG msg = GetMouseMsg();
//列對應橫坐標
int col = msg.x / SIZE + 1;
//行對應縱坐標
int row = msg.y / SIZE + 1;
int m = board[row][col];
switch (msg.uMsg)//分發(fā)鼠標信息
{
case WM_LBUTTONDOWN:
if (m >= 19 && m <= 48)
{
mciSendString("close ./掃雷/點擊聲音.wav", 0, 0, 0);
mciSendString("open ./掃雷/點擊聲音.wav", 0, 0, 0);
mciSendString("play ./掃雷/點擊聲音.wav", 0, 0, 0);
board[row][col] -= 20;
if (board[row][col] != -1)
{
flag++;
}
else
{
flag = -1;
break;
}
}
//遞歸展開
Nullarround(board, row, col);
break;
case WM_RBUTTONDOWN:
if (m >= 19 && m <= 28)
{
board[row][col] += 20;
}
break;
}
}
}
void judge(int mine[ROWS][COLS])
{
if (flag == -1)
{
//失敗
int isok = MessageBox(GetHWnd(), "很遺憾!你輸了!是否再來一把?", "提示", MB_OKCANCEL);
if (isok == IDOK)
{
flag = 0;
//將游戲初始化
Initboard(mine, ROWS, ROWS, 0);
Setmine(mine, ROW, COL);
password(mine, ROWS, ROWS);
}
else
{
mciSendString("close ./掃雷/卡農(nóng).mp3", 0, 0, 0);
exit(5201314);//隨機數(shù)
}
}
if (flag == ROW * COL - MINE)
{
//勝利
int isok = MessageBox(GetHWnd(), "很高興!你贏了!是否再來一把?", "提示", MB_OKCANCEL);
if (isok == IDOK)
{
flag = 0;
//將游戲初始化
Initboard(mine, ROWS, ROWS, 0);
Setmine(mine, ROW, COL);
password(mine, ROWS, ROWS);
}
else
{
mciSendString("close ./掃雷/卡農(nóng).mp3", 0, 0, 0);
exit(5201314);//隨機數(shù)
}
}
}
效果:文章來源:http://www.zghlxwxcb.cn/news/detail-484672.html
總結
如果能認真看到這里,我堅信你能收獲很多很多!也希望這篇文章能幫助到你,如果覺得不錯,請點擊一下不要錢的贊,如果有誤請溫柔的指出,在這里感謝大家了!文章來源地址http://www.zghlxwxcb.cn/news/detail-484672.html
到了這里,關于入門C語言第三話:數(shù)組之實戰(zhàn)篇——掃雷(進階版——圖形化界面,遞歸展開,播放音樂與音效,標記取消雷,記錄雷的個數(shù),鼠標點擊,文末附有完整代碼)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!