C語言代碼實現(xiàn)簡單掃雷小游戲
用C語言寫一個簡單的掃雷,供大家參考,具體內(nèi)容如下
1.所需要的知識
c語言的基本語法,簡單的二維數(shù)組,一點簡單的遞歸知識。
2.總體思路
掃雷游戲主要由3個部分組成,埋雷子,掃雷,判斷輸贏。
掃雷游戲的主體是兩個個字符類型的二維數(shù)組。一個是mine[][]它的構(gòu)成是'0'和‘1',其中'0'表示無雷,'1'表示有雷。一個是show[][]它的構(gòu)成是'*'和'數(shù)字'。星號表示未開啟的地方,數(shù)字表示周圍的雷數(shù)。這里要注意的是:mine和show的實際大小是11x11,但是展示的效果是 9x9。這樣做的優(yōu)點將在Find()中體現(xiàn)。藍(lán)色部分是可見的9x9,實際的類似紅色 11x11。

下面是我用到的一些函數(shù)。
//game.h #pragma once #ifndef __GAME_H__ #define __GAME_H__ #include<stdio.h> #include<stdlib.h> #include<process.h> #include<string.h> #include<time.h> #define ROW 9 // 9行 #define COL 9 // 9列 #define ROWS ROW+2 //實際行 #define COLS COL+2 //實際列 #define MineNum 10 //雷子數(shù)量 //菜單信息 void menu(); //執(zhí)行菜單 void test(char mine[ROWS][COLS], int row1, int col1, char show[ROWS][COLS], int row2, int col2); //游戲主體 void game(char mine[ROWS][COLS], int row1, int col1, char show[ROWS][COLS], int row2, int col2); //打印雷陣 void InitBoard(char arr[ROWS][COLS], int row, int col); //埋雷子 void SetMine(char mine[ROWS][COLS], int row, int col); //找雷子 int FindMine(char mine[ROWS][COLS], int row1, int col1, char show[ROWS][COLS], int row2, int col2); //空白算法 void Find(char mine[ROWS][COLS], int row1, int col1, char show[ROWS][COLS], int row2, int col2,int x, int y,int exam[ROWS][COLS]); #endif//__GAME_H__
下面是主函數(shù)內(nèi)容
#include"game.h"
int main()
{
char mine[ROWS][COLS];
char show[ROWS][COLS];
srand ((unsigned int)time(NULL)); //生成隨機數(shù),用于隨機埋雷
int i = 0, j = 0;
test(mine, ROWS, COLS, show, ROWS, COLS); //測試函數(shù)
system("pause");
return 0;
}
3.詳細(xì)實現(xiàn)
菜單函數(shù)
void menu()
{
printf("******************\n");
printf("******1.play *****\n");
printf("******0.exit *****\n");
printf("******************\n");
}
這個函數(shù)是用來打印信息的,打印一個簡單的菜單。
執(zhí)行菜單
void test(char mine[ROWS][COLS], int row1, int col1,char show[ROWS][COLS],int row2,int col2)
{
int m = 0;
do
{
menu();
scanf_s("%d", &m);
switch (m)
{
case 1:
game(mine, row1, col1, show, row2, col2);
break;
case 0:
exit(0);
default:
printf("輸入錯誤!\n");
}
} while (m);
}
這個函數(shù)是用來執(zhí)行用戶選項的。1.進(jìn)行游戲 0.退出游戲。
游戲主體函數(shù)
void game(char mine[ROWS][COLS], int row1, int col1, char show[ROWS][COLS], int row2, int col2)
{
int i = 0, j = 0;
int flag = 0;
int count = 0;
for (i = 0; i < row1; i++)
{
for (j = 0; j < col1; j++)
{
mine[i][j] = '0';
}
}
for (i = 0; i < row2; i++)
{
for (j = 0; j < col2; j++)
{
show[i][j] = '*';
}
}
SetMine(mine, row1, col1);
while (1)
{
InitBoard(mine, row1 - 1, col1 - 1);
printf("------------------------\n");
InitBoard(show, row2 - 1, col2 - 1);
flag = FindMine(mine, row1, col1, show, row2, col2);
if (flag == 0)
{
printf("恭喜你,你被炸死了!\n");
InitBoard(mine, row1 - 1, col1 - 1);
break;
}
else if (flag == 1 )
{
for (i = 1; i < row2 - 1; i++)
{
for (j = 1; j < col2 - 1; j++)
{
if (show[i][j] == '*')
{
count++;
}
}
}
printf("count == %d\n", count);
if (count == MineNum)
{
printf("很遺憾,游戲結(jié)束\n");
break;
}
else
{
count = 0;
}
}
}
}
這個函數(shù)是游戲的主體部分。在一開始定義了一個標(biāo)志變量flag和一個計數(shù)變量count。之后,使用了兩個兩個for循環(huán)對二維數(shù)組進(jìn)行了初始化,mine被初始化為全'0',show被初始化了全'*'。然后,使用了SetMine()函數(shù)對mine進(jìn)行了埋雷活動。最后使用個一個while死循環(huán),開始進(jìn)行掃雷游戲。
在while循環(huán)里首先是兩個InitBoard()函數(shù)對mine和show進(jìn)行打印。
FindMine函數(shù)是掃雷函數(shù)。它會返回一個值,如果被雷炸死了,他會返回0,如果點開區(qū)域沒有觸發(fā)雷的話,它會返回1。
接下來如果flag==1時,開始進(jìn)行掃描,看看show中還剩下幾個星號,如果剩下10個星號,那么就證明掃完了,此時打印獲勝信息,并break跳出循環(huán)。如果沒有剩下10個星號,那么將已有的count信息清除,繼續(xù)進(jìn)行以上步驟。
打印面板函數(shù)
void InitBoard(char arr[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i < row; i++)
{
printf("%d ", i);
for (j = 1; j < col; j++)
{
printf("%c ", arr[i][j]);
}
printf("\n");
}
}
這是一個簡單的打印函數(shù),show和mine都可以公共使用。第一個for循環(huán)打印的是列坐標(biāo)。第二個for循環(huán)中,第一個printf函數(shù)打印的是行坐標(biāo)。
埋雷函數(shù)
void SetMine(char mine[ROWS][COLS], int row, int col)
{
int m = 0, n = 0;
int count = 0;
while (count < MineNum)
{
m = rand() % 9 + 1;
n = rand() % 9 + 1;
if (mine[m][n] == '0')
{
mine[m][n] = '1';
count++;
}
}
}
這是一個埋雷函數(shù)。埋雷需要用到隨機數(shù),我使用m和n來存放隨機數(shù)。while循環(huán)的終止條件是埋雷數(shù) count 達(dá)到預(yù)設(shè)雷數(shù) MineNum 。rand()%9+1是為了產(chǎn)生1~9的隨機數(shù)。if語句保證設(shè)雷地區(qū)不重復(fù)。
掃雷函數(shù)
int FindMine(char mine[ROWS][COLS], int row1, int col1, char show[ROWS][COLS], int row2, int col2)
{
int m = 0, n = 0;
int flag = 0;
static int fflag = 0;
int a1 = 0, a2 = 0;
int exam[ROWS][COLS] = { 0 };
while (1)
{
scanf_s("%d %d", &m, &n);
if ((m >= 1 && m <= 9) && (n >= 1 && n <= 9))
{
break;
}
else
{
printf("輸錯了吧?\n");
}
}
if (mine[m][n] == '0')
{
Find(mine, row1, col1, show, row2, col2, m, n, exam);
flag = 1;
}
if (mine[m][n] == '1' && fflag > 0)
{
flag = 0;
}
if (mine[m][n] == '1' && fflag == 0)
{
mine[m][n] = '0';
a1 = m;
a2 = n;
while (1)
{
m = rand() % 9 + 1;
n = rand() % 9 + 1;
if (mine[m][n] == '0'&& m != a1 && n != a2)
{
mine[m][n] = '1';
flag = 1;
break;
}
}
fflag = 1;
}
return flag;
}
這是一個掃雷函數(shù)。m和n是用來保存位置,flag 是標(biāo)志變量,fflag也是踩雷標(biāo)志變量。a1和a2是暫存m和n的位置的。exam是一個標(biāo)志數(shù)組,它將在Find函數(shù)發(fā)揮作用。
第一個while死循環(huán)它的作用是確保輸入正確的坐標(biāo)信息。在確保輸入的m和n的數(shù)據(jù)是正確的后。開始處理數(shù)據(jù),第一個if語句,如果第一下沒有踩雷,那么將執(zhí)行Find空白的算法,結(jié)果是產(chǎn)生周圍雷數(shù)。第二個if語句中,如果不是第一下踩雷,那么將會反饋爆炸信息flag == 0。第三個if語句中,如果第一下踩雷了,那么將這顆雷移動到別的地方去。
移動的方法是將踩雷地點先用a1和a2記錄下來,然后生成隨機數(shù),該隨機數(shù)必須在 無雷 并且 不同于 m和n的坐標(biāo)的地方。
空白算法函數(shù)
void Find(char mine[ROWS][COLS], int row1, int col1, char show[ROWS][COLS], int row2, int col2, int x, int y,int exam[ROWS][COLS])
{
int count = 0;
if (x <= 0 || y <= 0 || x >= row1-1||y >= col1-1)
{
return;
}
count = mine[x - 1][y - 1] + mine[x - 1][y] + mine[x - 1][y + 1] + mine[x][y - 1] + mine[x][y + 1] + mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] - 8 * '0';
show[x][y] = '0' + count;
if (show[x][y] == '0' && exam[x][y] == 0)
{
if (show[x][y] == '0')
{
exam[x][y] = 1;
}
Find(mine, row1, col1, show, row2, col2, x - 1, y - 1,exam);
Find(mine, row1, col1, show, row2, col2, x - 1, y, exam);
Find(mine, row1, col1, show, row2, col2, x - 1, y + 1, exam);
Find(mine, row1, col1, show, row2, col2, x , y - 1, exam);
Find(mine, row1, col1, show, row2, col2, x , y + 1, exam);
Find(mine, row1, col1, show, row2, col2, x + 1, y - 1, exam);
Find(mine, row1, col1, show, row2, col2, x + 1, y, exam);
Find(mine, row1, col1, show, row2, col2, x + 1, y + 1, exam);
}
else
{
return;
}
}
這個函數(shù)是用來實現(xiàn)空白算法的。具體效果類似下圖。

