目錄
前言
一.實作該小游戲應注意的重要知識點
1.首先就是要會使用陣列與函式
2.一定會用遞回去實作展開
二.游戲的實作思路
三.游戲主體的實作
1.游戲選單的實作
2.主函式的實作
3.game()函式實作,完成了游戲主體實作
4.游戲的各種函式實作(最重要的地方)
四.掃雷小游戲全部代碼
1.game.h
2.game.c
3.test.c
五.掃雷小游戲運行實況
前言
hello哇,又一次和大家見面了,這次帶來的是小游戲——掃雷,此掃雷,并不能像我們正常游玩一樣,只需要用滑鼠點就可以,也不可以立flag,畢竟我們還是一個C語言的初學者哇,我們要一點點的學習進步,等到了那一層次,那么我們也一定可以做出一個真正像樣的掃雷小游戲的,
掃雷的實作和上一篇的三子棋比較相似,也采用模塊化的思想,建議先看完上一篇三子棋后再來學習這一篇掃雷,同時,上一篇的一些重復的內容在這一篇就簡略帶過了,
好了,話不多說,現在就開始實作掃雷小游戲啦,
一.實作該小游戲應注意的重要知識點
1.首先就是要會使用陣列與函式
陣列與函式的知識在之前都有介紹,在這就先不說啦,
2.一定會用遞回去實作展開
要想實作可以向四周展開,那么我們最好的辦法就是采用遞回,遞回對于我們一個初學者來說,具有一定的難度,但我們一定要吃透它,遞回是一個很重要的知識點,大家可以看看我之前(通過遞回實作【漢諾塔】和【青蛙跳臺階】的問題),以加深對遞回的理解,
二.游戲的實作思路
1.首先要想多次玩這個游戲,應該創建一個選單,并放入do while回圈中,
2.要想實作一個掃雷游戲,我們一定要能熟練的使用陣列和函式,我們如果創建一個棋盤,那么我們把雷放上去之后,玩家都能看到了,那就沒有任何的可玩性了,所以既然創建一個不行,那就再來一個,我們創建兩個棋盤,一個用來我們內部實作的,存放一些雷,而另一個則是展現在玩家眼前的,
3.然后創建完,就應該放置一些雷在內部陣列中,
4.最后,就是最關鍵的一步“掃雷”,我們應該在這里完成坐標的輸入,對雷的排查,每排查一個雷所展現在玩家眼前不同的棋盤,以及踩到雷或是掃雷成功的提示與演算法實作,
5.存放方式
game.h存放頭檔案,宏定義,函式宣告
game.c用來實作函式
test.c用于該游戲的整體實作,是該游戲的測驗
三.游戲主體的實作
1.游戲選單的實作
void menu()
{
printf("**************************\n");
printf("******* 1.play *******\n");
printf("******* 0.exit *******\n");
printf("**************************\n");
}
2.主函式的實作
void test()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("請選擇:>");
scanf("%d", &input);
switch(input)
{
case 1:
game();
break;
case 0:
printf("退出游戲\n");
break;
default:
printf("選擇錯誤,請重新選擇\n");
}
} while (input);
}
int main()
{
test();
return 0;
}
1,2這兩步與三子棋幾乎一樣,
3.game()函式實作,完成了游戲主體實作
宏定義了ROW COL
ROWS=ROW+2,COLS=COL+2
void game()
{
//創建布置雷的資訊的陣列(內部,不給玩家看)
char mine[ROWS][COLS] = { 0 };
//創建排查雷的資訊的陣列(外部,給玩家看的)
char show[ROWS][COLS] = { 0 };
//初始化棋盤
InitBoard(mine, ROWS, COLS, '0');//把內部全部初始化為0
InitBoard(show, ROWS, COLS, '*');//把外部全部初始化為*
//DisplayBoard(mine, ROW, COL);(列印這個棋盤可以自己除錯用,但不給玩家看)
//DisplayBoard(show, ROW, COL);
//布置雷
SetMine(mine, ROW, COL);
//列印棋盤(想要列印中間的9*9的棋盤,但傳過去的是11*11的整個陣列)
DisplayBoard(show, ROW, COL);
//排查雷
FineMine(mine, show, ROW, COL);
}
4.游戲的各種函式實作(最重要的地方)
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
//列印列號,因為在之前列印了個行號,所以讓第一列是0,但得多列印一行,
//所以前面i=0,后面i<=row
for (i = 0; i <= row; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
//列印行號
printf("%d ", i);
//列印棋盤
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
void SetMine(char mine[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
static int get_mine_count(char mine[ROWS][COLS], int x, int y)
{
return mine[x - 1][y - 1] +
mine[x - 1][y] +
mine[x - 1][y + 1] +
mine[x][y - 1] +
mine[x][y + 1] +
mine[x + 1][y - 1] +
mine[x + 1][y] +
mine[x + 1][y + 1] -
8 * '0';
}
void open_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
int count = get_mine_count(mine, x, y);
if (count == 0)
{
show[x][y] = ' ';
if (show[x - 1][y - 1] == '*')
open_mine(mine, show, x - 1, y - 1);
if (show[x - 1][y] == '*')
open_mine(mine, show, x - 1, y);
if (show[x - 1][y + 1] == '*')
open_mine(mine, show, x - 1, y + 1);
if (show[x][y - 1] == '*')
open_mine(mine, show, x, y - 1);
if (show[x][y + 1] == '*')
open_mine(mine, show, x, y + 1);
if (show[x + 1][y - 1] == '*')
open_mine(mine, show, x + 1, y - 1);
if (show[x + 1][y] == '*')
open_mine(mine, show, x + 1, y);
if (show[x + 1][y + 1] == '*')
open_mine(mine, show, x + 1, y + 1);
}
else
show[x][y] = get_mine_count(mine, x, y) + '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("請輸入要排查雷的坐標:>");
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 = get_mine_count(mine, x, y);
//show[x][y] = count + '0';//使用遞回后不需要這兩個了,在open_mine中實作了這些功能
open_mine(mine, show, x, y);//如果輸入坐標附近無雷,則向四周展開直到遇到雷
DisplayBoard(show, ROW, COL);//每次排雷后再次列印棋盤
win++;
}
}
else
{
printf("坐標非法,請重新輸入\n");
}
}
if (win == row * col - EASY_COUNT)
{
printf("恭喜你,排雷成功\n");
DisplayBoard(mine, row, col);
}
}
上面的是使用遞回實作之后的,如果不想實作展開,那么可以修改如下代碼(洗掉open_mine,同時將上面我注釋掉的給解除注釋):
//將這個open_mine的函式全部內容洗掉
void open_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
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("請輸入要排查雷的坐標:>");
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 = get_mine_count(mine, x, y);
show[x][y] = count + '0';//使用上面這兩個
//open_mine(mine, show, x, y);//刪去改函式的一切
DisplayBoard(show, ROW, COL);//每次排雷后再次列印棋盤
win++;
}
}
else
{
printf("坐標非法,請重新輸入\n");
}
}
if (win == row * col - EASY_COUNT)
{
printf("恭喜你,排雷成功\n");
DisplayBoard(mine, row, col);
}
}
四.掃雷小游戲全部代碼
1.game.h
#pragma once
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define EASY_COUNT 10
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//初始化棋盤
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
//列印棋盤
void DisplayBoard(char board[ROWS][COLS], int row, int col); //傳過來的是整個陣列,用ROWS和COLS接收
//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col);
//排查雷
void FineMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
2.game.c
#include "game.h"
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
//列印列號,因為在之前列印了個行號,所以讓第一列是0,但得多列印一行,
//所以前面i=0,后面i<=row
for (i = 0; i <= row; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
//列印行號
printf("%d ", i);
//列印棋盤
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
void SetMine(char mine[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
static int get_mine_count(char mine[ROWS][COLS], int x, int y)
{
return mine[x - 1][y - 1] +
mine[x - 1][y] +
mine[x - 1][y + 1] +
mine[x][y - 1] +
mine[x][y + 1] +
mine[x + 1][y - 1] +
mine[x + 1][y] +
mine[x + 1][y + 1] -
8 * '0';
}
void open_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
int count = get_mine_count(mine, x, y);
if (count == 0)
{
show[x][y] = ' ';
if (show[x - 1][y - 1] == '*')
open_mine(mine, show, x - 1, y - 1);
if (show[x - 1][y] == '*')
open_mine(mine, show, x - 1, y);
if (show[x - 1][y + 1] == '*')
open_mine(mine, show, x - 1, y + 1);
if (show[x][y - 1] == '*')
open_mine(mine, show, x, y - 1);
if (show[x][y + 1] == '*')
open_mine(mine, show, x, y + 1);
if (show[x + 1][y - 1] == '*')
open_mine(mine, show, x + 1, y - 1);
if (show[x + 1][y] == '*')
open_mine(mine, show, x + 1, y);
if (show[x + 1][y + 1] == '*')
open_mine(mine, show, x + 1, y + 1);
}
else
show[x][y] = get_mine_count(mine, x, y) + '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("請輸入要排查雷的坐標:>");
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
{
open_mine(mine, show, x, y);//如果輸入坐標附近無雷,則向四周展開直到遇到雷
DisplayBoard(show, ROW, COL);//每次排雷后再次列印棋盤
win++;
}
}
else
{
printf("坐標非法,請重新輸入\n");
}
}
if (win == row * col - EASY_COUNT)
{
printf("恭喜你,排雷成功\n");
DisplayBoard(mine, row, col);
}
}
3.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] = { 0 };
//創建排查雷的資訊的陣列(外部,給玩家看的)
char show[ROWS][COLS] = { 0 };
//初始化棋盤
InitBoard(mine, ROWS, COLS, '0');//把內部全部初始化為0
InitBoard(show, ROWS, COLS, '*');//把外部全部初始化為*
//布置雷
SetMine(mine, ROW, COL);
//列印棋盤(想要列印中間的9*9的棋盤,但傳過去的是11*11的整個陣列)
DisplayBoard(show, ROW, COL);
//排查雷
FineMine(mine, show, ROW, COL);
}
void test()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("請選擇:>");
scanf("%d", &input);
switch(input)
{
case 1:
game();
break;
case 0:
printf("退出游戲\n");
break;
default:
printf("選擇錯誤,請重新選擇\n");
}
} while (input);
}
int main()
{
test();
return 0;
}
五.掃雷小游戲運行實況


這被炸死了可不是我菜奧,這是為了給大家展示踩雷的效果 ,

好了,本篇掃雷就到此結束了啦,希望大家都可以在這每一個代碼中逐漸成長,直到成為一個大佬的那天,
最后的最后呢,還是求個贊啦,謝謝大家啦,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/356852.html
標籤:其他
下一篇:做個掃雷玩玩唄
