摘要:如果整個(gè)游戲的數(shù)據(jù)設(shè)計(jì)都基于一個(gè)二維數(shù)組的話(huà)相對(duì)來(lái)說(shuō)容易混淆,比如只有一個(gè)數(shù)組的話(huà),除了要對(duì)區(qū)分雷區(qū)與非雷區(qū)加以處理,還有后續(xù)排雷的信息要處理。
今天要分享給大家的是掃雷的代碼實(shí)現(xiàn),和前幾天寫(xiě)的那個(gè)三子棋差不多,大體思想就是以二維數(shù)組為載體,編寫(xiě)設(shè)計(jì)函數(shù)來(lái)實(shí)現(xiàn)它的各種功能。我們先來(lái)看看最后的成果展示吧(完整代碼在文章末尾處~)
首先從這個(gè)成果圖中可以看出,游戲結(jié)束后可以選擇再來(lái)一次,也可以退出,所以在代碼中我們肯定是將整個(gè)游戲過(guò)程放在一個(gè)循環(huán)里面,我是采用的do-while循環(huán),大致構(gòu)思與前面寫(xiě)的三子棋相同??创a:
void test(){ int input = 0; do { srand((unsigned)time(NULL));//利用時(shí)間戳來(lái)設(shè)置隨機(jī)種子 menu(); printf("請(qǐng)選擇->"); scanf("%d", &input); switch (input) { case 1: printf("掃雷/n"); game(); break; case 0: printf("退出游戲/n"); break; default: printf("輸入不合法,請(qǐng)重新輸入!/n"); } } while (input);}
?在這里補(bǔ)充一下為什么要將input作為while循環(huán)的條件哈,因?yàn)檩斎?時(shí),input的值為1,為真,與之對(duì)應(yīng)的是play,開(kāi)始游戲;輸入0時(shí),為假,對(duì)應(yīng)的是exit,剛好也是跳出循環(huán),輸入其他值時(shí)會(huì)被要求重新輸入,直到輸入0或1。這樣安排一舉兩得哈哈哈。
當(dāng)輸入1后,程序會(huì)進(jìn)入到game()函數(shù),也就是我們游戲的主要設(shè)計(jì)了。
我主要?jiǎng)?chuàng)建了兩個(gè)相同的二維數(shù)組,mine[ROWS][COLS]數(shù)組用來(lái)存放雷的信息;show[ROWS][COLS]數(shù)組用來(lái)展示雷盤(pán),后續(xù)的排雷過(guò)程也是在此二維數(shù)組上來(lái)展示。
如果整個(gè)游戲的數(shù)據(jù)設(shè)計(jì)都基于一個(gè)二維數(shù)組的話(huà)相對(duì)來(lái)說(shuō)容易混淆,比如只有一個(gè)數(shù)組的話(huà),除了要對(duì)區(qū)分雷區(qū)與非雷區(qū)加以處理,還有后續(xù)排雷的信息要處理。倒也不是說(shuō)不能用一個(gè)二維數(shù)組,用2個(gè)二維數(shù)組是為了使思路更清晰。
創(chuàng)建好了之后就調(diào)用以下函數(shù)InitBoard()對(duì)它們進(jì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; } }}
然后我們可以寫(xiě)一個(gè)打印數(shù)組的函數(shù)DisplayBoard(),用來(lái)模擬玩游戲時(shí)出現(xiàn)在界面上的雷盤(pán)。
void DisplayBoard(char board[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 <=col; i++) { printf(" %d ", i); for (j = 1; j <=col; j++) { printf(" %c ", board[i][j]); } printf("/n"); }}
之后我們要開(kāi)始對(duì)mine數(shù)組進(jìn)行埋雷了,因?yàn)閙ine數(shù)組是用來(lái)存放雷的信息的,而show是來(lái)展示的,所以不需要對(duì)show數(shù)組埋雷。雷區(qū)用字符‘1’來(lái)表示,非雷區(qū)用字符‘0’來(lái)表示。這里用的是SetMine()函數(shù),下面是代碼實(shí)現(xiàn):
void SetMine(char board[ROWS][COLS], int row, int col){ int i = 0; int j = 0; int count = COUNT; while(count)//雷的個(gè)數(shù) { i = rand() % row + 1; j = rand() % col + 1; if (board[i][j] == "0") { board[i][j] = "1"; count--; } }}
下面函數(shù)是用來(lái)統(tǒng)計(jì)某個(gè)非雷區(qū)周?chē)袔讉€(gè)雷區(qū)的,用get_mine_count()函數(shù)實(shí)現(xiàn)。很簡(jiǎn)單,我們直接看代碼:
int get_mine_count(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";}
以上基本就是準(zhǔn)備工作,接下來(lái)就是排雷操作了。主要用?FindMine()函數(shù)來(lái)實(shí)現(xiàn)。排雷操作我主要是對(duì)show數(shù)組的數(shù)據(jù)進(jìn)行更改。因?yàn)檎宫F(xiàn)在大家面前的就是show數(shù)組來(lái)模擬的一個(gè)棋盤(pán)。因?yàn)閙ine數(shù)組和show數(shù)組的格式是相同且一一對(duì)應(yīng)的。然后大致思想就是將用戶(hù)要排查的坐標(biāo)在mine數(shù)組進(jìn)行比對(duì),如是否踩到雷或其周?chē)袔讉€(gè)雷等,然后將結(jié)果反映到show數(shù)組對(duì)應(yīng)的坐標(biāo)上。讓我們來(lái)看代碼是怎樣實(shí)現(xiàn)的:
void FindMine(char board1[ROWS][COLS], char board2[ROWS][COLS], int row, int col){ int i = 0; int j = 0; int n = 0; while (n < (ROW * COL - COUNT)) { printf("請(qǐng)輸入要排查的坐標(biāo)->"); scanf("%d %d", &i, &j); if (i >= 1 && i <= 9&& j >= 1 && j <= 9&& board2[i][j]=="*") { if (board1[i][j] == "1") { printf("很遺憾,,你被炸死了/n"); DisplayBoard(board1, ROW, COL); break; } else// { spread(board1, board2, i, j); DisplayBoard(board2, row, col); n++; } } else printf("輸入不合法,請(qǐng)重新輸入!"); } if (n == row * col - COUNT) printf("排雷成功!!!/n");}
這里有個(gè)spread()函數(shù)必須要講一下,這也是游戲設(shè)計(jì)中較難的一點(diǎn)。其作用就是若以輸入坐標(biāo)為中心,若其周?chē)?個(gè)坐標(biāo)都沒(méi)有雷則將這8個(gè)坐標(biāo)全部展開(kāi)。再以展開(kāi)的坐標(biāo)依次為中心,判斷其周?chē)?個(gè)坐標(biāo)是否不存在雷(已展開(kāi)的坐標(biāo)不用再判斷,否則會(huì)形成死遞歸),若不存在則再展開(kāi)它周?chē)?個(gè)坐標(biāo),然后再對(duì)這8個(gè)坐標(biāo)依次進(jìn)行判斷......以此類(lèi)推,直到不能再展開(kāi)為止。我們先來(lái)看一看它的具體代碼:
void spread(char mine[ROWS][COLS],char show[ROWS][COLS], int x, int y){ if (0 == get_mine_count(mine, x, y)) { show[x][y] = " "; int i = 0; int j = 0; for (i = x - 1; i <= x + 1; i++) { for (j = y - 1; j <= y + 1; j++) if (show[i][j] == "*" && i >0 && j > 0 && i <=ROW && j <= COL) spread(mine, show, i, j); } } else { int m = get_mine_count(mine, x, y); show[x][y] = m + "0"; } }
這段代碼是怎樣實(shí)現(xiàn)上述功能的呢?不難看出,這里用到了遞歸思想。我是先對(duì)傳進(jìn)來(lái)的坐標(biāo)進(jìn)行判斷,若此坐標(biāo)對(duì)應(yīng)的mine數(shù)組的坐標(biāo)的周?chē)?個(gè)坐標(biāo)都沒(méi)有雷,則將該坐標(biāo)對(duì)應(yīng)的show數(shù)組的元素置為字符‘ ’,再對(duì)它周?chē)?的坐標(biāo)一一排查,若排查到某一個(gè)坐標(biāo)的周?chē)捕紱](méi)有雷,則再將這某一個(gè)坐標(biāo)置為‘ ’,然后再對(duì)這某一個(gè)坐標(biāo)的周?chē)?個(gè)坐標(biāo)一一進(jìn)行排查.......直到排查的某一個(gè)坐標(biāo)的周?chē)?個(gè)坐標(biāo)的周?chē)贾辽儆幸粋€(gè)雷時(shí)停止,然后將這些不能被置為‘? ’的坐標(biāo)對(duì)應(yīng)的show數(shù)組的元素置為數(shù)字字符,有幾個(gè)雷就顯示數(shù)字字符幾。
最后再補(bǔ)充一下,我是怎樣用數(shù)字字符來(lái)顯示某個(gè)非雷區(qū)的周?chē)袔讉€(gè)雷的。因?yàn)閿?shù)組定義的是字符數(shù)組,所以不能直接用數(shù)字來(lái)表示。那如果某個(gè)非雷區(qū)周?chē)?個(gè)雷的話(huà)我們?cè)趺粗刂迷撟址麛?shù)組元素好讓玩家知道呢?這里就不得不先來(lái)看一下這個(gè)ASCII表:
?數(shù)字3不能用來(lái)表示,但我們可以用字符‘3’來(lái)表示,通過(guò)上圖可以看出若想得到字符‘3’,則只需要在字符‘0’上加上數(shù)字3即可,字符‘0’對(duì)應(yīng)的ASCII碼值為48,加上3就是51,剛好對(duì)應(yīng)字符‘3’。同樣的,若想得到字符‘2’,則只需要用‘0’+2就行了,即用‘0’+數(shù)字就可以得到與數(shù)字相同的字符了。
好了好了,到這里實(shí)現(xiàn)各功能的函數(shù)就大致講完了,覺(jué)得還可以個(gè)小伙伴就給個(gè)贊吧,三連當(dāng)然是最好啦。最后在這里附上全部代碼。test.c里面是游戲?qū)崿F(xiàn)邏輯,game.c里面是游戲各函數(shù)實(shí)現(xiàn)邏輯,game.h里面是頭文件的包含,各函數(shù)、符號(hào)的聲明。至于為什么這么設(shè)計(jì)歡迎看我前幾天寫(xiě)的三子棋哈,里面有講解。
game.h
#pragma once//頭文件的包含#include#include#include//符號(hào)的的聲明#define ROW 9#define COL 9#define COLS COL+2#define ROWS ROW+2#define COUNT 10//函數(shù)的聲明void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);//初始化棋盤(pán)void DisplayBoard(char bodrd[ROWS][COLS], int row, int col);//打印棋盤(pán)void SetMine(char[ROWS][COLS], int row, int col);//布置雷void FindMine(char board1[ROWS][COLS], char board2[ROWS][COLS], int row, int col);//排查雷
game.c
//游戲各函數(shù)實(shí)現(xiàn)邏輯#define _CRT_SECURE_NO_WARNINGS #include "game.h"#define _CRT_SECURE_NO_WARNINGS //初始化棋盤(pá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; } }}//打印棋盤(pán)void DisplayBoard(char board[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 <=col; i++) { 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 i = 0; int j = 0; int count = COUNT; while(count)//雷的個(gè)數(shù) { i = rand() % row + 1; j = rand() % col + 1; if (board[i][j] == "0") { board[i][j] = "1"; count--; } }}int get_mine_count(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";}/*若以輸入坐標(biāo)為中心,其周?chē)?個(gè)坐標(biāo)都沒(méi)有雷則全部展開(kāi)。再以展開(kāi)的坐標(biāo)依次為中心,判斷其周?chē)?個(gè)是否存在雷(已展開(kāi)的坐標(biāo)不用再判斷,否則會(huì)形成死遞歸)以此類(lèi)推,直到不能再展開(kāi)為止。*/void spread(char mine[ROWS][COLS],char show[ROWS][COLS], int x, int y){ if (0 == get_mine_count(mine, x, y)) { show[x][y] = " "; int i = 0; int j = 0; for (i = x - 1; i <= x + 1; i++) { for (j = y - 1; j <= y + 1; j++) if (show[i][j] == "*" && i >0 && j > 0 && i <=ROW && j <= COL) spread(mine, show, i, j); } } else { int m = get_mine_count(mine, x, y); show[x][y] = m + "0"; } }void FindMine(char board1[ROWS][COLS], char board2[ROWS][COLS], int row, int col){ int i = 0; int j = 0; int n = 0; while (n < (ROW * COL - COUNT)) { printf("請(qǐng)輸入要排查的坐標(biāo)->"); scanf("%d %d", &i, &j); if (i >= 1 && i <= 9&& j >= 1 && j <= 9&& board2[i][j]=="*") { if (board1[i][j] == "1") { printf("很遺憾,,你被炸死了/n"); DisplayBoard(board1, ROW, COL); break; } else//統(tǒng)計(jì)雷的個(gè)數(shù) { spread(board1, board2, i, j); DisplayBoard(board2, row, col); n++; } } else printf("輸入不合法,請(qǐng)重新輸入!"); } if (n == row * col - COUNT) printf("排雷成功!!!/n");}
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(){ char mine[ROWS][COLS] = { 0 };//布置雷的棋盤(pán) char show[ROWS][COLS] = { 0 };//排查雷的棋盤(pán),也就是用戶(hù)端看到的棋盤(pán) InitBoard(mine, ROWS, COLS, "0");//初始化mine數(shù)組全為"0" InitBoard(show, ROWS, COLS, "*");//c初始化show數(shù)組全為’*‘ SetMine(mine, ROW, COL);//布置雷 //DisplayBoard(mine, ROW, COL); DisplayBoard(show, ROW, COL);//打印雷的棋盤(pán) FindMine(mine,show,ROW,COL);//排雷}void test(){ int input = 0; do { srand((unsigned)time(NULL));//利用時(shí)間戳來(lái)設(shè)置隨機(jī)種子 menu(); printf("請(qǐng)選擇->"); scanf("%d", &input); switch (input) { case 1: printf("掃雷/n"); game(); break; case 0: printf("退出游戲/n"); break; default: printf("輸入不合法,請(qǐng)重新輸入!/n"); } } while (input);}int main(){ test(); return 0;}
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/123505.html
摘要:函數(shù)游戲菜單請(qǐng)選擇掃雷游戲退出游戲選擇錯(cuò)誤解析函數(shù)內(nèi)部利用時(shí)間戳,形成隨機(jī)數(shù),主要目的是實(shí)現(xiàn)游戲中地雷的隨機(jī)埋放。 前言 本篇文章使用C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單小游戲---掃雷。(文章最后有完整代碼鏈接) 想必大多數(shù)人都玩過(guò)或者了解過(guò)掃雷的游戲規(guī)則,但是在這里,我們?cè)谝黄鹬販匾幌聮呃椎挠螒蛞?guī)則,也更好...
摘要:目錄前言前言前期的準(zhǔn)備前期的準(zhǔn)備游戲代碼的具體實(shí)現(xiàn)游戲代碼的具體實(shí)現(xiàn)完整版的掃雷小游戲代碼完整版的掃雷小游戲代碼總結(jié)總結(jié)前言?huà)呃资且豢畲蟊婎?lèi)的益智小游戲,于年發(fā)行。 目錄 前言 前期的準(zhǔn)備 游戲代碼的具體實(shí)現(xiàn) 1、text.c 2、game.h 3、game.c 完整版的掃雷小游戲代碼: 1...
摘要:展示雷盤(pán)和初始化雷盤(pán)不一樣,展示雷盤(pán)只需要用即可,并不需要將都展示出來(lái),只是為了我們更好的計(jì)算掃雷的位置周?chē)睦椎臄?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...
摘要:玩家選擇開(kāi)始游戲后,出現(xiàn)雷盤(pán),并且隨機(jī)布置雷。雷盤(pán)的數(shù)組大小為,方便計(jì)算掃雷時(shí)周?chē)椎臄?shù)量,并防止數(shù)組越界。放置布置的雷的信息放置排查出雷的信息初始化雷盤(pán)初始化展示界面打印展示界面效果如下布置雷隨機(jī)在數(shù)組中讓十個(gè)變成作為雷。 目錄 前言 一、游戲思路 二、游戲框架 1.菜單界面 1.菜單:...
摘要:寫(xiě)在前面我們已經(jīng)寫(xiě)過(guò)了三子棋小游戲肯定沒(méi)玩過(guò)癮,我們?cè)賹?xiě)個(gè)掃雷小游戲吧目錄寫(xiě)在前面認(rèn)識(shí)游戲游戲規(guī)則游戲框架游戲?qū)崿F(xiàn)效果展示全部代碼文件文件文件認(rèn)識(shí)游戲相信大家對(duì)掃雷都不陌生每臺(tái)電腦必備的小游戲游戲規(guī)則就是在規(guī)定的時(shí)間將 ...
閱讀 2190·2021-11-16 11:45
閱讀 1346·2021-10-22 09:53
閱讀 4089·2021-09-07 10:26
閱讀 1282·2021-09-06 15:00
閱讀 2134·2019-08-28 18:09
閱讀 2882·2019-08-26 14:06
閱讀 4115·2019-08-26 13:48
閱讀 1361·2019-08-26 12:11