您好,登錄后才能下訂單哦!
這篇文章主要介紹“c語言怎么實現含遞歸清場版掃雷游戲”,在日常操作中,相信很多人在c語言怎么實現含遞歸清場版掃雷游戲問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”c語言怎么實現含遞歸清場版掃雷游戲”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
想必大家都玩過掃雷
這便是一個標準的掃雷,換做代碼實現,我們需要考慮以下幾點:
1.棋盤的設計與初始化
2.在棋盤中放入雷
3.統計雷數
4.如何實現“一片”的效果
5.輸贏的判斷
接下來我們進行具體操作。
對任意一個游戲,菜單是必不可少的,也是最簡單的部分,直接上代碼
void menu() { printf("------------------掃雷------------------\n"); printf("---------------1.開始游戲---------------\n"); printf("---------------0.退出游戲---------------\n"); } int main() { srand((unsigned int)time(NULL)); int a = 0; do { menu(); scanf("%d", &a); if (a == 0) { break; } game(); } while (a); return 0; }
其中srand是為了求隨機值,用來布置雷
主菜單完后進入game函數,在game函數里我們就要開始主要的游戲部分,如棋盤初始化與打印等,當然這些步驟都依靠函數完成,game函數只相當于集合了一系列的游戲模塊
void game() { char mine[ROWS][COLS]; char show[ROWS][COLS]; initeboard(mine, ROWS, COLS, '0'); initeboard(show, ROWS, COLS, '*');//初始棋盤 displayboard(show, ROW, COL);//打印棋盤 mine_make(mine, ROW, COL);//設置雷 //displayboard(mine, ROW, COL); find_mine(mine, show, ROWS, COLS);//排查雷 }
可以看到,我在game函數里初始了兩個棋盤,為什么要兩個呢?
其實,一個是為了放置了雷,一個為了展示給玩家,為什么不用一個呢,我們要在放雷處用'1',表示不放雷處用‘0',這樣計算一個坐標周圍雷的數量就會更簡單,接下來看一段代碼:
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <time.h> #define ROW 10 #define COL 10 #define ROWS ROW+2 #define COLS COL+2
這里我們看到定義了一個ROWS和COLS這又是為何呢?
掃雷時當你確認一個點時,它會對此點周圍的八個點進行排查看是否有淚,當坐標位于紅線處時沒有無法判斷八個,因此有了ROWS與COLS,這時,有人就會問了:那埋雷的地方用ROW COL就可以了,還不用擔心雷跑到外邊我們加的框,想法很好,但我們有兩個棋盤,必須對應,而且也不存在跑出雷的情況,往下分析你就會知道
void initeboard(char board[ROWS][COLS], int cols, int rows,char s)//棋盤初始化,此處用了個節省步驟的方法,不用兩個棋盤依次初始化 { int i = 0; int j = 0; for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { board[i][j] = s; } } } void displayboard(char board[ROWS][COLS], int row, int col)//棋盤打印 { int i = 0; int j = 0; printf(" ");//與行中打印的0%d對應 for (j = 0; j <=col; j++) { printf(" %d ", j); } printf("\n"); printf("-"); for (j = 1; j <= col + 1; j++) { printf("---"); printf("|"); } printf("\n");//列對應打印完成 for (i = 1; i <= row; i++) { if (i <= 9) { printf(" 0%d ", i); } else printf(" %d ", i); printf("|"); for (j = 1; j <= col; j++) { printf(" %c ", board[i][j]); printf("|"); } printf("\n"); printf("-"); for (j = 1; j <= col+1; j++) { printf("---"); printf("|"); } printf("\n");//行對應嵌套在內部 打印的數前加0是為了讓當行數大于9時能夠對應 如09與10 } }
棋盤的打印做了行列對應,所以可能有點不明顯
雷的放置很簡單,在棋盤‘0',處放置就行,因為我們對隨機數的算式使隨機數只會出現在0-9沒有跑出的情況
mine_make(char mine[ROWS][COLS], int row, int col)//設置雷 { int count = 10; while (count) { int x = rand() % 10; int y = rand() % 10; if (mine[x][y] == '0') { mine[x][y] = '1'; count--; } } }
雷的個數就需要一定考慮了:
首先,我們需要把周圍八個位置是否有雷,有多少個雷判斷出來,這時我們設計‘0' ‘1'類型就排上用場了,但是注意,這是字符,不是數字
當然返回的數字記得轉成字符類型
int get_mine(char mine[ROWS][COLS], int i, int j)//得到一個坐標附近雷的個數 { return mine[i - 1][j - 1] + mine[i - 1][j] + mine[i - 1][j + 1] + mine[i][j - 1] + mine[i][j + 1] + mine[i + 1][j - 1] + mine[i +1 ][j] + mine[i + 1][j + 1] - 8 * '0';//此處我們的數字其實是字符,用此方法可以轉為數字整形 }
當不為雷是會展開附近一片不為雷,提高游戲效率
void spread(char show[ROWS][COLS], char mine[ROWS][COLS], int x, int y)//遞歸方法實現一大片 { show[x][y] = ' ';//先讓輸入金的坐標處變為空格,因為已經判定過雷所以可以直接轉空格 int i = 0; int j = 0; int ret = 0; for (i = x - 1; i <= x + 1; i++) { for (j = y - 1; j <= y + 1; j++)//嵌套for循環表示輸入坐標包括自生及周圍八個 { if (i > 0 && i <= ROW && j > 0 && j <= COL && mine[i][j] != '1' && show[i][j] == '*')//防止出現負坐標,避免有雷,避免輸入重復 { ret = get_mine(mine, i, j);//判斷ret是0或非0,并得出周圍雷數 if (!ret)//如果ret=0,!ret便是非0;為真 { spread(show, mine, i, j);//遞歸 } if (ret)//ret!=0時為真,便打印數 { show[i][j] = ret + '0';//使數字轉成對應字符 } } } } }
負責判斷是否被炸死及游戲勝利
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//排查雷 { printf("請輸入坐標\n"); int i = 0; int j = 0; int win = 0; while (row*col-10)//因為是十個雷,所以是—10,因為下總數減10就贏了,所以可以以此跳出循環,當然要是雷部位10,定一個變量就行,此處就不改了 { scanf("%d %d", &i, &j); if (mine[i][j] == '1') { printf("你掛了\n"); displayboard(mine, ROW, COL); break; } else { show[i][j] = get_mine(mine, i, j)+'0'; spread(show,mine, i, j); displayboard(show, ROW, COL); win++; } } if (win ==row * col - 10) { printf("恭喜你,成功了\n"); displayboard(mine, ROW, COL); } }
具體注釋都在代碼里了
正常情況把打印雷盤注釋就行,就可以正常游戲了
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <time.h> #define ROW 10 #define COL 10 #define ROWS ROW+2 #define COLS COL+2 void menu() { printf("------------------掃雷------------------\n"); printf("---------------1.開始游戲---------------\n"); printf("---------------0.退出游戲---------------\n"); } void initeboard(char board[ROWS][COLS], int cols, int rows,char s)//棋盤初始化,此處用了個節省步驟的方法,不用兩個棋盤依次初始化 { int i = 0; int j = 0; for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { board[i][j] = s; } } } void displayboard(char board[ROWS][COLS], int row, int col)//棋盤打印 { int i = 0; int j = 0; printf(" ");//與行中打印的0%d對應 for (j = 0; j <=col; j++) { printf(" %d ", j); } printf("\n"); printf("-"); for (j = 1; j <= col + 1; j++) { printf("---"); printf("|"); } printf("\n");//列對應打印完成 for (i = 1; i <= row; i++) { if (i <= 9) { printf(" 0%d ", i); } else printf(" %d ", i); printf("|"); for (j = 1; j <= col; j++) { printf(" %c ", board[i][j]); printf("|"); } printf("\n"); printf("-"); for (j = 1; j <= col+1; j++) { printf("---"); printf("|"); } printf("\n");//行對應嵌套在內部 打印的數前加0是為了讓當行數大于9時能夠對應 如09與10 } } mine_make(char mine[ROWS][COLS], int row, int col)//設置雷 { int count = 10; while (count) { int x = rand() % 10; int y = rand() % 10; if (mine[x][y] == '0') { mine[x][y] = '1'; count--; } } } int get_mine(char mine[ROWS][COLS], int i, int j)//得到一個坐標附近雷的個數 { return mine[i - 1][j - 1] + mine[i - 1][j] + mine[i - 1][j + 1] + mine[i][j - 1] + mine[i][j + 1] + mine[i + 1][j - 1] + mine[i +1 ][j] + mine[i + 1][j + 1] - 8 * '0';//此處我們的數字其實是字符,用此方法可以轉為數字整形 } void spread(char show[ROWS][COLS], char mine[ROWS][COLS], int x, int y)//遞歸方法實現一大片 { show[x][y] = ' ';//先讓輸入金的坐標處變為空格,因為已經判定過雷所以可以直接轉空格 int i = 0; int j = 0; int ret = 0; for (i = x - 1; i <= x + 1; i++) { for (j = y - 1; j <= y + 1; j++)//嵌套for循環表示輸入坐標包括自生及周圍八個 { if (i > 0 && i <= ROW && j > 0 && j <= COL && mine[i][j] != '1' && show[i][j] == '*')//防止出現負坐標,避免有雷,避免輸入重復 { ret = get_mine(mine, i, j);//判斷ret是0或非0,并得出周圍雷數 if (!ret)//如果ret=0,!ret便是非0;為真 { spread(show, mine, i, j);//遞歸 } if (ret)//ret!=0時為真,便打印數 { show[i][j] = ret + '0';//使數字轉成對應字符 } } } } } void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//排查雷 { printf("請輸入坐標\n"); int i = 0; int j = 0; int win = 0; while (row*col-10)//因為是十個雷,所以是—10,因為下總數減10就贏了,所以可以以此跳出循環,當然要是雷部位10,定一個變量就行,此處就不改了 { scanf("%d %d", &i, &j); if (mine[i][j] == '1') { printf("你掛了\n"); displayboard(mine, ROW, COL); break; } else { show[i][j] = get_mine(mine, i, j)+'0'; spread(show,mine, i, j); displayboard(show, ROW, COL); win++; } } if (win ==row * col - 10) { printf("恭喜你,成功了\n"); displayboard(mine, ROW, COL); } } void game() { char mine[ROWS][COLS]; char show[ROWS][COLS]; initeboard(mine, ROWS, COLS, '0'); initeboard(show, ROWS, COLS, '*');//初始棋盤 displayboard(show, ROW, COL);//打印棋盤 mine_make(mine, ROW, COL);//設置雷 displayboard(mine, ROW, COL); find_mine(mine, show, ROWS, COLS);//排查雷 } int main() { srand((unsigned int)time(NULL)); int a = 0; do { menu(); scanf("%d", &a); if (a == 0) { break; } game(); } while (a); return 0; }
到此,關于“c語言怎么實現含遞歸清場版掃雷游戲”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。