文接上一篇博文C語言:三子棋小游戲。本篇博文是使用C語言來實現(xiàn)掃雷小游戲的。這里不對掃雷的規(guī)則進行贅述。玩家通過鍵盤輸入坐標來探雷。博主在實現(xiàn)掃雷之前從未看過掃雷實現(xiàn)的相關視頻,所以這里實現(xiàn)的掃雷完全是博主的原生思路,具有邏輯性。下面詳細介紹一下如何實現(xiàn)掃雷。
(建議在閱讀過上一篇博文再閱讀本文,因為再本文中對重復的問題不會再次解讀。)
步驟一:制定框架
框架是什么?如何制定框架?這些問題在三子棋的實現(xiàn)中就已經(jīng)解答了,這里也不多講。這里的框架與三子棋的框架完全相同。
#include"detect.h"
int main()
{
srand((unsigned)time(NULL));//這里設置了隨機種子,為了之后隨機生成雷
int n = 0;
do
{
menu();
printf("your choice:\n");
scanf("%d", &n);
switch (n)
{
case 1:
system("cls");
game();
break;
case 0:
system("cls");
printf("exit game\n");
break;
default:
printf("input error,again:\n");
Sleep(1000);
system("cls");
}
} while (n);
return 0;
}
menu是什么在三子棋實現(xiàn)中也提過,這里使用了Sleep函數(shù)(程序暫停運行多少毫秒)和system("cls")(清屏)是為了更好的游戲體驗。這里的detect.h代碼如下:
#pragma once
#define ROW 10
#define COL 10
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
void menu();
void game();
步驟二:實現(xiàn)game函數(shù)
跟三子棋的game函數(shù)一樣,我們需要事先想好整個game的流程。
分析過程:既然有雷,我們需要將雷的位置記錄下來,那我們就需要一個字符二維數(shù)組,雷用大寫字符'O'表示,雷的位置就初始化為'O',其他位置為空格。另外,開局時我們一個地方都沒探測,我們難道要將帶雷的數(shù)組直接打印上去嗎?顯然這樣雷就直接被打印出來了。我們可以想到用第二個字符二維數(shù)組,里面初始時全是空格字符,這個數(shù)組是用來打印的。我們在這個數(shù)組中進行探測。
結束條件:如果探的是雷,那么直接宣告失敗,結束本次游戲;如果這一次避開了所有的雷,那么直接宣告成功,結束本次游戲;如果這一次沒探到雷而且沒有結束,那么顯示此處旁邊雷的個數(shù)
那我們怎么知道探出的是不是雷?其實很簡單,在數(shù)組一中此處如果是雷,說明這次探到雷了
下面是game的代碼
void game()
{
char map1[ROW][COL] = { 0 };
char map2[ROW][COL] = { 0 };
mapInit(map1, ROW, COL);//真正存儲炸彈
mapInit(map2, ROW, COL);//用來打印
BoomInit(map1, ROW, COL);
system("cls");
showMap(map2, ROW, COL);
while (1)
{
int ret=playerMove(map1, map2, ROW, COL,ROW*COL/8);
if (ret==1)//炸了
{
system("cls");
showMap(map1, ROW, COL);
printf("game over\n");
system("pause");
break;
}
else if (ret== 2)//排除了所有炸彈
{
system("cls");
showMap(map1, ROW, COL);//展示所有炸彈位置
printf("detect successfully\n");
Sleep(2000);
break;
}
system("cls");
showMap(map2, ROW, COL);
}
}
當然只是代碼還是很模糊的,下面依然需要對game中的各個部分進行講解。
map1:即數(shù)組一,用來存放炸彈的
map2:即數(shù)組二,用來打印的
ROW,COL:宏定義,這個宏定義在"detect.h"中,之前已經(jīng)給出
mapInit:用來初始化兩個數(shù)組,將兩個數(shù)組的每一個元素變成空格字符
BoomInit:用來將map1的隨機位置放上炸彈
showMap:將map2打印出來(連帶格子的線條,之后會詳細實現(xiàn))
playerMove:返回值為int類型,玩家在map2中的一個位置進行探測,如果在map1中相應位置是炸彈就返回1,避開所有炸彈就返回2,其他情況返回0;
?步驟三:實現(xiàn)game中的函數(shù)
?
?
void mapInit(char map[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
map[i][j] = ' ';
}
}
}//這個函數(shù)很簡單,不作講解
void BoomInit(char map[ROW][COL], int row, int col)
{
int boomNum = row * col / 6;//6分之一是炸彈
//設置炸彈進map
int curNum = 0;
int x = 0;
int y = 0;
while (curNum != boomNum)
{
x = rand() % row;
y = rand() % col;
if (map[x][y] == ' ')//如果是空格才能正常放入,如果已經(jīng)是炸彈就不放,重新生成一個坐標
{
map[x][y] = 'O';
curNum++;
}
}
}
void showMap(char map[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf(" %c ", map[i][j]);
if (j < col - 1)
printf("|");
}
printf("\n");
if (i < row - 1)
{
for (int x = 0; x < col; x++)
{
printf("---");
if (x < col - 1)
printf("|");
}
printf("\n");
}//這一段其實是將畫格子線和棋子一并畫出,
//需要自己動手操作一下才能明白這段代碼每一句是在做什么
//不動手再怎么講都不會弄明白
}
}
//warning函數(shù)是為了完成playerMove函數(shù)而寫的,請先看playerMove函數(shù)
char warning(char map[ROW][COL], int row, int col, int x, int y)
{
int countBoom = 0;//最大為8,加上'0'變成字符
for (int i = x - 1; i <= x + 1;i++)
{
for (int j = y - 1; j <= y + 1; j++)
{
if (i >= 0 && i <= row && j >= 0 && j <= col)//越界了就不判斷是不是雷
{
if (map[i][j] == 'O')
countBoom++;
}
}
}
return countBoom +'0';
}
int playerMove(char map1[ROW][COL],char map2[ROW][COL], int row, int col,int boomNum)
{
int x = 0;
int y = 0;
static count = 0;//靜態(tài)局部變量,記錄用戶一共開了幾個格子
while (1)
{
printf("input x:\n");
scanf("%d", &x);
printf("input y:\n");
scanf("%d", &y);
x--;
y--;//用戶輸入的1就是第一個位置,數(shù)組下標就是0
if (x < 0 || x >= row || y < 0 || y >= col || map2[x][y] != ' ')
{
printf("wrong place,again\n");//非法坐標,重新輸入
}
else
{
break;//合法,退出循環(huán)
}
}
//如果探到雷了,map2的該位置就改成'O',沒探到雷就顯示旁邊有幾個雷
//這里的warning函數(shù)就是用來給出map1的相應位置旁邊有幾個雷,返回值是char類型
map2[x][y] = map1[x][y]=='O'?'O':warning(map1,ROW,COL,x,y);
if (map2[x][y] == 'O')
return 1;//探到雷了,返回1
else//判斷是否排除完
{
count++;
if (count == col * row - boomNum)
{
count = 0;//歸零,下一次進行游戲count還是從0開始計數(shù),否則count還是之前的值
return 2;//避開了所有的雷,返回2
}
}
return 0;//正常進行下一次探測,返回0
}
?
?
?到這里為止,所有的工作就完成了,我們來看看效果文章來源:http://www.zghlxwxcb.cn/news/detail-708676.html
測試:
?配合清屏和睡眠函數(shù)效果還是不錯的,只是和原版的掃雷少了一個功能。我們知道,原版的掃雷在探到一個格子旁邊沒有一個炸彈時,也就這里實現(xiàn)的掃雷顯示'0'時,會自動將旁邊的格子顯示出來,只是這個功能實現(xiàn)起來有點困難。當時想過用遞歸解決這個問題,就是說如果map2中探到一個0雷格,將旁邊八個格子打開,如果這八個格子還有0雷格,就會進行遞歸,繼續(xù)將旁邊的格子打開,只是這樣會有一個問題,0雷格挨在一起的話會陷入死遞歸。個人感覺這個問題使用遞歸是最好解決的,之后想到了解決方案會更新博文。文章來源地址http://www.zghlxwxcb.cn/news/detail-708676.html
到了這里,關于C語言:掃雷小游戲的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!