C語言實(shí)現(xiàn)爆炸展開的掃雷詳解
游戲介紹
首先,我們來說基礎(chǔ)版的掃雷游戲有什么功能:
1.打印菜單,由玩家選擇玩游戲或者是退出游戲。
2.打印雷盤,讓玩家知道我們的雷盤是什么樣子的,從而讓玩家知道排雷的時(shí)候哪個(gè)位置對應(yīng)著哪個(gè)坐標(biāo)。
3.玩家開始排雷,并在排雷的函數(shù)中加入判斷輸贏的模塊。
以上就是我們基礎(chǔ)版掃雷的功能啦?。。‘?dāng)然,這樣玩掃雷這個(gè)游戲會很累的,因?yàn)槲覀冊谟螒蛑性O(shè)置的展現(xiàn)給玩家的雷盤是9X9的雷盤,也就是說,我們?nèi)绻脍A,我們就需要在這個(gè)雷盤中排查71個(gè)非雷部分(當(dāng)然,如果排查到雷那游戲就會直接結(jié)束了?。。┻@樣的游戲是毫無游戲體驗(yàn)感的。
所以,我們今天來學(xué)習(xí)一下,如何讓我們的掃雷游戲變得厲害起來?。?!
那么,我們進(jìn)階版的掃雷游戲有什么新加的功能吶???
1.在玩家排雷的模塊,我們增添了爆炸展開的情況。如果玩家排雷的位置沒有雷,并且,周圍的位置也沒有雷,我們就讓這些位置爆炸式的展開。
2.在玩家開始排雷之前,我們增加了一個(gè)小菜單,用來讓玩家選擇排雷,添加標(biāo)記或者是取消標(biāo)記。
3.為了增加游戲的快樂,我們增加了添加標(biāo)記和取消標(biāo)記這兩個(gè)功能。如果玩家認(rèn)為某個(gè)位置有雷的存在,就可以在那個(gè)位置增加一個(gè)" ! "的標(biāo)記。
游戲功能實(shí)現(xiàn)
1.主菜單:
在游戲開始之前,我們先給玩家來上這么一個(gè)菜單來供玩家選擇玩游戲還是退出游戲
void Menu()
{
printf("\t***************************************\n\n");
printf("\t************** 1.play ***************\n\n");
printf("\t************** 0.exit ***************\n\n");
printf("\t***************************************\n");
}2.初始化雷盤
//mine數(shù)組在沒有布置雷的時(shí)候,全是'0'
//show數(shù)組在沒有排查雷的時(shí)候,全是'*'
void Initboard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}3.打印雷盤
//打印雷盤
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("\t*** 掃雷游戲 ***\n\n");
printf("\t");
for (j = 0; j <= col; j++)
{
printf("%d ",j );
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("\t");
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("\n\t*** 掃雷選擇 ***\n\n");
}此時(shí),我們的調(diào)試結(jié)果應(yīng)該如下圖所示:

