利用C語言實(shí)現(xiàn)簡易版掃雷
我和我的父親都是掃雷的狂熱粉,小時(shí)候我常常因?yàn)榧夹g(shù)不好而被父親嘲笑,那么今天我要來做一個(gè)簡易版掃雷,回頭也給他玩一玩。
首先我們要構(gòu)建好雷盤的樣子,我們理所當(dāng)然想到利用二維數(shù)組。那么請注意:因?yàn)槲覀兠恳淮坞S機(jī)生成的雷盤不能展示給用戶,所以顯示盤與雷盤要分開,那么我們在這里要用到兩個(gè)二維數(shù)組。一個(gè)是雷盤,用來記錄隨機(jī)生成雷的布局,另一個(gè)是顯示盤,初始化全為*,讓用戶來掃雷。

具體功能:
- 先由電腦隨機(jī)生成雷的分布。
- 玩家通過輸入坐標(biāo)來選擇點(diǎn)。
- 玩家選擇對應(yīng)點(diǎn)后,對應(yīng)點(diǎn)將顯示周圍雷的個(gè)數(shù)(以該點(diǎn)為中心的一個(gè)九宮格)。
- 玩家需要根據(jù)這個(gè)個(gè)數(shù),自己推斷出有雷的地方,不能輸入有雷的對應(yīng)坐標(biāo),只能輸入沒雷的對應(yīng)坐標(biāo)。
- 當(dāng)輸入坐標(biāo)對應(yīng)點(diǎn)有雷時(shí),炸“死”,游戲結(jié)束。當(dāng)剩下未選中的點(diǎn)的個(gè)數(shù)等于總共布下的雷的個(gè)數(shù)時(shí),游戲勝利。
實(shí)現(xiàn)功能的函數(shù):
1.菜單函數(shù),必不可少,是展示給用戶的第一界面,這個(gè)比較簡陋,后期可以考慮做一些fashion一點(diǎn)的。
void Menu()
{
printf("##########################\n");
printf("#####choose 1 to play#####\n");
printf("#####choose 0 to exit#####\n");
printf("Please input your select here:>\n");
}
2.隨機(jī)生成雷函數(shù),那么對應(yīng)雷的橫豎坐標(biāo)就是需要隨機(jī)生成的數(shù)。如果大家看過我之前的三子棋就知道,在這里關(guān)于隨機(jī)生成用到了函數(shù)GetIndex,算是一個(gè)小優(yōu)化。
void SetMine(char mine_board[][COL], int row, int col)
{
srand((unsigned long)time(NULL));
int mine_num = MINES;
while (mine_num)
{
int i_index = GetIndex(1,col-2);//生成1~10的隨機(jī)數(shù)
int j_index = GetIndex(1,col-2);
if (mine_board[i_index][j_index] == '0')
{
mine_board[i_index][j_index] = '1';
mine_num--;
}
}
}
3.GetIndex函數(shù),這里要注意start和end表示的是生成的隨機(jī)數(shù)的范圍。之前我們 如果用rand生成0~10的隨機(jī)數(shù),就直接rand%10,但是如果是5 ~10呢?所以我們用(end-start+1)得到的是0 ~end的范圍,再加一個(gè)start,就能到到start ~end的范圍。
static int GetIndex(int start, int end)//static修飾 代表該函數(shù)只能在本文件內(nèi)部使用
{
return rand() % (end - start + 1) + start;
}
4.得到一個(gè)點(diǎn)周圍雷的數(shù)量函數(shù),這里要注意,我寫的這個(gè)函數(shù)的返回值是整型,但得到的mine_board的和是字符型,那么要通過8-'0'來轉(zhuǎn)換一下。
int GetMineNum(char mine_board[][COL], int i, int j)
{
return mine_board[i-1][j-1]+mine_board[i-1][j]+ mine_board[i-1][j+1]+ \
mine_board[i][j-1]+ mine_board[i][j+1]+ \
mine_board[i+1][j-1]+mine_board[i+1][j]+ mine_board[i+1][j+1]-8*'0';//整型
}
5.顯示雷盤函數(shù)
void ShowBoard(char show_board[][COL], int row, int col)
{
int i = 0;
int j = 0;
printf(" ");
for (i = 1; i <= col-2; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= col - 1; i++)
{
printf("----");
}
printf("\n");
for (i = 1; i <=row - 2; i++)
{
printf("%-2d|", i);
for (j = 1; j <=col - 2; j++)
{
printf(" %c |", show_board[i][j]);
}
printf("\n");
int k = 1;
for (k = 1; k <= col - 1; k++)
{
printf("----");
}
printf("\n");
}
}
6.進(jìn)行游戲函數(shù),以total作為一個(gè)衡量標(biāo)準(zhǔn)。輸入坐標(biāo),判斷是否為雷的位置,是則游戲結(jié)束,不是則總的方塊數(shù)減1,繼續(xù)輸入坐標(biāo)。
void PlayGame(char show_board[][COL], char mine_board[][COL], int row, int col)
{
int i = 0;
int j = 0;
int total = (ROW - 2)*(COL - 2);
while (1)
{
ShowBoard(show_board, row, col);
printf("Please enter your pos<x,y>");
scanf("%d%d", &i, &j);
if (i >= 1 && i < row - 2 && j >= 1 && j < col - 2)
{
if (mine_board[i][j] == '0')
{
int num = GetMineNum(mine_board, i, j);
show_board[i][j] = num + '0';
total--;
}
else
{
ShowBoard(mine_board, row, col);
printf("Game over!you lose!:(\n");
break;
}
}
else
{
printf("Error!Try again!\n");
continue;
}
if (total == MINES)
{
printf("You win:)!\n");
break;
}
}
}
7.Game函數(shù),初始化兩個(gè)盤,主要調(diào)用了前面的函數(shù),對函數(shù)的一個(gè)整合,來貫穿一下整個(gè)流程。
void Game()
{
char show_board[ROW][COL];
char mine_board[ROW][COL];
memset(show_board, '*', sizeof(show_board));
memset(mine_board, '0', sizeof(mine_board));
SetMine(mine_board, ROW, COL);
PlayGame(show_board, mine_board, ROW, COL);
}
這里還是采用了文件的形式,分為函數(shù)聲明,函數(shù)定義,主函數(shù)。
函數(shù)聲明 Mine.h
#ifndef _MINE_H_ #define _MINE_H_ #include<stdio.h> #include<stdlib.h> #include<string.h> #include<time.h> #define ROW 12 #define COL 12 #define MINES 20 void Menu(); void Game(); int GetIndex(int start, int end); void SetMine(char mine_board[][COL], int row, int col); int GetMineNum(char mine_board[][COL], int i, int j); void ShowBoard(char show_board[][COL], int row, int col); void PlayGame(char show_board[][COL], char mine_board[][COL], int row, int col); #endif
函數(shù)定義 Mine.c
#include"Mine.h"
void Menu()
{
printf("##########################\n");
printf("#####choose 1 to play#####\n");
printf("#####choose 0 to exit#####\n");
printf("Please input your select here:>\n");
}
static int GetIndex(int start, int end)//static修飾 代表該函數(shù)只能在本文件內(nèi)部使用
{
return rand() % (end - start + 1) + start;
}
//隨機(jī)生成雷
void SetMine(char mine_board[][COL], int row, int col)
{
srand((unsigned long)time(NULL));
int mine_num = MINES;
while (mine_num)
{
int i_index = GetIndex(1,col-2);
int j_index = GetIndex(1,col-2);
if (mine_board[i_index][j_index] == '0')
{
mine_board[i_index][j_index] = '1';
mine_num--;
}
}
}
//得到一個(gè)點(diǎn)周圍雷的數(shù)量
int GetMineNum(char mine_board[][COL], int i, int j)
{
return mine_board[i-1][j-1]+mine_board[i-1][j]+ mine_board[i-1][j+1]+ \
mine_board[i][j-1]+ mine_board[i][j+1]+ \
mine_board[i+1][j-1]+mine_board[i+1][j]+ mine_board[i+1][j+1]-8*'0';//整型
}
//顯示雷盤
void ShowBoard(char show_board[][COL], int row, int col)
{
int i = 0;
int j = 0;
printf(" ");
for (i = 1; i <= col-2; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= col - 1; i++)
{
printf("----");
}
printf("\n");
for (i = 1; i <=row - 2; i++)
{
printf("%-2d|", i);
for (j = 1; j <=col - 2; j++)
{
printf(" %c |", show_board[i][j]);
}
printf("\n");
int k = 1;
for (k = 1; k <= col - 1; k++)
{
printf("----");
}
printf("\n");
}
}
void PlayGame(char show_board[][COL], char mine_board[][COL], int row, int col)
{
int i = 0;
int j = 0;
int total = (ROW - 2)*(COL - 2);
while (1)
{
ShowBoard(show_board, row, col);
printf("Please enter your pos<x,y>");
scanf("%d%d", &i, &j);
if (i >= 1 && i < row - 2 && j >= 1 && j < col - 2)
{
if (mine_board[i][j] == '0')
{
int num = GetMineNum(mine_board, i, j);
show_board[i][j] = num + '0';
total--;
}
else
{
ShowBoard(mine_board, row, col);
printf("Game over!you lose!:(\n");
break;
}
}
else
{
printf("Error!Try again!\n");
continue;
}
if (total == MINES)
{
printf("You win:)!\n");
break;
}
}
}
void Game()
{
char show_board[ROW][COL];
char mine_board[ROW][COL];
memset(show_board, '*', sizeof(show_board));
memset(mine_board, '0', sizeof(mine_board));
SetMine(mine_board, ROW, COL);
PlayGame(show_board, mine_board, ROW, COL);
}
主函數(shù) main.c
#include"Mine.h"
int main()
{
int select = 0;
int quit = 0;
while (!quit)
{
Menu();
scanf("%d", &select);
switch (select)
{
case 1:
Game();
break;
case 0:
printf("OK,byebye!\n");
quit = 1;
break;
default:
printf("Error!input again!\n");
break;
}
}
system("pause");
return 0;
}
運(yùn)行展示界面:


這是簡易版的掃雷,過過干癮還是可以,但和電腦里的掃雷還是有一定的差別,后期還要做一些優(yōu)化。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
c++ lambda捕獲this 導(dǎo)致多線程下類釋放后還在使用的錯(cuò)誤問題
Lambda表達(dá)式是現(xiàn)代C++的一個(gè)語法糖,挺好用的。但是如果使用不當(dāng),會導(dǎo)致內(nèi)存泄露或潛在的崩潰問題,這里總結(jié)下c++ lambda捕獲this 導(dǎo)致多線程下類釋放后還在使用的錯(cuò)誤問題,感興趣的朋友一起看看吧2023-02-02
c++11中關(guān)于std::thread的join的詳解
這篇文章主要介紹了c++11中關(guān)于std::thread的join詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03

