目錄
一:想要達到的游戲功能:
二:代碼展示環節:
1:text.c游戲測驗程式的撰寫
2:進行game.c功能的實作
1:在game.h中進行游戲函式的宣告:
2:初始化棋盤陣列函式的定義
3:棋盤列印函式的實作
4:放置雷函式的實作
5:實作在show中排查后顯示位置的雷數
6:實作排雷函式
7:用遞回來實作打開一個空格展開一片
三:game.c的總代碼
一:想要達到的游戲功能:
大家如果想撰寫一個游戲,應具備以下的步驟:
1:了解游戲的規則
2: 知道游戲應該實作哪些功能
3:根據這些功能構建出游戲的基本框架
4:如何將整個游戲拆分成一個個模塊,進行模塊化編程
我們拿到一個任務,尤其是撰寫像掃雷這對于初學者有難度的問題時,應該做到先理清思路,再進行代碼撰寫,現在我們來講一下掃雷游戲預期實作的功能,
1:要有一個游戲選單能讓玩家選擇進入游戲還是退出游戲,
2:程式能夠實作反復玩,玩家玩完一盤后可以進行選擇是否繼續游戲還是退出,
3:應該有一個game函式來進入游戲后游戲的整體功能
game中應有的功能:
1:創建兩個棋盤二維陣列:一個棋盤是放置雷的,另一個棋盤則是玩家游戲時看到的棋盤,
(注意如果只有一個棋盤:那么這個棋盤陣列要放1:表示有雷 還要放0表示無雷,此時棋盤已經放滿,但還需要表示玩家掃雷時顯示該位置周圍的雷數,因此一個棋盤陣列不方便做到)
2:撰寫一個函式對陣列進行初始化:比如把mine(表示放置雷陣列)全部初始化成0(表示無雷),將show(表示展示給玩家看并進行排雷的陣列)全部初始化成'*'(表示此位置沒有被查過,像網頁版上沒有排雷之前的空白一樣)
3:撰寫一個函式進行放置雷,即在mine陣列中隨機選取位置放置’1‘(表示此位置有雷)
4:撰寫一個函式表示在mine陣列中一個位置周圍的雷數,并將它傳遞給show,這樣在排雷后,如果沒有被炸死就會顯示這個位置的雷數
5:撰寫一個遞回函式其功能是如果一個位置顯示0(即周圍的雷數為0),會先把自己的位置變成空格,再檢索周圍8個陣列元素,把表示為0的也重置成空格,以上的目的是實作像網頁版一樣,點開一個空格展開一片空格,
6:讓玩家輸入坐標進行排雷(此程序應是一個回圈),并且能反饋”很遺憾!你被炸死了,“和”恭喜你排雷成功!“兩種結果
二:代碼展示環節:
為了更加清晰有條理的撰寫程式,我們用多檔案的方式來呈現,
1:text.c游戲測驗程式的撰寫
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#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');
InitBoard(show, ROWS, COLS, '*');
//在mine陣列中進行放置雷
SetMine(mine, ROW, COL);
//列印出show棋盤給玩家看
DisplayBoard(show, ROW, COL);
//進行排雷
FindMine(mine, show, ROW, COL);
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do {
menu();
printf("請選擇>:\n");
scanf("%d", &input);
//在選單中選擇是否進入游戲
//因為要實作反復玩,所以用do while回圈
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戲\n");
break;
default:
printf("輸入的是無效指令,請重新輸入:\n");
break;
}
} while (input);
return 0;
}
2:進行game.c功能的實作
1:在game.h中進行游戲函式的宣告:
#pragma once
#define ROW 9
#define COL 9//玩家操作的棋盤應該是9*9的
//但為了防止在查雷的數目時,9*9邊緣的格子周圍并沒有8個格子
#define ROWS ROW+2
#define COLS COL+2
#define MineCount 10//定義雷的數目
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
//初始化棋盤陣列的宣告
void InitBoard(char arr[ROWS][COLS], int rows, int cols, char set);
//棋盤陣列的列印
void DisplayBoard(char board[ROWS][COLS], int row, int col);
//放置雷函式的宣告
void SetMine(char board[ROWS][COLS], int row, int col);
//求mine陣列中一個位置周圍的雷數
int GetMineCount(char mine[ROWS][COLS], int x, int y);
//排雷函式的宣告
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
2:初始化棋盤陣列函式的定義
//這里進行棋盤陣列的初始化
//
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;//這里的set存放的是0或*,方便測驗時兩個棋盤的列印
}
}
}
3:棋盤列印函式的實作
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 1;
printf("---------------------------------\n");
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");//列印棋盤的坐標序號
for (i = 1; i <= row; i++)
{
printf("%d ", i);
int j = 1;
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
//棋盤陣列元素的定義
printf("------------------------------\n");
}
4:放置雷函式的實作
//這里來實作放置雷的功能
void SetMine(char board[ROWS][COLS], int row, int col)
{
int count =10;//總共放置10顆雷
while (count)
{
int x = rand() % row + 1;//讓電腦隨機生成一組x,y保證雷位置的隨機性
int y = rand() % col + 1;//因為整個陣列是11*11的所以中間有效區域是9*9下標是1到9
if (board[x][y] != '1')
{
board[x][y] = '1';
count--;
}
}
}
5:實作在show中排查后顯示位置的雷數
//統計周圍雷的個數
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{//因為在放置雷函式中放的是字符0和1所以雷數就等于周圍八個元素之和減8倍的'0'
return (mine[x - 1][y] + mine[x + 1][y] + mine[x][y - 1] + mine[x][y + 1]
+ mine[x - 1][y - 1] + mine[x - 1][y + 1] + mine[x + 1][y - 1] + mine[x + 1][y + 1]
- 8 * '0');
}
6:實作排雷函式
//這里來實作排查雷的功能
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int ret = row * col - 10;//有81個位置10個雷只有71個位置沒有放雷,如果71位置全排查完的獲勝
while (ret)
{
printf("請輸入你要排查的坐標");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= 9 && y >= 1 && y <= 9)
{
if (show[x][y] == '*')
{
if (mine[x][y] == '1')
{
printf("很遺憾!你被炸死了\n");
DisplayBoard(mine, ROW, COL);
break;
}
else {
OpenNOMine(mine, show, x, y);
DisplayBoard(show, ROW, COL);
}
}
else
{
printf("你輸入的位置已經被排查過,請重新輸入\n");
}
}
else
{
printf("你輸入的坐標超出范圍,請重新輸入\n");
}
}
if (ret == 0)
{
printf("恭喜你!排雷成功\n");
}
}
7:用遞回來實作打開一個空格展開一片
void OpenNOMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
int n=0;
n=GetMineCount(mine, x, y);
if (n == 0)
{
show[x][y] = ' ';//為防止出現死遞回的現象,將該位置變為空格
int i = 0;
for (i = x - 1; i <= x + 1; i++)
{
int j = 0;
for (j = y - 1; j <= y + 1; j++)
{
if (show[i][j] == '*'&&mine[i][j]=='0')//需滿足該位置沒有雷,且沒有被排查過
{
OpenNOMine(mine, show, i, j);//進行遞回
}
}
}
}
else {
show[x][y] =n+'0';
}
}
三:game.c的總代碼
#define _CRT_SECURE_NO_WARNINGS 1
#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;//這里的set存放的是0或*,方便測驗時兩個棋盤的列印
}
}
}
//這里實作棋盤的列印
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 1;
printf("---------------------------------\n");
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");//列印棋盤的坐標序號
for (i = 1; i <= row; i++)
{
printf("%d ", i);
int j = 1;
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 =10;//總共放置10顆雷
while (count)
{
int x = rand() % row + 1;//讓電腦隨機生成一組x,y保證雷位置的隨機性
int y = rand() % col + 1;//因為整個陣列是11*11的所以中間有效區域是9*9下標是1到9
if (board[x][y] != '1')
{
board[x][y] = '1';
count--;
}
}
}
//統計周圍雷的個數
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{//因為在放置雷函式中放的是字符0和1所以雷數就等于周圍八個元素之和減8倍的'0'
return (mine[x - 1][y] + mine[x + 1][y] + mine[x][y - 1] + mine[x][y + 1]
+ mine[x - 1][y - 1] + mine[x - 1][y + 1] + mine[x + 1][y - 1] + mine[x + 1][y + 1]
- 8 * '0');
}
//實作掃雷時,點開一個空白打開周圍一片的功能
void OpenNOMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
int n=0;
n=GetMineCount(mine, x, y);
if (n == 0)
{
show[x][y] = ' ';//為防止出現死遞回的現象,將該位置變為空格
int i = 0;
for (i = x - 1; i <= x + 1; i++)
{
int j = 0;
for (j = y - 1; j <= y + 1; j++)
{
if (show[i][j] == '*'&&mine[i][j]=='0')//需滿足該位置沒有雷,且沒有被排查過
{
OpenNOMine(mine, show, i, j);//進行遞回
}
}
}
}
else {
show[x][y] =n+'0';
}
}
//這里來實作排查雷的功能
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int ret = row * col - 10;//有81個位置10個雷只有71個位置沒有放雷,如果71位置全排查完的獲勝
while (ret)
{
printf("請輸入你要排查的坐標");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= 9 && y >= 1 && y <= 9)
{
if (show[x][y] == '*')
{
if (mine[x][y] == '1')
{
printf("很遺憾!你被炸死了\n");
DisplayBoard(mine, ROW, COL);
break;
}
else {
OpenNOMine(mine, show, x, y);
DisplayBoard(show, ROW, COL);
}
}
else
{
printf("你輸入的位置已經被排查過,請重新輸入\n");
}
}
else
{
printf("你輸入的坐標超出范圍,請重新輸入\n");
}
}
if (ret == 0)
{
printf("恭喜你!排雷成功\n");
}
}
由于本人是初學者,難免會出現錯誤,如有發現還望斧正,萬分感謝!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/292593.html
標籤:其他
下一篇:手游安全保護-基礎篇
