C語(yǔ)言實(shí)現(xiàn)掃雷游戲的方法
相信大家對(duì)掃雷一定都不陌生吧!但是你敢信僅僅使用一些C語(yǔ)言的初階基礎(chǔ)知識(shí)就能夠制作一個(gè)掃雷簡(jiǎn)單小游戲?今天,我將帶領(lǐng)大家一起走進(jìn)掃雷,探究其基礎(chǔ)算法奧秘。
一、基本思路
首先,既然是玩游戲,我們應(yīng)該設(shè)計(jì)相應(yīng)的菜單。
輸入1后繼續(xù)讓玩家選擇游戲難度:
我們?cè)谶@里設(shè)計(jì)簡(jiǎn)單模式為6x6大小的面板,雷埋10個(gè);中等模式為10x10大小的面板,雷埋30個(gè);困難模式為14x14大小的面板,雷埋50個(gè)。
為了方便雷的布置與顯示,我們?cè)O(shè)計(jì)了兩張面板:show_board[ROW][COL]和mine_board[ROW][COL],其中show面板負(fù)責(zé)顯示“空格”,mine面板負(fù)責(zé)記錄周?chē)椎膫€(gè)數(shù)。
玩家通過(guò)輸入每個(gè)格子所對(duì)應(yīng)的坐標(biāo)進(jìn)行掃雷操作。
char** show_board = (char**)malloc(sizeof(char*) * (ROW + grade * 4));//二維數(shù)組動(dòng)態(tài)內(nèi)存分配 ? for (int i = 0; i < ROW + grade * 4; i++) { ?? ?show_board[i] = (char*)malloc(sizeof(char) * (COL + grade * 4)); ?? ?memset(show_board[i], ' ', (COL + grade * 4));//數(shù)組全部賦值為空格 } ? char** mine_board = (char**)malloc(sizeof(char*) * (ROW + grade * 4)); ? for (int i = 0; i < ROW + grade * 4; i++) { ?? ?mine_board[i] = (char*)malloc(sizeof(char) * (COL + grade * 4)); ?? ?memset(mine_board[i], '0', (COL + grade * 4));//數(shù)組全部賦值為‘0' }?
二、代碼實(shí)現(xiàn)
Step1.畫(huà)圖
想要進(jìn)行掃雷游戲,首先應(yīng)該有掃雷界面的設(shè)計(jì),如下:
我們建立Showboard函數(shù)進(jìn)行面板的基本繪制:
static void Showboard(char **board,int grade)//面板制作 { ?? ?printf(" "); ?? ?for (int i = 1; i <= ROW-2+4*grade; i++) { ?? ??? ?printf(" %3d", i); ?? ?} ?? ?printf("\n"); ? ?? ?for (int i = 1; i <= ROW-2+4*grade; i++){ ?? ??? ?printf(" ? "); ?? ??? ?for (int k = 1; k <= COL-2+4*grade; k++) { ?? ??? ??? ?printf("----"); ?? ??? ?} ?? ??? ?printf("\n"); ?? ??? ?printf("%2d|",i); ?? ??? ?for (int j = 1; j <= COL-2+4*grade; j++){ ?? ??? ??? ?printf(" %c |",board[i][j]); ?? ??? ?} ?? ??? ?printf("\n"); ?? ?} ?? ?printf(" ? "); ?? ?for (int k = 1; k <= COL-2+4*grade; k++) { ?? ??? ?printf("----"); ?? ?} ?? ?printf("\n"); }
成果圖如下:
Step2. 埋雷
埋雷應(yīng)做到一下幾點(diǎn):
1.展示面板show_board(這里傳參后以形參board替代)賦值為1(BOOM宏定義為1) ;
2.為了提高用戶(hù)體驗(yàn),在被炸后能夠展示出雷的位置,我們又建立了一個(gè)lei_board數(shù)組用來(lái)顯示,并在埋雷時(shí)將對(duì)應(yīng)位置賦值為'*';
3.埋雷要具有隨機(jī)性,所以這里引用rand函數(shù)(主函數(shù)要種隨機(jī)數(shù)種子);
static void SetMines(char **board,char **lei_board,int grade) { ?? ?int i = 1; ?? ?int x, y; ?? ?while (i <= NUM+grade*20) { ?? ??? ?x = rand() % (ROW-2+4*grade) + 1; ?? ??? ?y = rand() % (COL-2+4*grade) + 1; ?? ??? ?if (board[x][y] != BOOM) { ?? ??? ??? ?board[x][y] = BOOM; ?? ??? ??? ?lei_board[x][y] = '*'; ?? ??? ??? ?i++; ?? ??? ?} ?? ?} }
Step3.計(jì)算周?chē)椎膫€(gè)數(shù)
當(dāng)我們計(jì)算周?chē)椎膫€(gè)數(shù)時(shí),自然而然地就會(huì)想到統(tǒng)計(jì)周?chē)艑m格的雷的個(gè)數(shù)。如果要搜索的位置在面板中間,這很簡(jiǎn)單,但如果是以下這類(lèi)情況,比如頂點(diǎn)格或者邊格怎么辦?如何知道該算哪個(gè)格?
為了避免這種特殊情況所帶來(lái)的問(wèn)題,我們不如直接在外面再套一圈,對(duì)于各類(lèi)面板(即二維數(shù)組)的建立也直接按照增大的來(lái),這樣就無(wú)需討論邊角的特殊性了。
統(tǒng)計(jì)函數(shù)直接通過(guò)簡(jiǎn)單的函數(shù)返回來(lái)實(shí)現(xiàn):
static int CountMine(char **board,int x,int y) { ?? ?return board[x - 1][y - 1] + board[x - 1][y] + board[x - 1][y + 1] + \ ?? ??? ?board[x][y - 1] + board[x][y + 1] + board[x + 1][y - 1] + \ ?? ??? ?board[x + 1][y] + board[x + 1][y + 1] - 8 * '0'; }
三、完整代碼
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<time.h> #include<windows.h> ? #define BOOM '1' #define ROW 8 #define COL 8 #define NUM 10 ? static void SetMines(char **board,char **lei_board,int grade)//埋雷 { ?? ?int i = 1; ?? ?int x, y; ?? ?while (i <= NUM+grade*20) { ?? ??? ?x = rand() % (ROW-2+4*grade) + 1; ?? ??? ?y = rand() % (COL-2+4*grade) + 1; ?? ??? ?if (board[x][y] != BOOM) { ?? ??? ??? ?board[x][y] = BOOM; ?? ??? ??? ?lei_board[x][y] = '*'; ?? ??? ??? ?i++; ?? ??? ?} ?? ?} } static void Showboard(char **board,int grade)//面板制作 { ?? ?printf(" "); ?? ?for (int i = 1; i <= ROW-2+4*grade; i++) { ?? ??? ?printf(" %3d", i); ?? ?} ?? ?printf("\n"); ? ?? ?for (int i = 1; i <= ROW-2+4*grade; i++){ ?? ??? ?printf(" ? "); ?? ??? ?for (int k = 1; k <= COL-2+4*grade; k++) { ?? ??? ??? ?printf("----"); ?? ??? ?} ?? ??? ?printf("\n"); ?? ??? ?printf("%2d|",i); ?? ??? ?for (int j = 1; j <= COL-2+4*grade; j++){ ?? ??? ??? ?printf(" %c |",board[i][j]); ?? ??? ?} ?? ??? ?printf("\n"); ?? ?} ?? ?printf(" ? "); ?? ?for (int k = 1; k <= COL-2+4*grade; k++) { ?? ??? ?printf("----"); ?? ?} ?? ?printf("\n"); } static int CountMine(char **board,int x,int y)//統(tǒng)計(jì)周?chē)椎臄?shù)目 { ?? ?return board[x - 1][y - 1] + board[x - 1][y] + board[x - 1][y + 1] + \ ?? ??? ?board[x][y - 1] + board[x][y + 1] + board[x + 1][y - 1] + \ ?? ??? ?board[x + 1][y] + board[x + 1][y + 1] - 8 * '0'; } ? void Game(int grade)//游戲函數(shù),grade為游戲難度等級(jí) { ?? ? ?? ?char** show_board = (char**)malloc(sizeof(char*) * (ROW + grade * 4)); ?? ?for (int i = 0; i < ROW + grade * 4; i++) { ?? ??? ?show_board[i] = (char*)malloc(sizeof(char) * (COL + grade * 4)); ?? ??? ?memset(show_board[i], ' ', (COL + grade * 4)); ?? ?} ?? ?char** mine_board = (char**)malloc(sizeof(char*) * (ROW + grade * 4)); ?? ?for (int i = 0; i < ROW + grade * 4; i++) { ?? ??? ?mine_board[i] = (char*)malloc(sizeof(char) * (COL + grade * 4)); ?? ??? ?memset(mine_board[i], '0', (COL + grade * 4)); ?? ?} ?? ?char** lei_board = (char**)malloc(sizeof(char*) * (ROW + grade * 4)); ?? ?for (int i = 0; i < ROW + grade * 4; i++) { ?? ??? ?lei_board[i] = (char*)malloc(sizeof(char) * (COL + grade * 4)); ?? ??? ?memset(lei_board[i], ' ', (COL + grade * 4)); ?? ?} ?? ? ?? ?SetMines(mine_board,lei_board,grade); ?? ?int x = 0, y = 0; ?? ?int total = 0; ?? ?while (1) ?? ?{ ?? ??? ? ?? ??? ?Showboard(show_board, grade); ?? ??? ?printf("請(qǐng)輸入坐標(biāo):"); ?? ??? ?//printf("%d", '*'); ?? ??? ?scanf("%d %d", &x, &y); ?? ??? ?if (!(x > 0 && x <= ROW + 4 * grade - 2 && y > 0 && y <= COL + 4 * grade - 2)) { ?? ??? ??? ?printf("掃雷的位置有問(wèn)題!\n"); ?? ??? ??? ?continue; ?? ??? ?} ?? ??? ?if (show_board[x][y] != ' ') { ?? ??? ??? ?printf("該位置已經(jīng)掃過(guò)了!\n"); ?? ??? ??? ?continue; ?? ??? ?} ?? ??? ?if (mine_board[x][y] == '1') { ?? ??? ??? ?printf("對(duì)不起,你被炸死了!\n"); ?? ??? ??? ?Showboard(lei_board, grade); ?? ??? ??? ?break; ?? ??? ?} ?? ??? ?else { ?? ??? ??? ?int count = CountMine(mine_board, x, y); ?? ??? ??? ?show_board[x][y] = count + '0'; ?? ??? ??? ?total++; ?? ??? ??? ?system("cls"); ?? ??? ?} ?? ??? ?if ((ROW - 2) * (COL - 2) - total <= NUM) { ?? ??? ??? ?printf("恭喜你,游戲通過(guò)!\n"); ?? ??? ??? ?break; ?? ??? ?} ?? ?} ?? ?for (int i = 0; i < ROW + grade * 4; i++) { ?? ??? ?free(show_board[i]); ?? ?} ?? ?free(show_board); ?? ?for (int i = 0; i < ROW + grade * 4; i++) { ?? ??? ?free(mine_board[i]); ?? ?} ?? ?free(mine_board); ?? ?for (int i = 0; i < ROW + grade * 4; i++) { ?? ??? ?free(lei_board[i]); ?? ?} ?? ?free(lei_board); } ? void Menu() { ?? ?printf("#########################################\n"); ?? ?printf("## ? ? ? ? ? ? ? ? 1.play ? ? ? ? ? ? ?##\n"); ?? ?printf("## ? ? ? ? ? ? ? ? 0.exit ? ? ? ? ? ? ?##\n"); ?? ?printf("#########################################\n"); } ? int main() { ?? ?srand((unsigned long)time(NULL)); ?? ?int quit = 0; ?? ?while (!quit) ?? ?{ ?? ??? ?int select; ?? ??? ?Menu(); ?? ??? ?printf("請(qǐng)輸入游戲選項(xiàng):"); ?? ??? ?scanf("%d", &select); ?? ??? ?switch (select) ?? ??? ?{ ?? ??? ?case 1: ?? ??? ??? ?printf("#########################################\n"); ?? ??? ??? ?printf("## ? ? ? ? ? ? ? ? 1.easy ? ? ? ? ? ? ?##\n"); ?? ??? ??? ?printf("## ? ? ? ? ? ? ? ? 2.middle ? ? ? ? ? ?##\n"); ?? ??? ??? ?printf("## ? ? ? ? ? ? ? ? 3.difficult ? ? ? ? ##\n"); ?? ??? ??? ?printf("#########################################\n"); ?? ??? ??? ?printf("請(qǐng)輸入游戲難度:"); ?? ??? ??? ?scanf("%d", &select); ?? ??? ??? ?switch (select) ?? ??? ??? ?{ ?? ??? ??? ?case 1: ?? ??? ??? ??? ?Game(0); ?? ??? ??? ??? ?break; ?? ??? ??? ?case 2: ?? ??? ??? ??? ?Game(1); ?? ??? ??? ??? ?break; ?? ??? ??? ?case 3: ?? ??? ??? ??? ?Game(2); ?? ??? ??? ??? ?break; ?? ??? ??? ?} ?? ??? ??? ?break; ?? ??? ?case 0: ?? ??? ??? ?quit = 1; ?? ??? ??? ?printf("感謝使用!"); ?? ??? ??? ?break; ?? ??? ?default: ?? ??? ??? ?printf("輸入有誤,請(qǐng)重新輸入!\n"); ?? ??? ??? ?break; ?? ??? ?} ? ?? ?} ?? ? }
期待大家在這個(gè)代碼的基礎(chǔ)上加入更多創(chuàng)新與改進(jìn),寫(xiě)出用戶(hù)體驗(yàn)感更好,更加智能高端的掃雷程序!
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- C語(yǔ)言實(shí)現(xiàn)掃雷小游戲完整算法詳解(附完整代碼)
- C語(yǔ)言遞歸應(yīng)用實(shí)現(xiàn)掃雷游戲
- C語(yǔ)言二維數(shù)組應(yīng)用實(shí)現(xiàn)掃雷游戲
- C語(yǔ)言制作掃雷游戲(圖形庫(kù))
- C語(yǔ)言實(shí)現(xiàn)掃雷代碼
- 基于C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易的掃雷游戲
- C語(yǔ)言詳細(xì)講解通過(guò)遞歸實(shí)現(xiàn)掃雷的展開(kāi)
- C語(yǔ)言實(shí)現(xiàn)經(jīng)典掃雷小游戲完整代碼(遞歸展開(kāi)?+?選擇標(biāo)記)
- C語(yǔ)言實(shí)現(xiàn)爆炸展開(kāi)的掃雷詳解
相關(guān)文章
C++實(shí)現(xiàn)LeetCode(7.翻轉(zhuǎn)整數(shù))
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(7.翻轉(zhuǎn)整數(shù)),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)順序表的進(jìn)階講解
程序中經(jīng)常需要將一組數(shù)據(jù)元素作為整體管理和使用,需要?jiǎng)?chuàng)建這種元素組,用變量記錄它們,傳進(jìn)傳出函數(shù)等。一組數(shù)據(jù)中包含的元素個(gè)數(shù)可能發(fā)生變化,順序表則是將元素順序地存放在一塊連續(xù)的存儲(chǔ)區(qū)里,元素間的順序關(guān)系由它們的存儲(chǔ)順序自然表示2022-04-04深入探討:main函數(shù)執(zhí)行完畢后,是否可能會(huì)再執(zhí)行一段代碼?
本篇文章是對(duì)main函數(shù)執(zhí)行完畢后,是否可能會(huì)再執(zhí)行一段代碼,進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05C語(yǔ)言實(shí)現(xiàn)打印數(shù)組以及打印注意事項(xiàng)說(shuō)明
這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)打印數(shù)組以及打印注意事項(xiàng)說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01C/C++ 中堆和棧及靜態(tài)數(shù)據(jù)區(qū)詳解
這篇文章主要介紹了C/C++ 中堆和棧及靜態(tài)數(shù)據(jù)區(qū)詳解的相關(guān)資料,需要的朋友可以參考下2017-04-04C++類(lèi)和對(duì)象深入探索之分文件編寫(xiě)點(diǎn)和圓的關(guān)系詳解
先前把C++類(lèi)和對(duì)象的封裝講完了,并且留下了一個(gè)判斷兩個(gè)立方體是否相等的案例,但是那么多知識(shí)點(diǎn),僅僅一個(gè)案例是不夠的,所以再來(lái)一個(gè)分文件編寫(xiě)點(diǎn)圓關(guān)系的案例;創(chuàng)建圓類(lèi)和點(diǎn)類(lèi),圓類(lèi)包含點(diǎn)類(lèi),算是一個(gè)嵌套吧,順便復(fù)習(xí)一下分文件編寫(xiě)的方法,開(kāi)整2022-05-05