4.布置雷
void SetMine(char board[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;//雷的個(gè)數(shù)
while (count)
{
int x = rand() % row + 1;//1~9
int y = rand() % col + 1;//1~9
if (board[x][y] == '0')//查看該坐標(biāo)處是否已經(jīng)布置雷
{
board[x][y] = '1';
count--;
}
}
}這個(gè)時(shí)候,我們來看看是否能夠完美的布置好我們的雷:

5.玩家開始排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int input1 = 0;
int win = 0;//找到非雷的數(shù)量
int flag_count = 0;//標(biāo)記雷的個(gè)數(shù)
while (1)
{
Menu1();
printf("請輸入你的選擇:>");
scanf("%d", &input1);
printf("\n");
if (input1 == 1)
{
int x = 0;
int y = 0;
printf("請輸入要排查的坐標(biāo):>");
scanf("%d %d", &x, &y);
//坐標(biāo)是否合法
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] != '*')
{
printf("該坐標(biāo)被排查過了,不能重復(fù)排查\n");
}
else {
//是雷
if (mine[x][y] == '1')
{
printf("非常遺憾,你被炸死了?。。n");
DisplayBoard(mine, ROW, COL);
break;
}
//不是雷
else
{
win++;
broad(mine, show, x, y);
//要注意字符1和數(shù)字1的區(qū)別
if (get_mine_count(mine, x, y) == 0)
{
show[x][y] = ' ';
system("cls");
DisplayBoard(show, ROW, COL);//如果該位置周圍沒有雷就顯示為空格
}
else
{
int count = get_mine_count(mine, x, y);//統(tǒng)計(jì)mine數(shù)組中x,y坐標(biāo)周圍有幾個(gè)0
show[x][y] = count + '0';
DisplayBoard(show, ROW, COL);
}
//int count = get_mine_count(mine, x, y);//統(tǒng)計(jì)mine數(shù)組中x,y坐標(biāo)周圍有幾個(gè)0
//show[x][y] = count + '0';//數(shù)字轉(zhuǎn)換為字符
}
}
}
else
{
printf("輸入坐標(biāo)非法?。?!請重新輸入。\n");
}
}
else if (input1 == 2)
{
printf("請開始標(biāo)記雷:");
flag_count = Flagmine(show, ROW, COL, flag_count);
DisplayBoard(show, ROW, COL);
}
else if (input1 == 3)
{
printf("請取消已經(jīng)標(biāo)記雷:");
flag_count = Cancelflag(show, ROW, COL, flag_count);
DisplayBoard(show, ROW, COL);
}
if (win == COL * ROW)
{
printf("恭喜你排雷成功?。。n");
DisplayBoard(mine, ROW, COL);
break;
}
}
}6.小菜單
void Menu1()
{
printf("\t*** 1.開始排雷 ***\n\n");
printf("\t*** 2.添加標(biāo)記 ***\n\n");
printf("\t*** 3.取消標(biāo)記 ***\n\n");
}7.排查位置周圍的八個(gè)坐標(biāo)有幾個(gè)雷
int get_mine_count(char board[ROWS][COLS], int x, int y)
{
return (board[x - 1][y] + board[x - 1][y - 1] + board[x][y - 1] +
board[x + 1][y - 1] + board[x + 1][y] + board[x + 1][y + 1] +
board[x][y + 1] + board[x - 1][y + 1] - 8 * '0');
}8.使用遞歸爆炸式展開
void broad(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
//判斷是否在范圍內(nèi),坐標(biāo)是否越界
if (x == 0 || y == 0 || x == ROWS - 1 || y == COLS - 1)
{
return;
}
//判斷該坐標(biāo)是否已經(jīng)被排查過了
if (show[x][y] != '*')
{
return;
}
//開始準(zhǔn)備遞歸
int count = get_mine_count(mine, x, y);
if (count == 0)
{
show[x][y] = ' ';
broad(mine, show, x - 1, y);
broad(mine, show, x - 1, y - 1);
broad(mine, show, x, y - 1);
broad(mine, show, x + 1, y - 1);
broad(mine, show, x + 1, y);
broad(mine, show, x + 1, y + 1);
broad(mine, show, x, y + 1);
broad(mine, show, x - 1, y + 1);
}
else if (count > 0)
{
show[x][y] = count + '0';
}
}9.標(biāo)記功能
//標(biāo)記功能——>玩家可以自行標(biāo)記自己覺得是雷的位置
int Flagmine(char show[ROWS][COLS], int row, int col,int flag_count)
{
int x = 0;
int y = 0;
//如果目前雷盤上已經(jīng)標(biāo)記過的點(diǎn)的數(shù)量已經(jīng)和我們要排的雷的數(shù)量相等的話,顯示無法標(biāo)記
if (flag_count == EASY_COUNT)
{
printf("目前雷盤上已經(jīng)存在和所要排雷數(shù)量相等的標(biāo)記,無法進(jìn)行標(biāo)記?。?!\n");
return;
}
printf("請輸入你要標(biāo)記的位置坐標(biāo):> ");
scanf("%d %d", &x, &y);
//判斷坐標(biāo)是否在指定的區(qū)域
if (x > 0 && x <= row && y > 0 && y <= col)
{
//判斷該坐標(biāo)是否仍未被排除
if (show[x][y] == '*')
{
show[x][y] = '!';
flag_count++;
}
else
{
printf("該位置不可能是雷,請重新輸入\n");
}
}
else
{
printf("該坐標(biāo)不合法,請重新輸入:>\n");
}
return flag_count;
}10.取消標(biāo)記功能
//取消標(biāo)記的功能
int Cancelflag(char show[ROWS][COLS], int row, int col, int flag_count)
{
int x = 0;
int y = 0;
printf("請輸入你要取消標(biāo)記的位置坐標(biāo):> ");
scanf("%d %d", &x, &y);
//判斷坐標(biāo)是否在指定的區(qū)域
if (x > 0 && x <= row && y > 0 && y <= col)
{
if (show[x][y] == '!')
{
show[x][y] = '*';
flag_count--;
}
else
{
printf("該坐標(biāo)沒有被標(biāo)記,無需取消標(biāo)記\n");
}
}
else
{
printf("該坐標(biāo)不合法,請重新輸入:>");
}
return flag_count;
}完整代碼
1.game.c
掃雷游戲代碼
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//mine數(shù)組在沒有布置雷的時(shí)候,全是'0'
//show數(shù)組在沒有排查雷的時(shí)候,全是'*'
void Initboard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
//打印棋盤
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("\t*** 掃雷游戲 ***\n\n");
printf("\t");
for (j = 0; j <= col; j++)
{
printf("%d ",j );
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("\t");
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("\n\t*** 掃雷選擇 ***\n\n");
}
//設(shè)置雷
void SetMine(char board[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;//雷的個(gè)數(shù)
while (count)
{
int x = rand() % row + 1;//1~9
int y = rand() % col + 1;//1~9
if (board[x][y] == '0')//查看該坐標(biāo)處是否已經(jīng)布置雷
{
board[x][y] = '1';
count--;
}
}
}
//排查雷
int get_mine_count(char board[ROWS][COLS], int x, int y)
{
return (board[x - 1][y] + board[x - 1][y - 1] + board[x][y - 1] +
board[x + 1][y - 1] + board[x + 1][y] + board[x + 1][y + 1] +
board[x][y + 1] + board[x - 1][y + 1] - 8 * '0');
}
//遞歸爆炸式展開
void broad(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
//判斷是否在范圍內(nèi),坐標(biāo)是否越界
if (x == 0 || y == 0 || x == ROWS - 1 || y == COLS - 1)
{
return;
}
//判斷該坐標(biāo)是否已經(jīng)被排查過了
if (show[x][y] != '*')
{
return;
}
//開始準(zhǔn)備遞歸
int count = get_mine_count(mine, x, y);
if (count == 0)
{
show[x][y] = ' ';
broad(mine, show, x - 1, y);
broad(mine, show, x - 1, y - 1);
broad(mine, show, x, y - 1);
broad(mine, show, x + 1, y - 1);
broad(mine, show, x + 1, y);
broad(mine, show, x + 1, y + 1);
broad(mine, show, x, y + 1);
broad(mine, show, x - 1, y + 1);
}
else if (count > 0)
{
show[x][y] = count + '0';
}
}
//標(biāo)記功能——>玩家可以自行標(biāo)記自己覺得是雷的位置
int Flagmine(char show[ROWS][COLS], int row, int col,int flag_count)
{
int x = 0;
int y = 0;
//如果目前雷盤上已經(jīng)標(biāo)記過的點(diǎn)的數(shù)量已經(jīng)和我們要排的雷的數(shù)量相等的話,顯示無法標(biāo)記
if (flag_count == EASY_COUNT)
{
printf("目前雷盤上已經(jīng)存在和所要排雷數(shù)量相等的標(biāo)記,無法進(jìn)行標(biāo)記?。?!\n");
return;
}
printf("請輸入你要標(biāo)記的位置坐標(biāo):> ");
scanf("%d %d", &x, &y);
//判斷坐標(biāo)是否在指定的區(qū)域
if (x > 0 && x <= row && y > 0 && y <= col)
{
//判斷該坐標(biāo)是否仍未被排除
if (show[x][y] == '*')
{
show[x][y] = '!';
flag_count++;
}
else
{
printf("該位置不可能是雷,請重新輸入\n");
}
}
else
{
printf("該坐標(biāo)不合法,請重新輸入:>\n");
}
return flag_count;
}
//取消標(biāo)記的功能
int Cancelflag(char show[ROWS][COLS], int row, int col, int flag_count)
{
int x = 0;
int y = 0;
printf("請輸入你要取消標(biāo)記的位置坐標(biāo):> ");
scanf("%d %d", &x, &y);
//判斷坐標(biāo)是否在指定的區(qū)域
if (x > 0 && x <= row && y > 0 && y <= col)
{
if (show[x][y] == '!')
{
show[x][y] = '*';
flag_count--;
}
else
{
printf("該坐標(biāo)沒有被標(biāo)記,無需取消標(biāo)記\n");
}
}
else
{
printf("該坐標(biāo)不合法,請重新輸入:>");
}
return flag_count;
}
void Menu1()
{
printf("\t*** 1.開始排雷 ***\n\n");
printf("\t*** 2.添加標(biāo)記 ***\n\n");
printf("\t*** 3.取消標(biāo)記 ***\n\n");
}
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int input1 = 0;
int win = 0;//找到非雷的數(shù)量
int flag_count = 0;//標(biāo)記雷的個(gè)數(shù)
while (1)
{
Menu1();
printf("請輸入你的選擇:>");
scanf("%d", &input1);
printf("\n");
if (input1 == 1)
{
int x = 0;
int y = 0;
printf("請輸入要排查的坐標(biāo):>");
scanf("%d %d", &x, &y);
//坐標(biāo)是否合法
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] != '*')
{
printf("該坐標(biāo)被排查過了,不能重復(fù)排查\n");
}
else {
//是雷
if (mine[x][y] == '1')
{
printf("非常遺憾,你被炸死了?。?!\n");
DisplayBoard(mine, ROW, COL);
break;
}
//不是雷
else
{
win++;
broad(mine, show, x, y);
//要注意字符1和數(shù)字1的區(qū)別
if (get_mine_count(mine, x, y) == 0)
{
show[x][y] = ' ';
system("cls");
DisplayBoard(show, ROW, COL);//如果該位置周圍沒有雷就顯示為空格
}
else
{
int count = get_mine_count(mine, x, y);//統(tǒng)計(jì)mine數(shù)組中x,y坐標(biāo)周圍有幾個(gè)0
show[x][y] = count + '0';
DisplayBoard(show, ROW, COL);
}
//int count = get_mine_count(mine, x, y);//統(tǒng)計(jì)mine數(shù)組中x,y坐標(biāo)周圍有幾個(gè)0
//show[x][y] = count + '0';//數(shù)字轉(zhuǎn)換為字符
}
}
}
else
{
printf("輸入坐標(biāo)非法!?。≌堉匦螺斎?。\n");
}
}
else if (input1 == 2)
{
printf("請開始標(biāo)記雷:");
flag_count = Flagmine(show, ROW, COL, flag_count);
DisplayBoard(show, ROW, COL);
}
else if (input1 == 3)
{
printf("請取消已經(jīng)標(biāo)記雷:");
flag_count = Cancelflag(show, ROW, COL, flag_count);
DisplayBoard(show, ROW, COL);
}
if (win == COL * ROW)
{
printf("恭喜你排雷成功?。?!\n");
DisplayBoard(mine, ROW, COL);
break;
}
}
}2.test.c
游戲主邏輯
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void Menu()
{
printf("\t***************************************\n\n");
printf("\t************** 1.play ***************\n\n");
printf("\t************** 0.exit ***************\n\n");
printf("\t***************************************\n");
}
void game()
{
char mine[ROWS][COLS] = { 0 };//用來存放布置好的雷
char show[ROWS][COLS] = { 0 };//用來存放排查出的雷的信息
//初始化數(shù)組的內(nèi)容為我們指定的內(nèi)容
Initboard(mine, ROWS, COLS, '0');
Initboard(show, ROWS, COLS, '*');
//設(shè)置雷
SetMine(mine, ROW, COL);
//打印棋盤
DisplayBoard(show, ROW, COL);
//DisplayBoard(mine, ROW, COL);
//排查雷
FindMine(mine, show, ROW, COL);//在mine中找雷。把雷放在show中
}
int main()
{
//設(shè)置隨機(jī)數(shù)的生成起點(diǎn)
srand((unsigned int)time(NULL));
int input = 0;
do
{
Menu();
printf("請輸入你的選擇:>");
scanf("%d", &input);
printf("\n");
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戲\n已退出游戲,歡迎您再次游玩\n");
break;
default:
printf("輸入錯(cuò)誤,請重新選擇。\n");
break;
}
Sleep(3000);
system("cls");
} while (input);
return 0;
}3.game.h
頭文件部分
#pragma once #include<stdio.h> #include<time.h> #include<stdlib.h> #define ROW 9 #define COL 9 #define ROWS ROW+2 #define COLS COL+2 #define EASY_COUNT 10 void Initboard(char board[ROWS][COLS], int rows, int cols, char set); void DisplayBoard(char board[ROWS][COLS], int row, int col); void SetMine(char board[ROWS][COLS], int row, int col); void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col); int get_mine_count(char mine[ROWS][COLS], int x, int y); void broad(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y); int Flagmine(char show[ROWS][COLS], int row, int col, int flag_count);
詳細(xì)代碼:掃雷進(jìn)階版
到此這篇關(guān)于C語言實(shí)現(xiàn)爆炸展開的掃雷詳解的文章就介紹到這了,更多相關(guān)C語言掃雷內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實(shí)現(xiàn)插入排序?qū)φ麛?shù)數(shù)組排序
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)插入排序?qū)φ麛?shù)數(shù)組排序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-05-05
C++實(shí)現(xiàn)的一個(gè)可以寫遞歸lambda的Y函數(shù)
這篇文章主要介紹了C++實(shí)現(xiàn)的一個(gè)可以寫遞歸lambda的Y函數(shù),在Y函數(shù)的幫助,這個(gè)lambda表達(dá)是可以成功看到自己,然后遞歸調(diào)用的,需要的朋友可以參考下2014-07-07
C++實(shí)現(xiàn)LeetCode(179.最大組合數(shù))
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(179.最大組合數(shù)),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08
c++動態(tài)庫調(diào)用的實(shí)現(xiàn)
本文主要介紹了c++動態(tài)庫調(diào)用的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07
C++使用easyX庫實(shí)現(xiàn)三星環(huán)繞效果流程詳解
EasyX是針對C/C++的圖形庫,可以幫助使用C/C++語言的程序員快速上手圖形和游戲編程。這篇文章主要介紹了C++使用easyX庫實(shí)現(xiàn)三星環(huán)繞效果,需要的可以參考一下2022-10-10
C語言實(shí)現(xiàn)貪吃蛇游戲設(shè)計(jì)
這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)貪吃蛇游戲設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-07-07
用C/C++代碼檢測ip能否ping通(配合awk和system可以做到批量檢測)
今天小編就為大家分享一篇關(guān)于用C/C++代碼檢測ip能否ping通(配合awk和system可以做到批量檢測),小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-04-04

