哈嘍,大家好,上次我們已經(jīng)學(xué)習(xí)了三子棋小游戲,今天我們來學(xué)習(xí)掃雷小游戲了。
目錄
1.游戲介紹
2.函數(shù)部分
2.1菜單
2.2game()函數(shù)
2.3mian()函數(shù)
2.4初始化棋盤
2.5打印棋盤
2.6布置雷
2.7排查雷
2.8統(tǒng)計(jì)雷
2.9遞歸,展開一片區(qū)域
3.完整代碼展示?
1.游戲介紹
想必大家都玩過掃雷這款小游戲吧?
在一個(gè)棋盤上隨機(jī)擺放數(shù)個(gè)雷,這些雷用戶無法看見,只能一個(gè)個(gè)將雷排查出來,用戶點(diǎn)擊一個(gè)格子,如果這個(gè)格子含有雷,游戲就以失敗告終,如果這個(gè)格子不是雷,就會(huì)在這個(gè)格子上顯示周圍8個(gè)格子共有多少個(gè)雷,如下圖:
?今天我們就用C語言來實(shí)現(xiàn)這個(gè)掃雷小游戲
2.函數(shù)部分
下面是游戲要用到的函數(shù):
//初始化棋盤
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);
//統(tǒng)計(jì)雷
int GetMineCount(char mine[ROWS][COLS], int x, int y);
//遞歸,展開一片區(qū)域
void DfsMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int row, int col);
2.1菜單
菜單非常簡(jiǎn)潔,用戶輸入1表示開始游戲,輸入0則退出小游戲
void menu()
{
printf("********************\n");
printf("***** 1.play *****\n");
printf("***** 0.exit *****\n");
printf("********************\n");
}
2.2game()函數(shù)
game()函數(shù)包含一個(gè)游戲的執(zhí)行過程,將一些函數(shù)組合了起來,形成游戲的完整過程。在這兒我們定義了兩個(gè)數(shù)組,mine數(shù)組表示存放的雷,show數(shù)組表示存放排查出雷的信息。
void game()
{
char mine[ROWS][COLS];//存放的雷
char show[ROWS][COLS];//存放盤查出雷的信息
//初始化棋盤
//mine數(shù)組最開始全是‘0’
//show數(shù)組最開始全是‘*’
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
DisPlayBoard(show, ROW, COL);
//布置雷
SetMine(mine, ROW, COL);
//排查雷
FindMine(mine, show, ROW, COL);
}
2.3mian()函數(shù)
main函數(shù)是整個(gè)程序中必不可少的一個(gè)部分。
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("請(qǐng)選擇:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
system("cls");
printf("退出游戲\n");
break;
default:
printf("選擇錯(cuò)誤,重新選擇\n");
break;
}
} while (input);
}
2.4初始化棋盤
初始化棋盤將兩個(gè)數(shù)組初始化。mine數(shù)組全部初始化為‘0’,表示最開始還沒有存放雷。show數(shù)組最開始初始化為‘*’。
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
for (i = 0; i < rows; i++)
{
int j = 0;
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
2.5打印棋盤
打印棋盤這個(gè)步驟很簡(jiǎn)單,但為了方便玩家,我們順便把棋盤的行號(hào)和列號(hào)也打印出來。如下圖:
void DisPlayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
printf("--------掃雷--------\n");
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
int j = 0;
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
2.6布置雷
布置雷就是讓電腦隨機(jī)生成10個(gè)不重復(fù)的坐標(biāo),這些坐標(biāo)就是雷的位置
void SetMine(char board[ROWS][COLS], int row, int col)
{
//布置十個(gè)雷
//隨機(jī)生成坐標(biāo)
int count = ESAY_COUNT;
while(count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
2.7排查雷
用戶輸入要排查的雷的坐標(biāo),如果該坐標(biāo)是雷,就輸出"很遺憾,你被炸死了“,否則統(tǒng)計(jì)這個(gè)位置周圍的八個(gè)位置雷的數(shù)量,存到show數(shù)組對(duì)應(yīng)坐標(biāo)位置里。同時(shí)這里擴(kuò)展了一個(gè)遞歸展開,可以展開一片非雷區(qū)域。
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x, y;
int win = 0;
while (win < row * col - ESAY_COUNT)
{
system("cls");
DisPlayBoard(show, ROW, COL);
printf("請(qǐng)輸入要排查雷的坐標(biāo):>");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == '1')
{
printf("很遺憾,你被炸死了\n");
break;
}
else
{
//該位置不是雷,就統(tǒng)計(jì)這個(gè)坐標(biāo)周圍有幾個(gè)雷
int count = GetMineCount(mine, x, y);
show[x][y] = count + '0';
if (count == 0)
{
//遞歸,展開一片區(qū)域
DfsMine(mine, show, x, y, ROW, COL);
}
show[x][y] = count + '0';
DisPlayBoard(show, ROW, COL);
win++;
}
}
else
{
printf("坐標(biāo)非法,重新輸入\n");
}
}
if (win == row * col - ESAY_COUNT)
{
printf("恭喜你,排雷成功\n");
}
DisPlayBoard(mine, ROW, COL);
}
2.8統(tǒng)計(jì)雷
這個(gè)函數(shù)只要返回坐標(biāo)(x,y)周圍雷的數(shù)量即可。
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
return (mine[x - 1][y - 1] + mine[x][y - 1] +
mine[x + 1][y - 1] + mine[x + 1][y] +
mine[x + 1][y + 1] + mine[x][y + 1] +
mine[x - 1][y + 1] + mine[x - 1][y] - 8 * '0');
}
2.9遞歸,展開一片區(qū)域
這塊可以說是一個(gè)擴(kuò)展的內(nèi)容了,當(dāng)我們點(diǎn)到一個(gè)周圍沒有地雷的格子,這些區(qū)域就會(huì)自動(dòng)展開。
?這里需要用到函數(shù)遞歸來實(shí)現(xiàn),可以將其看作是一個(gè)深度優(yōu)先搜索
void DfsMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int row, int col)
{
int count= GetMineCount(mine, x, y);
show[x][y] = count + '0';
if (count != 0)
{
return;
}
int xx[] = { 1,1, 1 ,-1,-1,-1,0, 0 };
int yy[] = { 1,0,-1, 0, 1, -1 ,1,-1};
int i = 0;
for (i = 0; i < 8; i++)
{
int dx = x + xx[i];
int dy = y + yy[i];
if (dx >= 1 && dx <= row && dy >= 1 && dy <= col && mine[dx][dy]=='0' && show[dx][dy] == '*')
{
DfsMine(mine, show, dx, dy, ROW, COL);
}
}
}
3.完整代碼展示?
game.h文件
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<Windows.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define ESAY_COUNT 10 //布置雷的個(gè)數(shù)
//初始化棋盤
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);
//統(tǒng)計(jì)雷
int GetMineCount(char mine[ROWS][COLS], int x, int y);
//遞歸,展開一片區(qū)域
void DfsMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int row, int col);
game.c文件
#include"game.h"
//初始化棋盤
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
for (i = 0; i < rows; i++)
{
int j = 0;
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
//打印棋盤
void DisPlayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
printf("--------掃雷--------\n");
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
int j = 0;
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
//布置雷
void SetMine(char board[ROWS][COLS], int row, int col)
{
//布置十個(gè)雷
//隨機(jī)生成坐標(biāo)
int count = ESAY_COUNT;
while(count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x, y;
int win = 0;
while (win < row * col - ESAY_COUNT)
{
system("cls");
DisPlayBoard(show, ROW, COL);
printf("請(qǐng)輸入要排查雷的坐標(biāo):>");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == '1')
{
printf("很遺憾,你被炸死了\n");
break;
}
else
{
//該位置不是雷,就統(tǒng)計(jì)這個(gè)坐標(biāo)周圍有幾個(gè)雷
int count = GetMineCount(mine, x, y);
show[x][y] = count + '0';
if (count == 0)
{
//遞歸,展開一片區(qū)域
DfsMine(mine, show, x, y, ROW, COL);
}
show[x][y] = count + '0';
DisPlayBoard(show, ROW, COL);
win++;
}
}
else
{
printf("坐標(biāo)非法,重新輸入\n");
}
}
if (win == row * col - ESAY_COUNT)
{
printf("恭喜你,排雷成功\n");
}
DisPlayBoard(mine, ROW, COL);
}
//遞歸,展開一片區(qū)域
void DfsMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int row, int col)
{
int count= GetMineCount(mine, x, y);
show[x][y] = count + '0';
if (count != 0)
{
return;
}
int xx[] = { 1,1, 1 ,-1,-1,-1,0, 0 };
int yy[] = { 1,0,-1, 0, 1, -1 ,1,-1};
int i = 0;
for (i = 0; i < 8; i++)
{
int dx = x + xx[i];
int dy = y + yy[i];
if (dx >= 1 && dx <= row && dy >= 1 && dy <= col && mine[dx][dy]=='0' && show[dx][dy] == '*')
{
DfsMine(mine, show, dx, dy, ROW, COL);
}
}
}
//統(tǒng)計(jì)雷
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
return (mine[x - 1][y - 1] + mine[x][y - 1] +
mine[x + 1][y - 1] + mine[x + 1][y] +
mine[x + 1][y + 1] + mine[x][y + 1] +
mine[x - 1][y + 1] + mine[x - 1][y] - 8 * '0');
}
test.c文件
#include"game.h"
void menu()
{
printf("********************\n");
printf("***** 1.play *****\n");
printf("***** 2.exit *****\n");
printf("********************\n");
}
void game()
{
char mine[ROWS][COLS];//存放的雷
char show[ROWS][COLS];//存放盤查出雷的信息
//初始化棋盤
//mine數(shù)組最開始全是‘0’
//show數(shù)組最開始全是‘*’
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
DisPlayBoard(show, ROW, COL);
//布置雷
SetMine(mine, ROW, COL);
//排查雷
FindMine(mine, show, ROW, COL);
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("請(qǐng)選擇:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 2:
system("cls");
printf("退出游戲\n");
break;
default:
printf("選擇錯(cuò)誤,重新選擇\n");
break;
}
} while (input);
}
游戲效果展示:(為了方便截圖,已注釋了清屏的代碼)
?哈哈哈,這次游戲疏忽大意導(dǎo)致游戲失敗了~文章來源:http://www.zghlxwxcb.cn/news/detail-533429.html
總結(jié):今天我們學(xué)習(xí)了掃雷小游戲,再次使用多文件編程的形式,同時(shí)也體驗(yàn)了玩自己所寫的游戲,如果我寫的有什么的不好之處,請(qǐng)?jiān)谖恼孪路浇o出你寶貴的意見。如果覺得我寫的好的話請(qǐng)點(diǎn)個(gè)贊贊和關(guān)注哦~??文章來源地址http://www.zghlxwxcb.cn/news/detail-533429.html
到了這里,關(guān)于【C語言】掃雷小游戲(遞歸展開版)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!