摘要:如果整個游戲的數據設計都基于一個二維數組的話相對來說容易混淆,比如只有一個數組的話,除了要對區分雷區與非雷區加以處理,還有后續排雷的信息要處理。
今天要分享給大家的是掃雷的代碼實現,和前幾天寫的那個三子棋差不多,大體思想就是以二維數組為載體,編寫設計函數來實現它的各種功能。我們先來看看最后的成果展示吧(完整代碼在文章末尾處~)
首先從這個成果圖中可以看出,游戲結束后可以選擇再來一次,也可以退出,所以在代碼中我們肯定是將整個游戲過程放在一個循環里面,我是采用的do-while循環,大致構思與前面寫的三子棋相同。看代碼:
void test(){ int input = 0; do { srand((unsigned)time(NULL));//利用時間戳來設置隨機種子 menu(); printf("請選擇->"); scanf("%d", &input); switch (input) { case 1: printf("掃雷/n"); game(); break; case 0: printf("退出游戲/n"); break; default: printf("輸入不合法,請重新輸入!/n"); } } while (input);}
?在這里補充一下為什么要將input作為while循環的條件哈,因為輸入1時,input的值為1,為真,與之對應的是play,開始游戲;輸入0時,為假,對應的是exit,剛好也是跳出循環,輸入其他值時會被要求重新輸入,直到輸入0或1。這樣安排一舉兩得哈哈哈。
當輸入1后,程序會進入到game()函數,也就是我們游戲的主要設計了。
我主要創建了兩個相同的二維數組,mine[ROWS][COLS]數組用來存放雷的信息;show[ROWS][COLS]數組用來展示雷盤,后續的排雷過程也是在此二維數組上來展示。
如果整個游戲的數據設計都基于一個二維數組的話相對來說容易混淆,比如只有一個數組的話,除了要對區分雷區與非雷區加以處理,還有后續排雷的信息要處理。倒也不是說不能用一個二維數組,用2個二維數組是為了使思路更清晰。
創建好了之后就調用以下函數InitBoard()對它們進行初始化
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; } }}
然后我們可以寫一個打印數組的函數DisplayBoard(),用來模擬玩游戲時出現在界面上的雷盤。
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"); }}
之后我們要開始對mine數組進行埋雷了,因為mine數組是用來存放雷的信息的,而show是來展示的,所以不需要對show數組埋雷。雷區用字符‘1’來表示,非雷區用字符‘0’來表示。這里用的是SetMine()函數,下面是代碼實現:
void SetMine(char board[ROWS][COLS], int row, int col){ int i = 0; int j = 0; int count = COUNT; while(count)//雷的個數 { i = rand() % row + 1; j = rand() % col + 1; if (board[i][j] == "0") { board[i][j] = "1"; count--; } }}
下面函數是用來統計某個非雷區周圍有幾個雷區的,用get_mine_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";}
以上基本就是準備工作,接下來就是排雷操作了。主要用?FindMine()函數來實現。排雷操作我主要是對show數組的數據進行更改。因為展現在大家面前的就是show數組來模擬的一個棋盤。因為mine數組和show數組的格式是相同且一一對應的。然后大致思想就是將用戶要排查的坐標在mine數組進行比對,如是否踩到雷或其周圍有幾個雷等,然后將結果反映到show數組對應的坐標上。讓我們來看代碼是怎樣實現的:
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("請輸入要排查的坐標->"); 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("輸入不合法,請重新輸入!"); } if (n == row * col - COUNT) printf("排雷成功!!!/n");}
這里有個spread()函數必須要講一下,這也是游戲設計中較難的一點。其作用就是若以輸入坐標為中心,若其周圍8個坐標都沒有雷則將這8個坐標全部展開。再以展開的坐標依次為中心,判斷其周圍8個坐標是否不存在雷(已展開的坐標不用再判斷,否則會形成死遞歸),若不存在則再展開它周圍的8個坐標,然后再對這8個坐標依次進行判斷......以此類推,直到不能再展開為止。我們先來看一看它的具體代碼:
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"; } }
這段代碼是怎樣實現上述功能的呢?不難看出,這里用到了遞歸思想。我是先對傳進來的坐標進行判斷,若此坐標對應的mine數組的坐標的周圍8個坐標都沒有雷,則將該坐標對應的show數組的元素置為字符‘ ’,再對它周圍的8的坐標一一排查,若排查到某一個坐標的周圍也都沒有雷,則再將這某一個坐標置為‘ ’,然后再對這某一個坐標的周圍8個坐標一一進行排查.......直到排查的某一個坐標的周圍8個坐標的周圍都至少有一個雷時停止,然后將這些不能被置為‘? ’的坐標對應的show數組的元素置為數字字符,有幾個雷就顯示數字字符幾。
最后再補充一下,我是怎樣用數字字符來顯示某個非雷區的周圍有幾個雷的。因為數組定義的是字符數組,所以不能直接用數字來表示。那如果某個非雷區周圍有3個雷的話我們怎么重置該字符數組元素好讓玩家知道呢?這里就不得不先來看一下這個ASCII表:
?數字3不能用來表示,但我們可以用字符‘3’來表示,通過上圖可以看出若想得到字符‘3’,則只需要在字符‘0’上加上數字3即可,字符‘0’對應的ASCII碼值為48,加上3就是51,剛好對應字符‘3’。同樣的,若想得到字符‘2’,則只需要用‘0’+2就行了,即用‘0’+數字就可以得到與數字相同的字符了。
好了好了,到這里實現各功能的函數就大致講完了,覺得還可以個小伙伴就給個贊吧,三連當然是最好啦。最后在這里附上全部代碼。test.c里面是游戲實現邏輯,game.c里面是游戲各函數實現邏輯,game.h里面是頭文件的包含,各函數、符號的聲明。至于為什么這么設計歡迎看我前幾天寫的三子棋哈,里面有講解。
game.h
#pragma once//頭文件的包含#include#include#include//符號的的聲明#define ROW 9#define COL 9#define COLS COL+2#define ROWS ROW+2#define COUNT 10//函數的聲明void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);//初始化棋盤void DisplayBoard(char bodrd[ROWS][COLS], int row, int col);//打印棋盤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
//游戲各函數實現邏輯#define _CRT_SECURE_NO_WARNINGS #include "game.h"#define _CRT_SECURE_NO_WARNINGS //初始化棋盤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; 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)//雷的個數 { 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";}/*若以輸入坐標為中心,其周圍8個坐標都沒有雷則全部展開。再以展開的坐標依次為中心,判斷其周圍8個是否存在雷(已展開的坐標不用再判斷,否則會形成死遞歸)以此類推,直到不能再展開為止。*/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("請輸入要排查的坐標->"); 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("輸入不合法,請重新輸入!"); } 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 };//布置雷的棋盤 char show[ROWS][COLS] = { 0 };//排查雷的棋盤,也就是用戶端看到的棋盤 InitBoard(mine, ROWS, COLS, "0");//初始化mine數組全為"0" InitBoard(show, ROWS, COLS, "*");//c初始化show數組全為’*‘ SetMine(mine, ROW, COL);//布置雷 //DisplayBoard(mine, ROW, COL); DisplayBoard(show, ROW, COL);//打印雷的棋盤 FindMine(mine,show,ROW,COL);//排雷}void test(){ int input = 0; do { srand((unsigned)time(NULL));//利用時間戳來設置隨機種子 menu(); printf("請選擇->"); scanf("%d", &input); switch (input) { case 1: printf("掃雷/n"); game(); break; case 0: printf("退出游戲/n"); break; default: printf("輸入不合法,請重新輸入!/n"); } } while (input);}int main(){ test(); return 0;}
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/123505.html
摘要:函數游戲菜單請選擇掃雷游戲退出游戲選擇錯誤解析函數內部利用時間戳,形成隨機數,主要目的是實現游戲中地雷的隨機埋放。 前言 本篇文章使用C語言實現簡單小游戲---掃雷。(文章最后有完整代碼鏈接) 想必大多數人都玩過或者了解過掃雷的游戲規則,但是在這里,我們在一起重溫一下掃雷的游戲規則,也更好...
摘要:目錄前言前言前期的準備前期的準備游戲代碼的具體實現游戲代碼的具體實現完整版的掃雷小游戲代碼完整版的掃雷小游戲代碼總結總結前言掃雷是一款大眾類的益智小游戲,于年發行。 目錄 前言 前期的準備 游戲代碼的具體實現 1、text.c 2、game.h 3、game.c 完整版的掃雷小游戲代碼: 1...
摘要:展示雷盤和初始化雷盤不一樣,展示雷盤只需要用即可,并不需要將都展示出來,只是為了我們更好的計算掃雷的位置周圍的雷的數量。 目錄 1、需求分析 2、程序架構 3、代碼實現(分函數呈現) (1)主函數代碼實現 分析: 異常處理: (2)游戲主函數實現 分析: (3)初始化函數的實現 分析: (4...
摘要:玩家選擇開始游戲后,出現雷盤,并且隨機布置雷。雷盤的數組大小為,方便計算掃雷時周圍雷的數量,并防止數組越界。放置布置的雷的信息放置排查出雷的信息初始化雷盤初始化展示界面打印展示界面效果如下布置雷隨機在數組中讓十個變成作為雷。 目錄 前言 一、游戲思路 二、游戲框架 1.菜單界面 1.菜單:...
摘要:寫在前面我們已經寫過了三子棋小游戲肯定沒玩過癮,我們再寫個掃雷小游戲吧目錄寫在前面認識游戲游戲規則游戲框架游戲實現效果展示全部代碼文件文件文件認識游戲相信大家對掃雷都不陌生每臺電腦必備的小游戲游戲規則就是在規定的時間將 ...
閱讀 2113·2021-11-16 11:45
閱讀 1182·2021-10-22 09:53
閱讀 4002·2021-09-07 10:26
閱讀 1209·2021-09-06 15:00
閱讀 2072·2019-08-28 18:09
閱讀 2795·2019-08-26 14:06
閱讀 3933·2019-08-26 13:48
閱讀 1295·2019-08-26 12:11