摘要:每成功排一次雷,我們都要展示雷盤當(dāng)場(chǎng)上剩下的格子數(shù)等于雷數(shù)時(shí),游戲勝利,玩家踩雷時(shí),游戲結(jié)束,所以我們這是一個(gè)判斷輸贏的函數(shù)。
前言:寫完三子棋后,慢慢地熟悉了這種寫小游戲的過程,之前對(duì)于代碼的分區(qū)存儲(chǔ)都還是懵懵的,現(xiàn)在終于有點(diǎn)得心應(yīng)手啦,話不多說,這次我寫的是掃雷,但是博主水平有限,目前還不能做到圖形化界面,日后有能力時(shí)定來修改這篇文章,實(shí)現(xiàn)一個(gè)帶有圖形化界面的掃雷!
先來看看掃雷的樣子
與三子棋一樣,我們可以把要排雷的雷盤?(是這個(gè)名字不?)看成一個(gè)二維數(shù)組,當(dāng)我們點(diǎn)擊格子時(shí),格子會(huì)顯示周圍一圈的雷數(shù)。先要有一個(gè)二維數(shù)組來放我們的雷,但我們不可能把這個(gè)數(shù)組展示給玩家看(這樣直接開透視了呀)。我們得再創(chuàng)建一個(gè)二維數(shù)組展示給玩家,這個(gè)數(shù)組開始時(shí)全是’ * ’ ,當(dāng)玩家輸入一個(gè)坐標(biāo)時(shí),’ * ’ 會(huì)變成周圍一圈的雷數(shù)。
經(jīng)過梳理,游戲的邏輯就清晰了:開始時(shí)我們要初始化兩個(gè)數(shù)組,一個(gè)用來放雷(我們叫這個(gè)數(shù)組mine),另一個(gè)用來向玩家展示(我們叫它show)。接著我們會(huì)放置地雷,把show數(shù)組打印給玩家看,玩家輸入坐標(biāo),開始排雷。每成功排一次雷,我們都要展示雷盤當(dāng)場(chǎng)上剩下的格子數(shù)等于雷數(shù)時(shí),游戲勝利,玩家踩雷時(shí),游戲結(jié)束,所以我們這是一個(gè)判斷輸贏的函數(shù)。大概的過程我們就理清楚了。
還是像三子棋一樣,我們把整個(gè)游戲分成三個(gè)部分:
test.c — > 程序的運(yùn)行邏輯
game.c — > 游戲的實(shí)現(xiàn)邏輯
game.c — > 存放游戲相關(guān)函數(shù)的代碼與庫函數(shù)的頭文件
接著是游戲代碼
int main(){ srand((unsigned int)time(NULL));//設(shè)置隨機(jī)數(shù)種子,用來隨機(jī)生成地雷 test(); return 0;}
為了讓代碼看起來整潔,在主函數(shù)中調(diào)用test函數(shù)
test函數(shù)是游戲運(yùn)行的邏輯
void test(){ int input = 0; do { menu();//開始游戲前打印菜單 printf("請(qǐng)選擇 > 1/0/n"); scanf("%d", &input);//input變量存放玩家的選擇 switch (input)//根據(jù)input的值switch進(jìn)入不同的分支 { case 1: game();//游戲邏輯的實(shí)現(xiàn)函數(shù) break; case 0: printf("退出游戲/n"); default : printf("輸入錯(cuò)誤,請(qǐng)重新輸入/n"); break; } } while (input);//玩家可以反復(fù)玩游戲,玩家選0時(shí)退出游戲}
代碼實(shí)現(xiàn)與三子棋的類似,這次寫這部分代碼時(shí)就很熟練了。
游戲菜單(這個(gè)就和三子棋一模一樣了)
void menu(){ printf("***********************/n"); printf("***** 1.開始游戲 ****/n"); printf("***** 0.退出游戲 ****/n"); printf("***********************/n");}
void game(){ //雷棋盤與展示棋盤的初始化 char mine[ROWS][COLS] = { "0" }; char show[ROWS][COLS] = { "0" }; //初始化放雷棋盤 InitBoard(mine, ROWS, COLS,"0"); //初始化展示棋盤 InitBoard(show, ROWS, COLS,"*"); //放置地雷 SetMine(mine, ROW, COL); //打印展示棋盤 DisplayBoard(show, ROW, COL); //玩家排雷 Find(mine, show, ROW, COL);}
game函數(shù)就是我們剛剛梳理的游戲邏輯,接著我們就要一個(gè)個(gè)實(shí)現(xiàn)這些函數(shù)了。
首先呢,與三子棋不一樣的是,我們這次要初始化兩個(gè)棋盤,但是兩個(gè)棋盤的初始化內(nèi)容是不一樣的,這就要求我們的初始化函數(shù)要有相對(duì)的獨(dú)立性來實(shí)現(xiàn)對(duì)不同數(shù)組的初始化。要怎么做呢?我們可以在函數(shù)設(shè)置四個(gè)參數(shù)
我們來看看函數(shù)的實(shí)現(xiàn)
//初始化棋盤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;//將所有元素初始化 } }}
這里解釋為什么定義ROWS,COLS,ROW,COL這四個(gè)宏。
mine數(shù)組中,除了雷是用1表示,其他的元素都是用0表示,計(jì)算雷數(shù)時(shí),把周圍八個(gè)元素的值相加,得到的數(shù)剛好就是雷數(shù)。但是我們對(duì)邊界上的元素進(jìn)行排雷時(shí),會(huì)出先數(shù)組的越界訪問,產(chǎn)生意想不到的結(jié)果,這當(dāng)然不是我們想要的。所以,對(duì)數(shù)組增加兩行與兩列(假設(shè)二維數(shù)組是9 * 9的,增加后變?yōu)?1 * 11),對(duì)11 * 11的數(shù)組初始化,但我們使用的是9 * 9 的數(shù)組,在計(jì)算雷數(shù)時(shí)就不會(huì)出現(xiàn)錯(cuò)誤了。
所以,我們把ROWS與COLS設(shè)置成11,ROW與COL設(shè)值成9。
初始化后,我們就要放地雷了。
//放置地雷//這里有個(gè)小細(xì)節(jié),我們的數(shù)組大小是ROWS * COLS//但放地雷時(shí)只能在ROW * COL大小的數(shù)組中void SetMine(char board[ROWS][COLS], int row, int col){ int x = 0; int y = 0; int count = CON; //CON又是一個(gè)宏,指的是我們要放置的雷數(shù) //CON在頭文件中定義 //用count變量接收CON常量的值,放一次雷count減一 while (count) { //利用隨機(jī)數(shù)產(chǎn)生坐標(biāo) x = rand() % row + 1; y = rand() % col + 1; //坐標(biāo)的值可能相同,所以要判斷坐標(biāo)是否合理 if (board[x][y] == "0") { board[x][y] = "1"; count--;//當(dāng)count為0時(shí),循環(huán)結(jié)束 } }}
由于我們要用到rand函數(shù),所以在主函數(shù)中,我們調(diào)用了srand函數(shù)設(shè)置隨機(jī)數(shù)種子。
展示雷盤的時(shí)候,要是直接把雷盤打印出來,玩家輸入坐標(biāo)時(shí)對(duì)行號(hào)與列號(hào)可能會(huì)不太確定(畢竟數(shù)量有點(diǎn)多嘛),
看得清不?哈哈哈,所以我們要對(duì)行與列加上序號(hào),方便玩家確定坐標(biāo)
//同時(shí)打印行號(hào)與列號(hào)//我們展示的雷盤大小是ROW * COLvoid DisplayBoard(char board[ROWS][COLS], int row, int col){ int i = 0; int j = 0; //列號(hào)的打印 for (i = 0; i <= 9; i++) { printf("%d ", i); } printf("/n"); for (i = 1; i <= row; i++) { //行號(hào)的打印 //在打印行之前先打印行號(hào) printf("%d ", i); for (j = 1; j <= col; j++) { printf("%c ", board[i][j]); } printf("/n"); }}
這樣就好認(rèn)多了
接著就到了玩家進(jìn)行排雷了,通過玩家輸入坐標(biāo),程序把對(duì)應(yīng)的數(shù)組元素賦值成周圍一圈的雷數(shù),要是踩到雷了,提示玩家玩得太菜 游戲結(jié)束。但這又有一個(gè)細(xì)節(jié),我們創(chuàng)建的數(shù)組是字符數(shù)組,放置的是字符,把字符相加得到的是對(duì)應(yīng)的ASCII碼值。所以我們把相加后的值減去八個(gè)字符0的ASCII碼值,得到的就是雷數(shù)了。我寫了一個(gè)num函數(shù)來計(jì)算雷數(shù)。
//num函數(shù)返回類型是整形int num(char board[ROWS][COLS], int x, int y){ //返回八個(gè)周圍元素的相加值,但返回的得是整形,所以減去八個(gè)字符0 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";}
接著是玩家排雷的函數(shù)
void Find(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col){ int x = 0; int y = 0; //設(shè)置變量接收玩家輸入的值 int win = 0; //用win變量判斷玩家是否勝利 //win初始值為0,每排一次雷win加一 while (win < ROW * COL - CON) { printf("請(qǐng)輸入坐標(biāo)/n"); scanf("%d %d", &x, &y); if (x >= 1 && x <= 9 && y >= 1 && y <= 9 && show[x][y] == "*") //判斷玩家輸入的坐標(biāo)在雷盤中并且沒有對(duì)坐標(biāo)進(jìn)行過掃雷 { if (mine[x][y] == "1") { printf("很遺憾,你被炸死了/n"); DisplayBoard(mine, ROW, COL); //玩家被炸死后展示雷盤 break; } else { //計(jì)算雷的數(shù)量 int n = num(mine, x, y); //把展示雷盤對(duì)應(yīng)的元素賦值成周圍雷數(shù) show[x][y] = n + "0"; //但展示雷盤是字符數(shù)組,雷數(shù)要加上字符0 DisplayBoard(show, ROW, COL); //每次排雷展示雷盤 win++; } } else printf("輸入錯(cuò)誤,請(qǐng)重新輸入/n"); } //當(dāng)win等于雷盤大小減去雷數(shù)時(shí),玩家排雷成功,游戲結(jié)束 if (win == ROW * COL - CON) { printf("恭喜你,排雷成功/n"); }}
至此所有的代碼我們就完成了,接著是所有文件代碼的整體展示
#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; } }}//同時(shí)打印行號(hào)與列號(hào)void DisplayBoard(char board[ROWS][COLS], int row, int col){ int i = 0; int j = 0; //列號(hào)的打印 for (i = 0; i <= 9; i++) { printf("%d ", i); } printf("/n"); for (i = 1; i <= row; i++) { //行號(hào)的打印 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){ int x = 0; int y = 0; int count = CON; while (count) { x = rand() % row + 1; y = rand() % col + 1; if (board[x][y] == "0") { board[x][y] = "1"; count--; } }}int num(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 Find(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col){ int x = 0; int y = 0; int win = 0; while (win < ROW * COL - CON) { printf("請(qǐng)輸入坐標(biāo)/n"); scanf("%d %d", &x, &y); if (x >= 1 && x <= 9 && y >= 1 && y <= 9) { if (mine[x][y] == "1") { printf("恭喜你,你被炸死了/n"); DisplayBoard(mine, ROW, COL); break; } else { //計(jì)算雷的數(shù)量 int n = num(mine, x, y); show[x][y] = n + "0"; DisplayBoard(show, ROW, COL); win++; } } else printf("輸入錯(cuò)誤,請(qǐng)重新輸入/n"); } if (win == ROW * COL - CON) { printf("恭喜你,排雷成功/n"); }}
#include #include #include #define ROWS 11#define COLS 11#define ROW 9#define COL 9#define CON 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 Find(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
#include"game.h"void menu(){ printf("***********************/n"); printf("***** 1.開始游戲 ****/n"); printf("***** 0.退出游戲 ****/n"); printf("***********************/n");}void game(){ char mine[ROWS][COLS] = { "0" }; char show[ROWS][COLS] = { "0" }; //初始化放雷棋盤 InitBoard(mine, ROWS, COLS,"0"); //初始化展示棋盤 InitBoard(show, ROWS, COLS,"*"); //放置地雷 SetMine(mine, ROW, COL); //打印展示棋盤 DisplayBoard(show, ROW, COL); //玩家排雷 Find(mine, show, ROW, COL);}void test(){ int input = 0; do { menu(); printf
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/123356.html
摘要:相信大家都玩過掃雷游戲,在學(xué)習(xí)了二維數(shù)組之后,我也用語言寫了一個(gè)簡單的掃雷游戲規(guī)則如下通過對(duì)宏和宏來設(shè)置游戲的棋盤大小如果想玩的掃雷則需設(shè)置和為通過對(duì)宏來設(shè)置局中雷的個(gè)數(shù)雷的個(gè)數(shù)需要對(duì)用戶輸入要掃描的坐標(biāo),如果有雷則雷爆炸游戲結(jié)束,如 相信大家都玩過掃雷游戲,在學(xué)習(xí)了二維數(shù)組之后,我也用c語...
摘要:展示雷盤和初始化雷盤不一樣,展示雷盤只需要用即可,并不需要將都展示出來,只是為了我們更好的計(jì)算掃雷的位置周圍的雷的數(shù)量。 目錄 1、需求分析 2、程序架構(gòu) 3、代碼實(shí)現(xiàn)(分函數(shù)呈現(xiàn)) (1)主函數(shù)代碼實(shí)現(xiàn) 分析: 異常處理: (2)游戲主函數(shù)實(shí)現(xiàn) 分析: (3)初始化函數(shù)的實(shí)現(xiàn) 分析: (4...
摘要:新人小白的第一篇博客,有什么不好之處望多提意見。這個(gè)掃雷小游戲主要是基于二維數(shù)組,循環(huán)與基本的函數(shù)知識(shí)等。請(qǐng)輸入坐標(biāo)提示玩家輸入坐標(biāo)。換行是為了看著好看,要不然打印出來的數(shù)組會(huì)變形的。用來接收判斷輸贏的函數(shù)的返回值。 ???????新人小白的第一篇博客,有什么不好之處望多提意見。 ? ? ?...
摘要:設(shè)計(jì)實(shí)現(xiàn)掃雷游戲大致思路創(chuàng)建文件想法實(shí)現(xiàn)設(shè)計(jì)一個(gè)函數(shù),實(shí)現(xiàn)建議菜單循環(huán)和分支選擇游戲選項(xiàng)創(chuàng)造一個(gè)掃雷版面版面的大小最后是要可控的如何存放雷和版面的信息呢考慮排查雷時(shí)候的思路,我們要判斷該位置周圍個(gè)格子里面是否有雷初始化 ...
閱讀 2014·2021-11-15 11:38
閱讀 2047·2019-08-30 15:55
閱讀 2181·2019-08-30 15:52
閱讀 3166·2019-08-30 14:01
閱讀 2683·2019-08-30 12:47
閱讀 1127·2019-08-29 13:17
閱讀 1061·2019-08-26 13:55
閱讀 2628·2019-08-26 13:46