目錄
- 問題簡述
- 一、大概思路
- 二、基本流程
- 1.列印游戲選單
- 2.初始化掃雷面板
- 3.列印設定好的掃雷面版
- 4.隨機設定雷的坐標
- 5.進行排雷并判斷輸贏
- 三、拓展衍生
- 四、總代碼展示
- 1.頭檔案代碼
- 2.游戲實作代碼
- 3.主函式代碼
- 五、代碼效果展示
問題簡述
用C語言實作掃雷游戲
一、大概思路
1.在我們開始設計掃雷面板前,要有一個選單選擇開始游戲或退出游戲,玩完一把后仍然有選單選擇,
2.我們可以打開網頁版初階掃雷面板,它是一個9*9的格子面板,這時我們能聯想到二維陣列,
3.因為掃雷是先有面板選擇坐標,選擇后再把含有排除雷的數量的面板列印出來,因此要創建兩個二維陣列,但需要考慮的是,如果在掃雷面板最邊上排雷,排雷的坐標可能對于我們創建的陣列已經越界,這是不可取的,因此我們還要有行與列各11的掃雷面板(如圖所示),并且將其中一個二維陣列都放0,另一個都用‘ * ’號來代表沒有排雷的區域,

4.隨機設定雷的坐標,因為要隨機則涉及到rand與srand函式,并且設定地雷的區域是此前沒有設定地雷的區域,坐標不能重復,用‘1’代表雷,‘0’代表沒有雷的區域,
5.設定好地雷后要進行排雷,如果在選擇的坐標其邊上5個的區域內有雷,則必須在選擇的區域處將其邊上5個區域的雷數顯示出來,而且數字1與地雷‘1’要區分開來,
6.判斷是否踩雷,如果全部雷都排出來,則判斷成功,如果踩到了雷,則直接判斷失敗,如果既沒有排完雷也沒有踩雷,則游戲繼續,
二、基本流程
1.列印游戲選單
我們要求的是開始前選擇是否開始游戲,游戲結束時不關閉頁面重新進入選單,
void menu()
{
printf("************************\n");
printf("*********1.play*********\n");
printf("*********0.exit*********\n");
printf("************************\n");
}
int main
{
do
{
menu();
printf("請選擇:>\n");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戲\n");
break;
default:
printf("請重新選擇\n");
break;
}
} while (input);
}
2.初始化掃雷面板
先建立兩個不同的字符陣列,再將其中一個陣列都放入字符0,為了函式的可修改性,將陣列的行與列在頭檔案中設定,再在源檔案中包含頭檔案,函式實作前首先要在頭檔案中宣告,
void InitBoard(char board[ROWS][COLS], int rows, int cols,char set)
{
int i = 0;
for (i = 0; i < rows; i++)
{
int j = 0;
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
頭檔案處宣告與定義:
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
void InitBoard(char board[ROWS][COLS], int rows, int cols);//初始化棋盤
3.列印設定好的掃雷面版
因為一開始我們并沒有排雷,因此要將游戲面板上的所有坐標都先用‘ * ’號進行覆寫,選擇后再把排出雷的數量或雷列印出來,為了玩家在輸入坐標時方便,我們可以在掃雷面板的最上方與最左方將行數與列數標出來,
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
printf("---------------\n");
for (i = 0; i <= 9; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
int j = 0;
printf("%d ",i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("--------------\n");
}
頭檔案處進行宣告
void DisplayBoard(char Board[ROWS][COLS], int rows, int cols);//列印棋盤
4.隨機設定雷的坐標
根據掃雷游戲規則,在初階掃雷面板中最多能設定10個雷,并且要隨機與不重復,因此在主函式中我們設定種子,讓電腦隨機生成坐標放入地雷,
void SetMine(char board[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (board[x][y] != '1')
{
board[x][y] = '1';
count--;
}
}
}
頭檔案處進行宣告
void SetMine(char board[ROW][COL], int row, int col);//設定地雷
5.進行排雷并判斷輸贏
當雷已經隨機設定好后,我們要開始排雷,選擇的坐標(不能輸入非法坐標)在圍繞其旁邊的8個坐標內將雷的個數列印出來,因為一個掃雷面板只有10個雷,而總共有81個坐標,則還有71個坐標沒有設定雷,當我們排的雷達到10個后則成功,最后無論成功與失敗都要列印掃雷面板上所以雷的位置,
極其需要注意的點:因為我們創建的是字符型別的陣列,因此我們在列印排出雷的數量的時候要加上字符0,因為數字個位數加上字符0都會變為字符數,這樣才符合我們創建的陣列型別,
void FineMine(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 - EASY_COUNT)
{
printf("要排查地雷的坐標:\n");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == '1')
{
printf("你被炸死了\n");
DisplayBoard(mine, ROW, COL);
break;
}
else
{
int count = GetMineCount(mine, x, y);
show[x][y] = count+'0';
DisplayBoard(show , ROW, COL);
win++;
}
}
else
{
printf("坐標非法,請重新輸入\n");
}
}
if (win == row * col - EASY_COUNT)
{
printf("排雷成功\n");
DisplayBoard(mine, ROW, COL);
}
}
三、拓展衍生
測驗發現代碼效果沒有問題后,我們可以拓展出掃雷面板更大、如何在第一次排雷時不踩雷、倒計時等問題,如果把這些問題解決對自己的代碼邏輯會有很大的提升,
四、總代碼展示
1.頭檔案代碼
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define EASY_COUNT 10
void InitBoard(char board[ROWS][COLS], int rows, int cols);//初始化棋盤
void DisplayBoard(char Board[ROWS][COLS], int rows, int cols);//列印棋盤
void SetMine(char board[ROW][COL], int row, int col);//設定地雷
void FineMine(char mine[ROW][COL], char show[ROW][COL],int row, int col);//找地雷
int GetMineCount(char mine[ROWS][COLS], int x, int y);
2.游戲實作代碼
#include "game.h"
void InitBoard(char board[ROWS][COLS], int rows, int cols,char set)
{
int i = 0;
for (i = 0; i < rows; i++)
{
int j = 0;
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
printf("---------------\n");
for (i = 0; i <= 9; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
int j = 0;
printf("%d ",i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("--------------\n");
}
void SetMine(char board[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (board[x][y] != '1')
{
board[x][y] = '1';
count--;
}
}
}
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
return mine[x - 1][y] +
mine[x - 1][y - 1] +
mine[x][y - 1] +
mine[x][y + 1] +
mine[x + 1][y] +
mine[x + 1][y + 1] +
mine[x + 1][y - 1] +
mine[x - 1][y + 1]-8*'0';
}
void FineMine(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 - EASY_COUNT)
{
printf("要排查地雷的坐標:\n");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == '1')
{
printf("你被炸死了\n");
DisplayBoard(mine, ROW, COL);
break;
}
else
{
int count = GetMineCount(mine, x, y);
show[x][y] = count+'0';
DisplayBoard(show , ROW, COL);
win++;
}
}
else
{
printf("坐標非法,請重新輸入\n");
}
}
if (win == row * col - EASY_COUNT)
{
printf("排雷成功\n");
DisplayBoard(mine, ROW, COL);
}
}
3.主函式代碼
#include "game.h"
void menu()
{
printf("************************\n");
printf("*********1.play*********\n");
printf("*********0.exit*********\n");
printf("************************\n");
}
void game()
{
char mine[ROWS][COLS];
char show[ROWS][COLS];
InitBoard(mine, ROWS, COLS,'0');
InitBoard(show, ROWS, COLS,'*');
DisplayBoard(show, ROW, COL);
SetMine(mine, ROW, COL);
FineMine(mine,show, ROW, COL);
}
int main()
{
int input = 0;
srand((unsigned)time(NULL));
do
{
menu();
printf("請選擇:>\n");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戲\n");
break;
default:
printf("請重新選擇\n");
break;
}
} while (input);
return 0;
}
五、代碼效果展示

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/293053.html
標籤:其他
上一篇:c語言之推箱子功能匯總
下一篇:Unity 之 Excel表格轉換為Unity用的檔案格式 -- ScriptableObject,Json,XML 全部搞定
