目錄
- 分布詳解
- 1. 創建專案
- 2. 總體代碼設計
- 3. 定義棋盤大小
- 4.初始化棋盤
- 5. 列印棋盤
- 6. 布置雷
- 7. 排查雷
- 代碼匯總
- game.h
- game.c
- test.c
- 發現bug
分布詳解
1. 創建專案
- 在源檔案中創建
test.c檔案,對專案的相關功能進行測驗, - 在頭檔案中創建
game.h檔案,對自定義函式進行函式宣告, - 在源檔案中創建
game.c檔案,對自定義函式進行函式定義,
2. 總體代碼設計
test.c
#include <stdio.h>
void menu()
{
printf("*********************************\n");
printf("********** 1. play *********\n");
printf("********** 0. exit *********\n");
printf("*********************************\n");
}
void game()
{
}
int main()
{
int input = 0;
do
{
menu();
printf("請選擇:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戲\n");
break;
default:
printf("選擇錯誤,請重新選擇:>\n");
break;
}
} while (input);
return 0;
}
3. 定義棋盤大小

若定義成 9*9 的棋盤,則最外圈的排雷資訊和內部的要分情況討論,增加了代碼的復雜性,
所以我們考慮將棋盤放大一圈,這樣的話就能對棋盤內的所有位置做統一的處理,
除此之外,還要對有雷、無雷和所選區域周圍是否有雷做相應的統計,而這些僅使用一個二維陣列難以實作,
所以考慮定義兩個二維陣列,一個定義為
mine用來存放布置雷的資訊,有雷設為’1’,無雷設為’0’,另一個陣列show,用來列印棋盤及展示所選區域周圍是否有雷等資訊,
在game.h函式中定義宏,提高代碼的擴展性,
// 用于處理棋盤時做回圈控制變數使用
#define ROW 9
#define COL 9
// 用于初始化棋盤
#define ROWS ROW+2
#define COLS COL+2
在test.c中進行定義
char mine[ROWS][COLS]; // 存放雷的資訊
char show[ROWS][COLS]; // 存放排查出的雷的資訊
4.初始化棋盤
mine默認初始化為’0’,show初始化為’ '(空格),由于兩個棋盤要初始化的字符不同,我們用傳參的形式將要初始化的字符傳遞給初始化函式,
在game.h中進行函式宣告,
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
在game.c中進行函式定義,
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;
}
}
}
5. 列印棋盤
game.h
// 雖然沒有列印最外邊一圈的元素,但是傳參的時候傳的是mine陣列,還是要傳11*11的
void DisplayBoard(char board[ROWS][COLS], int row, int col);
game.c
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
for (i = 1; i <= row; i++)
{
if (i == 1)
printf(" %d ", i);
else
printf(" %d ", i);
}
printf("\n");
for (i = 0; i <= row; i++)
{
if (i == 0)
printf(" ");
else
printf("----");
}
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");
int m = 0;
for (m = 0; m <= row; m++)
{
if (m == 0)
printf(" ");
else
printf("----");
}
printf("\n");
}
}
列印效果展示:

6. 布置雷
這里要隨機生成雷的坐標,需要用到
rand函式,rand使用前要呼叫srand,我們在 主函式中
do回圈外面 呼叫srand( (unsigned)time( NULL ) );設定亂數的生成起點,將隨機生成的坐標內的值設為’1’,表示此處有雷,
game.h
void SetMine(char board[ROWS][COLS], int row, int col);
game.c
void SetMine(char board[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
while (count)
{
// 1. 生成隨機下標
int x = rand() % row + 1;
int y = rand() % col + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
將隨機生成的雷列印出來,查看程式是否正確,列印效果如圖所示:

7. 排查雷
排查玩家輸入的坐標是否有雷,
若輸入坐標無雷,則統計該坐標周圍八個坐標的雷數,并在這個坐標上顯示出來,
game.h
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
game.c
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 + 1][y - 1] +
mine[x + 1][y] +
mine[x + 1][y + 1] +
mine[x][y + 1] +
mine[x - 1][y + 1] - 8 * '0');
}
void FindMine(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("請輸入要排查的坐標:>");
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);
}
}
代碼匯總
game.h
#pragma once
#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, char set);
// 列印棋盤
// 雖然沒有列印最外邊一圈的元素,但是傳參的時候傳的是mine陣列還是要傳11*11的
void DisplayBoard(char board[ROWS][COLS], int row, int col);
// 布置雷
void SetMine(char board[ROWS][COLS], int row, int col);
// 排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
game.c
#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;
for (i = 1; i <= row; i++)
{
if (i == 1)
printf(" %d ", i);
else
printf(" %d ", i);
}
printf("\n");
for (i = 0; i <= row; i++)
{
if (i == 0)
printf(" ");
else
printf("----");
}
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");
int m = 0;
for (m = 0; m <= row; m++)
{
if (m == 0)
printf(" ");
else
printf("----");
}
printf("\n");
}
}
void SetMine(char board[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
while (count)
{
// 1. 生成隨機下標
int x = rand() % row + 1;
int y = rand() % col + 1;
if (board[x][y] == '0')
{
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 + 1][y - 1] +
mine[x + 1][y] +
mine[x + 1][y + 1] +
mine[x][y + 1] +
mine[x - 1][y + 1] - 8 * '0');
}
void FindMine(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("請輸入要排查的坐標:>");
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);
}
}
test.c
#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'); // 初始化為'0'
InitBoard(show, ROWS, COLS, ' '); // 初始化為' ' -- 空格
// 列印棋盤
//DisplayBoard(mine, ROW, COL);
DisplayBoard(show, ROW, COL);
// 布置雷
SetMine(mine, ROW, COL);
//DisplayBoard(mine, ROW, COL);
// 排查雷
FindMine(mine, show, ROW, COL);
}
int main()
{
int input = 0;
srand((unsigned)time(NULL));
do
{
menu();
printf("請選擇:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戲\n");
break;
default:
printf("選擇錯誤,請重新選擇:>\n");
break;
}
} while (input);
return 0;
}
發現bug
不知道大家有沒有發現,在這個小游戲當中也存在著
bug,當我們輸入字符或者浮點數時,程式就會進入死回圈,
那么這個問題要怎么解決呢?
經過一番查找,我發現bug是在scanf函式讀取快取區的時候產生的,
想要了解如何解決bug,可以訪問這篇博客,帶你解決scanf造成的死回圈問題,
希望可以對大家有所幫助,如果有什么不對的地方,還煩請指教,謝謝!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/294309.html
標籤:其他
下一篇:C語言——猜游戲
