今天再來給大家分享用C語言知識來實作一個簡單的掃雷游戲程序,
掃雷這個游戲的原理想必大家都是比較清楚的了,這里再來向大家簡單的介紹一下,
下面是一個9*9的掃雷棋盤

我們首先隨機的在棋盤上點擊一個位置,如果該位置被布置了雷,那么很遺憾你直接被炸死了,如果沒有雷,那么他會在該位置顯示出他周圍八個位置雷的個數,如果該位置有一個雷,就顯示數字1,有兩個雷就顯示數字2,依次類推,玩家根據提示把全部的安全位置都找到后,就會獲得游戲的勝利,這就是掃雷游戲的簡單規則,
接下來介紹C語言的實作程序,
在上一篇中我們剛剛介紹過了三子棋游戲的實作,我們就可以借鑒三子棋的游戲框架,只需改變游戲模塊的內容即可,所以我們創建一個test.c檔案來寫主函式部分,再創建一個game.c檔案來實作游戲部分內容,在創建一個game.h檔案來宣告函式,
首先我們還是先簡單來看一下主函式部分,用do while回圈來實作,
代碼如下:
int main()
{
int input = 0;
do
{
menu();
printf("請選擇:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();//掃雷游戲
break;
case 0:
printf("退出游戲\n");
break;
default:
printf("選擇錯誤!\n");
break;
}
} while (input);
return 0;
}
先給一個選單,選擇1進入游戲,選擇0退出游戲,選擇其他值則重新輸入,
接下來來看選單部分,很簡單,只需要一個函式來實作簡單的列印功能即可,
代碼如下:
void menu()
{
printf("**********************\n");
printf("**** 1. play ***\n");
printf("**** 0. exit ***\n");
printf("**********************\n");
}
寫完這個函式我們就可以將選單列印到螢屏上了,
好了,接下來我們來實作這個游戲最重要的部分,游戲函式部分,
這次我們就需要我們站在游戲設計的角度來看待這個游戲,怎樣才完成一個掃雷游戲呢,簡單的來概括有以下兩步:①設定雷, ②排雷,
首先作為設計者,我們應該給玩家在一組棋盤上提前埋好雷,很顯然在C語言中我們可以用一個特定的字符來表示雷,而安全的地方我們就可以用另一個字符來表示,寫到這里接下來的步驟顯然已經很明顯了,我們需要創建一個二維陣列來存放雷的位置和安全區域的位置,今天我們這里就來設計一個9*9的掃雷吧,所以我們需要設計一個9*9的二維陣列,
創建好了這個二維陣列,也就是我們的棋盤,接下來要做的就是初始化棋盤,寫到這里我想提問大家一下,如果我們這創建一個二維陣列夠嗎?顯然是不夠的,因為我們創建的這個二維陣列是來存放雷的,難道我們給玩家的棋盤能夠是我們存放雷的這個棋盤嗎?這樣的話我們雷的位置不就全部暴露出來了嗎?所以我們需要創建兩個二維陣列,一個是我們用來存放雷的陣列,一個是用來展示給玩家的陣列,而我們倒時候只需要把雷的位置傳給展示給玩家的陣列即可,
初始化之前我想先請大家簡單的思考一下游戲程序,我們排雷的時候需要排查這個元素周圍八個元素的位置里有沒有雷,而如果這個元素在中間的話,我們可以成功的找到他周圍的八個元素,那么如果這個元素在這個陣列的邊緣處,那么我們在排查的時候沒有八個位置排查的話就會出錯,所以我們實際上需要創建一個11*11的二維陣列來保證我們9*9陣列的每一個元素周圍都是有元素的,這樣才不會出錯,
同樣的我們可以參考三子棋時候的寫法,我們創建兩個全域變數來存放我們需要展示的陣列行和列,在創建兩個全域變數給前面的全域變數加2來存放實際創建陣列的行和列,這樣就不會把代碼寫死,
我們給埋雷的陣列全部初始化為’0’,展示的陣列全部初始化為’*’.
代碼如下:
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("----------------------------------\n");
//列號的列印
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
//每一行最前面的行號
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("----------------------------------\n");
}
這里我們需要注意,我們創建陣列的時候創建的是11*11的陣列,是避免邊緣元素排查出錯,而展示給玩家的時候,我們需要展示9*9的棋盤給玩家看,所以展示陣列的時候我們接收的應該是展示的行和列9.我們還看到列印函式的代碼中我們還對棋盤進行了修飾,上下列印了分割線,還在周圍列印了行和列的號,
棋盤初始化完之后,我們就需要給埋雷的棋盤上埋雷了,
埋雷的時候我們先要確定埋雷的數量,這里我們也可以定義一個全域變數來確定我們埋雷的個數,我們知道掃雷游戲也是有難度的,這樣我們就可以根據我們埋雷的數量來劃分游戲的難度,使游戲更加靈活多變,接下來我們需要隨機生成一個位置去放置雷,生成的隨機值我們還是用rand函式來實作,以時間戳作為srand函式的起點,這樣我們就可以得到這個隨機值了,我們還要注意,這個隨機值的坐標在我們初始化的11*11棋盤中的范圍應該是1-9.
代碼如下:
void SetMine(char board[ROWS][COLS], int row, int col)
{
//1. 隨機找坐標布置雷
//布置多少個雷 - 10
int count = EASY_COUNT;
while (count)
{
//布置成功一個雷,count--
//1. 生產隨機的坐標
int x = rand() % row + 1;//1-9
int y = rand() % col + 1;//1-9
//2. 布置
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
我們看到用一個簡單的while就可以實作埋雷的程序,這里我們用字符’1’,代表雷,
寫到這里可以看一下我們棋盤的效果了,我們可以將埋雷棋盤和展示棋盤用列印函式列印出來看一下,
如下圖:

上面是我們展示的棋盤,下面是我們埋雷的棋盤,
雷埋好之后就剩下最后一個掃雷的步驟了,接下來我們就來實作掃雷的代碼,
掃雷的程序是這樣的,首先玩家要輸入一個坐標,
接下來第一步我們要先判斷他輸入的這個坐標是不是雷,如果他直接輸入一個雷的坐標,那么我們就需要需要提示他被炸死了,需要重新開始一把游戲,
如果他輸入的坐標不是雷,那么我們接下來就要統計這個坐標周圍的雷的個數,這個步驟我們放在一個函式中進行,接下來我們來介紹這個函式的功能,
統計一個坐標周圍雷的個數,一般思維就是挨個檢查,這樣當然是可以的,但是有點麻煩,這里向大家介紹一種非常巧妙的方法,我們知道,我們設定為安全的位置是字符’0’,有雷的位置是’1’, **我們只需把他周圍的八個元素加起來不就得到雷的個數了嗎?**但是我們需要注意,這里的’1’和’0’是字符,不是數字,他們對應的ASCII碼值分別是48和49,所以我們計算的時候應該用加起來的數再減去字符’0’,然后把這個結果作為回傳值回傳過去,這樣我們就可以輕松得到周圍雷的個數了,
代碼如下:
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
return mine[x - 1][y] +
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] - 8 * '0';
}
我們就可以通過以上代碼實作當輸入坐標不是雷的時候用來標記該坐標周圍雷的個數,
那么標記之后,我們是不是還得判斷游戲是否勝利了啊,這里我們可以檢測玩家排除安全區域的個數,棋盤上棋子的總個數我們是知道的,就是9*9=81,雷的個數也是已知的,所以我們用總數目減去雷的位置數目就是安全區域的數目,接下來我們可以檢測排除的安全區域個數是否檢測完畢,如果檢查完畢,則判斷玩家游戲勝利,
代碼如下:
void FindMine(char mine[ROWS][COLS],
char show[ROWS][COLS],
int row,
int col)
{
int x = 0;
int y = 0;
int win = 0;
while (win");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
//判斷x,y坐標處是否是雷
if (mine[x][y] == '1')
{
printf("很遺憾,你被炸死了\n");
DisplayBoard(mine, row, col);
break;
}
else
{
//如果x,y坐標不是雷,就統計周圍有幾個雷
int count = GetMineCount(mine, x, y);
show[x][y] = count + '0';
DisplayBoard(show, ROW, COL);
win++;
}
}
else
{
printf("坐標非法\n");
}
}
if (win == ROW*COL - EASY_COUNT)
{
printf("恭喜你,排雷成功\n");
DisplayBoard(mine, row, col);
}
}
以上就是實作掃雷游戲的全部步驟,當然這里我們只是設計了一個簡易的掃雷游戲,還有許多地方可以繼續優化的,如果大家有興趣,下去之后還可以自己再完善一下這段代碼,希望我的這篇文章能給大家帶來幫助,
最后將這個游戲的完整代碼留給大家,
test.c
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
void menu()
{
printf("**********************\n");
printf("**** 1. play ***\n");
printf("**** 0. exit ***\n");
printf("**********************\n");
}
void game()
{
//真正掃雷的程序
//創建2個陣列
//存放布置好的雷
char mine[ROWS][COLS] = { 0 };//'0'
//存放排查出來的雷的資訊
char show[ROWS][COLS] = { 0 };//'*'
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
DisplayBoard(show, ROW, COL);
//布置好的雷的資訊不應該輕易列印
//DisplayBoard(mine, ROW, COL);
//1. 布置雷
SetMine(mine, ROW, COL);
//2. 掃雷
FindMine(mine, show, ROW, COL);
}
int main()
{
int input = 0;
//time_t -- 整形
srand((unsigned int)time(NULL));//設定亂數的生成起點的
do
{
menu();
printf("請選擇:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();//掃雷游戲
break;
case 0:
printf("退出游戲\n");
break;
default:
printf("選擇錯誤!\n");
break;
}
} while (input);
return 0;
}
game.c
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
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("----------------------------------\n");
//列號的列印
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
//每一行最前面的行號
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("----------------------------------\n");
}
void SetMine(char board[ROWS][COLS], int row, int col)
{
//1. 隨機找坐標布置雷
//布置多少個雷 - 10
int count = EASY_COUNT;
while (count)
{
//布置成功一個雷,count--
//1. 生產隨機的坐標
int x = rand() % row + 1;//1-9
int y = rand() % col + 1;//1-9
//2. 布置
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
return mine[x - 1][y] +
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] - 8 * '0';
}
//
//掃雷游戲是怎么結束的?
//1. 炸死了
//2. 正常排查了所有不是雷的位置
//
void FindMine(char mine[ROWS][COLS],
char show[ROWS][COLS],
int row,
int col)
{
int x = 0;
int y = 0;
int win = 0;
while (win");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
//判斷x,y坐標處是否是雷
if (mine[x][y] == '1')
{
printf("很遺憾,你被炸死了\n");
DisplayBoard(mine, row, col);
break;
}
else
{
//如果x,y坐標不是雷,就統計周圍有幾個雷
int count = GetMineCount(mine, x, y);
show[x][y] = count + '0';
DisplayBoard(show, ROW, COL);
win++;
}
}
else
{
printf("坐標非法\n");
}
}
if (win == ROW*COL - EASY_COUNT)
{
printf("恭喜你,排雷成功\n");
DisplayBoard(mine, row, col);
}
}
game.h
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define EASY_COUNT 10
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
//初始化
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 mine[ROWS][COLS], int row, int col);
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
//一定的編程邏輯+
//陣列-二維陣列
//函式 - 組合在一起 - 功能
//回圈-變數
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/171628.html
標籤:其他
上一篇:007:回傳什么才好呢