從圖中可以發(fā)現(xiàn),點開一個空白產(chǎn)生了連鎖效果。
在Find函數(shù)中第一個if判斷條件,是看看有沒有觸底或者觸頂,如果有,那么將返回到上個函數(shù)中去。
接下來count是為了計算該點周圍的雷數(shù)量。如下圖:

當(dāng)計算好后,將計算的數(shù)據(jù)填入到show中。由于'0'+數(shù)字 = ‘?dāng)?shù)字',相當(dāng)于把整形的count轉(zhuǎn)成了char填入到 show。
然后使用遞歸算法。

假設(shè)我們首先點開了棕色區(qū)域中心點,那么接下來 從x-1,y-1以順時針方向開始探索。此時我們進(jìn)入到第一個if中,檢查條件,exam該點默認(rèn)為0,表示我們沒有操作過它。
接下來將該點exam相對應(yīng)的地方改成1。然后進(jìn)入第一個Find()探索,也就是x - 1, y - 1。由于該點是‘ 1 ',所以return,返回到上層。此時按次序執(zhí)行第二個Find(),也就是 x - 1, y。由于該點是‘ 0 ',所以以這個點為中心,進(jìn)行探索(以紅色為標(biāo)記的九宮格)。探索前將這個點的標(biāo)記位改為‘ 1 ',表示我們已經(jīng)進(jìn)行了該點的探索。以該點 為 x,y,它的x-1, y-1是' 0 ‘,所以以黃色九宮格探索。以此類推直到觸頂、觸底停止,或者是周圍有不為 ‘ 0 '的數(shù)字停止。
這里為了防止兩個九宮格相互循環(huán),所以添加了exam標(biāo)志位。當(dāng)子九宮格再次探索到上個函數(shù)‘ 0 '時,發(fā)現(xiàn)其對應(yīng)的exam標(biāo)志為1,不跳越至上個函數(shù)‘ 0 '繼續(xù)進(jìn)行探索或返回。
4.程序運行效果
開局踩一顆雷,沒事;再踩一顆雷死了。

點開一大片空白。

游戲初始化面

游戲勝利!

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C++標(biāo)準(zhǔn)庫實現(xiàn)WAV文件讀寫的操作
本文將使用標(biāo)準(zhǔn)C++庫實現(xiàn)對數(shù)據(jù)為PCM格式的WAV文件的讀寫操作,只使用標(biāo)準(zhǔn)C++庫函數(shù),不依賴于其他的庫,對C++標(biāo)準(zhǔn)庫實現(xiàn)WAV文件讀寫相關(guān)知識感興趣的朋友一起看看吧2022-01-01
Qt MQTT開發(fā)環(huán)境搭建的實現(xiàn)示例
本文主要介紹了Qt MQTT開發(fā)環(huán)境搭建的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06

