扫雷超级超级详细讲解:
- 一:第一步菜单函数
- 二:主函数创建
- 三:游戏函数的实现
-
-
- 1.创建初始化地图
- 2.打印地图
- 3.玩家输入,电脑校验
- 4.判断胜负
- 5.打印地雷数函数
- 6.循环实现
- 7.循环最终判定
-
- 四:源代码
提到扫雷,我们每个人都会有自己的记忆,今天我来用C语言写一个简易版的扫雷。我会站在一个比较基础的角度去分析问题,让我们一起看看扫雷的完整步骤吧!
要想做一个简单的小游戏,我们首先会考虑到如何让用户看到我们的游戏,如何操作,所以我们先做一个简单的游戏交互菜单吧!
我们首先写一个菜单函数menu:
一:第一步菜单函数
int menu(){
int choice = 0;
printf("****************\n");
printf("**1.play********\n");
printf("**2.quit********\n");
printf("****************\n");
printf("输入你的选择:\n");
scanf("%d", &choice);
return choice;
}
当我们的菜单函数创建完成了,我们就要考虑main函数的创建了,main函数是我们的最基础(在这里我们可以将最开始创建的菜单函数的分支选择语句写道这里面)。
二:主函数创建
int main(){
while (1){
int choice = menu();
if (choice == 1){
game();
}
else if (choice == 2){
printf("bye\n");
break;
}
else{ printf("输入错误\n");
}
}
system("pause");
return 0;
}
看到我们的选择语句了吗?是不是有一个game函数,这就是我们接下来的任务了!这才是主要的游戏编写!
但是如何写一个游戏呢?
最重要的是先有思路,我们先把思路清晰,然后在根据我们列出的步骤来写代码!这样才是适合新手的方案!
三:游戏函数的实现
注意: 思路比具体的代码更重要.
1 . 创建地图并初始化. (两个地图,一个给用户看,一个给自己埋雷用)
2 . 打印地图(向用户展示基本的游戏界面)
3 . 程序读取玩家输入的要翻开位置的坐标, 并校验(电脑判断玩家下的棋子位置在自己埋雷的地图中是什么!)
4 . 判定该位置的坐标是否是地雷. 如果是地雷, 直接 GameOver
5 . 如果不是地雷, 统计当前位置周围雷的个数, 并显示到地图上.(就是扫雷的基本规则,一个地方周围的八个地方有没有雷子!)
6 . 然后循环以上步骤直到满足下一个条件7!
7 . 判定游戏是否胜利!(核心逻辑应该是判断当前是不是把所有不是雷的位置都翻开了。)
1.创建初始化地图
首先我们做第一步:创建初始化地图(2个)
void init(char showmap[MAX_ROW][MAX_COL],
char minemap[MAX_ROW][MAX_COL]){
for (int row = 0; row < MAX_ROW; row++){
for (int col = 0; col < MAX_COL; col++){
showmap[row][col] = ' *';
}
}
for (int row = 0; row < MAX_ROW; row++){
for (int col = 0; col < MAX_COL; col++){
minemap[row][col] = '0';
}
}
int n=DEFAULT_MINE_COUNT ;//10个雷子数!!!!
while (n>0){
int row = rand() % MAX_ROW;
int col = rand() % MAX_COL;
if (minemap[row][col] == 1){
continue;
}
minemap[row][col] ='1';
n--;
}
}
注意我为了方便,用宏定义来写了9行9列10雷!
#define MAX_ROW 9
#define MAX_COL 9
#define DEFAULT_MINE_COUNT 10
其中一个都是*** 这个是给玩家看的,一个是全为0,然后用rand函数赋值10个1作为雷子!
rand函数就是一个简单的伪随机数函数(我的其他博客有详细介绍!)
2.打印地图
- 打印地图(向用户展示基本的游戏界面)
这个步骤是我们打印棋盘的函数,每一次下棋都会更新!
void printmap(char themap[MAX_ROW][MAX_COL]){
printf(" |");
for (int col = 0; col < MAX_COL; col++){
printf("%d ", col);
}
printf("\n");
printf("--+------------------\n");
for (int row = 0; row < MAX_ROW; row++){
printf(" %d|",row);
for (int col = 0; col < MAX_COL; col++){
printf(" %c", themap[row][col]);
}
printf("\n");
}
}
3.玩家输入,电脑校验
- 程序读取玩家输入的要翻开位置的坐标, 并校验(电脑判断玩家下的棋子位置在自己埋雷的地图中是什么!)
注意:这里不是函数!!你先看得懂就好了,最后我们一起总结在game函数里!!
int row = 0;
int col = 0;
printf("请输入你的坐标:");
scanf("%d %d", &row, &col);
if (row < 0 || row >= MAX_ROW || col < 0 || col >= MAX_COL){
continue;
}
if (showmap[row][col] !='*'){
continue;
}
4.判断胜负
- 判定该位置的坐标是否是地雷. 如果是地雷, 直接 GameOver
为了让玩家死得明白,我们在死前帮助他打印一边地图!!注意是minemap(真正的地雷地图!!!)
if (minemap[row][col] == '1'){
printf("你输了!\n");
break;
}
5.打印地雷数函数
- 如果不是地雷, 统计当前位置周围雷的个数, 并显示到地图上.(就是扫雷的基本规则,一个地方周围的八个地方有没有雷子!)
这个函数比较复杂,我们用+1 ,-1的小二层循环镶嵌来表示的周围的地雷,也就是遍历周围的8个格子是不是地雷!!!!
int updateshowmap(char showmap[MAX_ROW][MAX_COL] ,
char minemap[MAX_ROW][MAX_COL],int row,int col ){
int count = 0;
for (int R = row - 1; R <= row + 1; R++){
for (int C = col - 1; C <= col + 1; C++){
if (minemap[R][C] == '1'){
count++;
}
if (R < 0 || R >= MAX_ROW
|| C < 0 || C >= MAX_COL) {
continue;
}
}
}
showmap[row][col] = count + '0';
}
6.循环实现
- 然后循环以上步骤直到满足下一个条件7!
这一步在game函数中简单的就可以解决,先省略。。看下来的game函数!!!
7.循环最终判定
- 判定游戏是否胜利!(核心逻辑应该是判断当前是不是把所有不是雷的位置都翻开了。)
if (count == MAX_ROW * MAX_COL - DEFAULT_MINE_COUNT) {
printf("游戏胜利!\n");
printmap(minemap);
break;
};
走到这里你是不是看懂了呢?只需最后一步我们把game函数总结起来,你就会豁然开朗!!!!
注意我们有一个检验正确性的辅助方法,就是打印我们的正确地图,记得让你朋友试试的时候删掉!!
printmap(minemap);
printf("=================================\n");//辅助
如下:
void game(){
char showmap[MAX_ROW][MAX_COL] = { 0 };
char minemap[MAX_ROW][MAX_COL] = { 0 };
init(showmap, minemap);
int count = 0;
while (1){
printmap(minemap);
printf("=================================\n");//辅助
printmap(showmap);
int row = 0;
int col = 0;
printf("请输入你的坐标:");
scanf("%d %d", &row, &col);
if (row < 0 || row >= MAX_ROW || col < 0 || col >= MAX_COL){
continue;
}
if (showmap[row][col] !='*'){
continue;
}
if (minemap[row][col] == '1'){
printf("你输了!\n");
break;
}
updateshowmap(showmap, minemap, row, col);
count++;
if (count == MAX_ROW * MAX_COL - DEFAULT_MINE_COUNT) {
printf("游戏胜利!\n");
printmap(minemap);
break;
}
}
}
所有的函数都被我们整合在了game里面!是不是很简单!!!
四:源代码
下面我把完整的源代码写在这里,你可以直接复制试一试!
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define MAX_ROW 9
#define MAX_COL 9
#define DEFAULT_MINE_COUNT 10
int menu(){
int choice = 0;
printf("****************\n");
printf("**1.play********\n");
printf("**2.quit********\n");
printf("****************\n");
printf("输入你的选择:\n");
scanf("%d", &choice);
return choice;
}
void init(char showmap[MAX_ROW][MAX_COL],
char minemap[MAX_ROW][MAX_COL]){
for (int row = 0; row < MAX_ROW; row++){
for (int col = 0; col < MAX_COL; col++){
showmap[row][col] = ' *';
}
}
for (int row = 0; row < MAX_ROW; row++){
for (int col = 0; col < MAX_COL; col++){
minemap[row][col] = '0';
}
}
int n=DEFAULT_MINE_COUNT ;
while (n>0){
int row = rand() % MAX_ROW;
int col = rand() % MAX_COL;
if (minemap[row][col] == 1){
continue;
}
minemap[row][col] ='1';
n--;
}
}
void printmap(char themap[MAX_ROW][MAX_COL]){
printf(" |");
for (int col = 0; col < MAX_COL; col++){
printf("%d ", col);
}
printf("\n");
printf("--+------------------\n");
for (int row = 0; row < MAX_ROW; row++){
printf(" %d|",row);
for (int col = 0; col < MAX_COL; col++){
printf(" %c", themap[row][col]);
}
printf("\n");
}
}
int updateshowmap(char showmap[MAX_ROW][MAX_COL] ,
char minemap[MAX_ROW][MAX_COL],int row,int col ){
int count = 0;
for (int R = row - 1; R <= row + 1; R++){
for (int C = col - 1; C <= col + 1; C++){
if (minemap[R][C] == '1'){
count++;
}
if (R < 0 || R >= MAX_ROW
|| C < 0 || C >= MAX_COL) {
continue;
}
}
}
showmap[row][col] = count + '0';
}
void game(){
char showmap[MAX_ROW][MAX_COL] = { 0 };
char minemap[MAX_ROW][MAX_COL] = { 0 };
init(showmap, minemap);
int count = 0;
while (1){
printmap(minemap);
printf("=================================\n");//辅助
printmap(showmap);
int row = 0;
int col = 0;
printf("请输入你的坐标:");
scanf("%d %d", &row, &col);
if (row < 0 || row >= MAX_ROW || col < 0 || col >= MAX_COL){
continue;
}
if (showmap[row][col] !='*'){
continue;
}
if (minemap[row][col] == '1'){
printf("你输了!\n");
break;
}
updateshowmap(showmap, minemap, row, col);
count++;
if (count == MAX_ROW * MAX_COL - DEFAULT_MINE_COUNT) {
printf("游戏胜利!\n");
printmap(minemap);
break;
}
}
}
int main(){
while (1){
int choice = menu();
if (choice == 1){
game();
}
else if (choice == 2){
printf("bye\n");
break;
}
else{ printf("输入错误\n");
}
}
system("pause");
return 0;
}