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

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

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;//標記雷的個數(shù)
while (1)
{
Menu1();
printf("請輸入你的選擇:>");
scanf("%d", &input1);
printf("\n");
if (input1 == 1)
{
int x = 0;
int y = 0;
printf("請輸入要排查的坐標:>");
scanf("%d %d", &x, &y);
//坐標是否合法
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] != '*')
{
printf("該坐標被排查過了,不能重復排查\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)計mine數(shù)組中x,y坐標周圍有幾個0
show[x][y] = count + '0';
DisplayBoard(show, ROW, COL);
}
//int count = get_mine_count(mine, x, y);//統(tǒng)計mine數(shù)組中x,y坐標周圍有幾個0
//show[x][y] = count + '0';//數(shù)字轉(zhuǎn)換為字符
}
}
}
else
{
printf("輸入坐標非法?。?!請重新輸入。\n");
}
}
else if (input1 == 2)
{
printf("請開始標記雷:");
flag_count = Flagmine(show, ROW, COL, flag_count);
DisplayBoard(show, ROW, COL);
}
else if (input1 == 3)
{
printf("請取消已經(jīng)標記雷:");
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.添加標記 ***\n\n");
printf("\t*** 3.取消標記 ***\n\n");
}7.排查位置周圍的八個坐標有幾個雷
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),坐標是否越界
if (x == 0 || y == 0 || x == ROWS - 1 || y == COLS - 1)
{
return;
}
//判斷該坐標是否已經(jīng)被排查過了
if (show[x][y] != '*')
{
return;
}
//開始準備遞歸
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.標記功能
//標記功能——>玩家可以自行標記自己覺得是雷的位置
int Flagmine(char show[ROWS][COLS], int row, int col,int flag_count)
{
int x = 0;
int y = 0;
//如果目前雷盤上已經(jīng)標記過的點的數(shù)量已經(jīng)和我們要排的雷的數(shù)量相等的話,顯示無法標記
if (flag_count == EASY_COUNT)
{
printf("目前雷盤上已經(jīng)存在和所要排雷數(shù)量相等的標記,無法進行標記!?。n");
return;
}
printf("請輸入你要標記的位置坐標:> ");
scanf("%d %d", &x, &y);
//判斷坐標是否在指定的區(qū)域
if (x > 0 && x <= row && y > 0 && y <= col)
{
//判斷該坐標是否仍未被排除
if (show[x][y] == '*')
{
show[x][y] = '!';
flag_count++;
}
else
{
printf("該位置不可能是雷,請重新輸入\n");
}
}
else
{
printf("該坐標不合法,請重新輸入:>\n");
}
return flag_count;
}10.取消標記功能
//取消標記的功能
int Cancelflag(char show[ROWS][COLS], int row, int col, int flag_count)
{
int x = 0;
int y = 0;
printf("請輸入你要取消標記的位置坐標:> ");
scanf("%d %d", &x, &y);
//判斷坐標是否在指定的區(qū)域
if (x > 0 && x <= row && y > 0 && y <= col)
{
if (show[x][y] == '!')
{
show[x][y] = '*';
flag_count--;
}
else
{
printf("該坐標沒有被標記,無需取消標記\n");
}
}
else
{
printf("該坐標不合法,請重新輸入:>");
}
return flag_count;
}完整代碼
1.game.c
掃雷游戲代碼
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//mine數(shù)組在沒有布置雷的時候,全是'0'
//show數(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;//雷的個數(shù)
while (count)
{
int x = rand() % row + 1;//1~9
int y = rand() % col + 1;//1~9
if (board[x][y] == '0')//查看該坐標處是否已經(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),坐標是否越界
if (x == 0 || y == 0 || x == ROWS - 1 || y == COLS - 1)
{
return;
}
//判斷該坐標是否已經(jīng)被排查過了
if (show[x][y] != '*')
{
return;
}
//開始準備遞歸
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';
}
}
//標記功能——>玩家可以自行標記自己覺得是雷的位置
int Flagmine(char show[ROWS][COLS], int row, int col,int flag_count)
{
int x = 0;
int y = 0;
//如果目前雷盤上已經(jīng)標記過的點的數(shù)量已經(jīng)和我們要排的雷的數(shù)量相等的話,顯示無法標記
if (flag_count == EASY_COUNT)
{
printf("目前雷盤上已經(jīng)存在和所要排雷數(shù)量相等的標記,無法進行標記?。。n");
return;
}
printf("請輸入你要標記的位置坐標:> ");
scanf("%d %d", &x, &y);
//判斷坐標是否在指定的區(qū)域
if (x > 0 && x <= row && y > 0 && y <= col)
{
//判斷該坐標是否仍未被排除
if (show[x][y] == '*')
{
show[x][y] = '!';
flag_count++;
}
else
{
printf("該位置不可能是雷,請重新輸入\n");
}
}
else
{
printf("該坐標不合法,請重新輸入:>\n");
}
return flag_count;
}
//取消標記的功能
int Cancelflag(char show[ROWS][COLS], int row, int col, int flag_count)
{
int x = 0;
int y = 0;
printf("請輸入你要取消標記的位置坐標:> ");
scanf("%d %d", &x, &y);
//判斷坐標是否在指定的區(qū)域
if (x > 0 && x <= row && y > 0 && y <= col)
{
if (show[x][y] == '!')
{
show[x][y] = '*';
flag_count--;
}
else
{
printf("該坐標沒有被標記,無需取消標記\n");
}
}
else
{
printf("該坐標不合法,請重新輸入:>");
}
return flag_count;
}
void Menu1()
{
printf("\t*** 1.開始排雷 ***\n\n");
printf("\t*** 2.添加標記 ***\n\n");
printf("\t*** 3.取消標記 ***\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;//標記雷的個數(shù)
while (1)
{
Menu1();
printf("請輸入你的選擇:>");
scanf("%d", &input1);
printf("\n");
if (input1 == 1)
{
int x = 0;
int y = 0;
printf("請輸入要排查的坐標:>");
scanf("%d %d", &x, &y);
//坐標是否合法
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] != '*')
{
printf("該坐標被排查過了,不能重復排查\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)計mine數(shù)組中x,y坐標周圍有幾個0
show[x][y] = count + '0';
DisplayBoard(show, ROW, COL);
}
//int count = get_mine_count(mine, x, y);//統(tǒng)計mine數(shù)組中x,y坐標周圍有幾個0
//show[x][y] = count + '0';//數(shù)字轉(zhuǎn)換為字符
}
}
}
else
{
printf("輸入坐標非法?。?!請重新輸入。\n");
}
}
else if (input1 == 2)
{
printf("請開始標記雷:");
flag_count = Flagmine(show, ROW, COL, flag_count);
DisplayBoard(show, ROW, COL);
}
else if (input1 == 3)
{
printf("請取消已經(jīng)標記雷:");
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è)置隨機數(shù)的生成起點
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("輸入錯誤,請重新選擇。\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);
詳細代碼:掃雷進階版
到此這篇關(guān)于C語言實現(xiàn)爆炸展開的掃雷詳解的文章就介紹到這了,更多相關(guān)C語言掃雷內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言用函數(shù)實現(xiàn)電話簿管理系統(tǒng)
這篇文章主要為大家詳細介紹了C語言用函數(shù)實現(xiàn)電話簿管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-12-12

