引言:
扫雷拓展版已经制作完成,约为400-500行代码即可实现,但代码的详解还在制作中,为什么要先发这篇博客呢,因为如果直接看扫雷拓展版的话可能会看不懂,所以先提前告知一下,还有提前把源码发出来,有助于你们的个人理解,然后再通过我的博客来理解,可能更容易理解透彻
所以:如果想要看明天的扫雷拓展版的教程的话,可以先去看一下基础版的教程(拓展版是基于基础版代码进行改造的,不看基础版可能看代码会有落差)
这是基础版扫雷的教程链接:C语言制作扫雷游戏(基础版赋源码)-CSDN博客
拓展版详解教程已发布,链接:C语言制作扫雷游戏(拓展版赋源码)-CSDN博客
那么我先讲一下拓展版新增的功能吧

新增功能:
扫雷拓展版已经制作完成,基于基础版新增了3个功能
1.难度选择
新增了可以选择难度的功能,分为简单,中等,困难和自定义,如图

2. 标记点
可以对你觉得是雷的点进行标记," ! " 为确定有雷," ? " 为不确定是否有雷,但感觉可能是雷,被标记的点无法进行排雷,这样可以防止排雷时一不小心把你知道的雷排了,如图


3.取消标记点
可以对已经被标记的点进行取消标记,如图


注:若选择的是标记和取消标记,会一直重复,直到选择排雷,这就跟扫雷时候一样,你可以一直标点不扫雷,点击后,再进行扫雷判断
4.排雷的展开(涉及dfs)
基础版的时候,我们都是选一个坐标,返回那个坐标附近有几个雷,并不会展开,而拓展版里,实现了展开,如图


功能与网页版区别
网页版与该拓展版的功能基本基本没有差别
唯一的差别就是网页版有游玩时间的计时,而拓展版没有(计时涉及知识点过多,就没实现)
源代码
那么,最后,我先把源代码发出来,可以复制过去一直玩玩看,如果觉得可以的话并且想知道怎么实现的,可以来看明天博客哟
记得看基础版博客C语言制作扫雷游戏(基础版赋源码)-CSDN博客
game.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
#define EChang 9//好处是,想更改棋盘大小时候直接改这里就好了,不用在程序里一个个改,方便很多
#define EKuan 9
#define MChang 16
#define MKuan 16
#define HChang 30
#define HKuan 16
#define EChangs EChang+2
#define EKuans EKuan+2
#define MChangs MChang+2
#define MKuans MKuan+2
#define HChangs HChang+2
#define HKuans HKuan+2
#define ELeisum 10
#define MLeisum 40
#define HLeisum 99
void chu(char arr[][100], int hang, int lie, char fu);
void print(char arr[][100], int lie, int hang);
void set(char arr[][100], int hang, int lie, int ge);
void Findlei(char yin[][100], char xian[][100], int lie, int hang, int leisum);
game.c
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
//初始化棋盘
void chu(char arr[][100],int hang,int lie,char fu)
{
for (int i = 0; i < hang; i++)
{
for (int j = 0; j < lie; j++)
arr[i][j] = fu;
}
}
//打印棋盘
void print(char arr[][100], int hang, int lie)
{
for (int i = 0; i <= lie; i++)
printf("%2d ", i);
printf("\n");
for (int i = 1; i <= hang; i++)
{
printf("%2d ", i);
for (int j = 1; j <= lie; j++)
printf("%2c ", arr[i][j]);
printf("\n");
}
}
//布置雷
void set(char arr[][100],int hang,int lie,int ge)
{
while (ge--)
{
int h = 1 + rand() % hang;
int l = 1 + rand() % lie;
if (arr[h][l] == '0')
{
arr[h][l] = '1';
}
else
ge++;
}
}
static void Choose()
{
printf("******************\n");
printf("*** 1.标记 ***\n");
printf("*** 2.取消标记 ***\n");
printf("*** 0.排雷 ***\n");
printf("******************\n");
}
static void menubiao()
{
printf("*********************\n");
printf("**** 1.?(不确定) ****\n");
printf("**** 2.!(肯定) ****\n");
printf("*********************\n");
}
//标记雷
void Biaolei(char arr[][100],int hang,int lie)
{
int x = 0, y = 0;
int type = 0;
while (1)
{
printf("请输入要标记的坐标:");
scanf("%d %d", &x, &y);
if (x<1 || x>hang || y<1 || y>lie)
{
printf("输入的坐标有误,请重新输入\n");
continue;
}
else if (arr[x][y] == '?' || arr[x][y] == '!')
{
printf("该位置已被标记,请重新输入\n");
continue;
}
else if (arr[x][y] != '*')
{
printf("该坐标已被排查,无法标记,请重新输入\n");
continue;
}
break;
}
menubiao();
do
{
printf("请输入要标记的类型:");
scanf("%d", &type);
if (type != 1 && type != 2)
{
printf("不存在该选项,请重新输入\n");
continue;
}
break;
} while (1);
switch (type)
{
case 1:
arr[x][y] = '?';
print(arr, hang, lie);
break;
case 2:
arr[x][y] = '!';
print(arr, hang, lie);
break;
}
}
//取消标记雷
void Clearlei(char arr[][100], int hang, int lie)
{
int x = 0, y = 0;
int type = 0;
while (1)
{
printf("请输入要取消标记的坐标:");
scanf("%d %d", &x, &y);
if (x<1 || x>hang || y<1 || y>lie)
{
printf("输入的坐标有误,请重新输入\n");
continue;
}
else if (arr[x][y] != '?' && arr[x][y] != '!')
{
printf("该位置未被标记,请重新输入\n");
continue;
}
break;
}
arr[x][y] = '*';
print(arr, hang, lie);
}
//展开
bool vis[100][100];
int fang[8][2] = { {0,1},{0,-1},{-1,0},{1,0},{1,1},{1,-1},{-1,1},{-1,-1} };
void zhanlei(char yin[][100], char xian[][100], int hang, int lie, int x, int y, int* ge)
{
if (xian[x][y] != '0')
return;
for (int i = 0; i < 8; i++)
{
int x1 = x + fang[i][0];
int y1 = y + fang[i][1];
if (!vis[x1][y1] && yin[x1][y1] != '1' && x1 >= 1 && x1 <= hang && y1 >= 1 && y1 <= lie)
{
(*ge)++;
xian[x1][y1] = '0';
vis[x1][y1] = 1;
for (int i = 0; i < 8; i++)
{
if (yin[x1 + fang[i][0]][y1 + fang[i][1]] == '1')
xian[x1][y1]++;
}
zhanlei(yin, xian, hang, lie, x1, y1, ge);
}
}
}
//排查雷
void Findlei(char yin[][100], char xian[][100], int hang, int lie,int leisum)
{
int x = 0, y = 0;
int ge = 0;
int biaoji = 0;
int input = 0;
while (1)
{
do
{
system("cls");
print(xian, hang, lie);
Choose();
printf("请选择:");
scanf("%d", &input);
if (input != 1 && input != 2 && input != 0)
{
printf("输入有误,请重新输入\n");
}
if (biaoji >= leisum && input == 1)
{
printf("标记个数已超出雷数,请重新选择\n");
continue;
}
if (biaoji <= 0 && input == 2)
{
printf("已经没有可以取消标记的点了,请重新选择\n");
continue;
}
switch (input)
{
case 1:
Biaolei(xian, hang, lie);
biaoji++;
break;
case 2:
Clearlei(xian, hang, lie);
biaoji--;
break;
default:
break;
}
} while (input);
do
{
printf("请输入要排查的坐标(行 列):");
scanf("%d %d", &x, &y);
if (x<1 || x>hang || y<1 || y>lie)
{
printf("输入的坐标有误,请重新输入\n");
continue;
}
else if (xian[x][y] == '?' || xian[x][y] == '!')
{
printf("该位置已被标记,请重新输入\n");
continue;
}
else if (xian[x][y] != '*')
{
printf("该坐标已排查过,请重新输入\n");
continue;
}
break;
} while (1);
if (yin[x][y] == '1')
{
system("cls");
printf("很遗憾,你被炸死了,游戏结束\n");
print(yin, hang, lie);
break;
}
else
{
xian[x][y] = '0';
vis[x][y] = 1;
for (int i = 0; i < 8; i++)
{
if (yin[x + fang[i][0]][y + fang[i][1]] == '1')
xian[x][y]++;
}
ge++;
if(xian[x][y]=='0')
zhanlei(yin, xian, hang, lie, x, y, &ge);
system("cls");
print(xian, hang, lie);
if (ge + leisum == hang * lie)
{
system("cls");
print(yin, hang, lie);
printf("恭喜你,排雷成功\n");
break;
}
}
}
}
扫雷.c
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
void menu()
{
printf("********************\n");
printf("***** 1.play *****\n");
printf("***** 0.exit *****\n");
printf("********************\n");
}
void Lelve()
{
printf("************************\n");
printf("*** 1.easy(9*9 10) ***\n");
printf("*** 2.mid(16*16 40) ***\n");
printf("*** 3.hard(30*16 99) ***\n");
printf("*** 4.自定义 ***\n");
printf("************************\n");
}
void game()
{
//初始化函数
int input = 0;
int chang = 0, kuan = 0, lei = 0;
Lelve();
printf("请选择:");
do
{
scanf("%d", &input);
if (input < 1 || input>4)
{
printf("输入有误,请重新输入:");
continue;
}
break;
} while (1);
char cun[100][100] = { 0 };
char show[100][100] = { 0 };
switch (input)
{
case 1:
chu(cun, EKuans, EChangs, '0');
chu(show, EKuans, EChangs, '*');
//布置雷
set(cun, EKuan, EChang, ELeisum);
//打印棋盘
print(show, EKuan, EChang);
//排查雷,标记雷
Findlei(cun, show, EKuan, EChang, ELeisum);
break;
case 2:
chu(cun, MKuans, MChangs, '0');
chu(show, MKuans, MChangs, '*');
//布置雷
set(cun, MKuan, MChang, MLeisum);
//打印棋盘
print(show, MKuan, MChang);
//排查雷
Findlei(cun, show, MKuan, MChang, MLeisum);
break;
case 3:
chu(cun, HKuans, HChangs, '0');
chu(show, HKuans, HChangs, '*');
//布置雷
set(cun, HKuan, HChang, HLeisum);
//打印棋盘
print(show, HKuan, HChang);
//排查雷
Findlei(cun, show, HKuan, HChang, HLeisum);
break;
case 4:
printf("请输入长度 宽度 雷的个数(长<=50 宽<=16 雷数<长*宽)\n");//过大控制台太小,屏幕会乱跳,不好操控
do
{
scanf("%d %d %d", &chang, &kuan, &lei);
if (chang > 50 || chang < 1 || kuan>50 || kuan < 1 || chang * kuan <= lei)
{
printf("输入有误,请重新输入:");
continue;
}
break;
} while (1);
chu(cun, kuan+2, chang+2, '0');
chu(show, kuan+2, chang+2, '*');
//布置雷
set(cun, kuan, chang, lei);
//打印棋盘
print(show, kuan, chang);
//排查雷
Findlei(cun, show, kuan, chang, lei);
break;
}
}
void test()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
system("cls");
printf("游戏开始\n");
game();
break;
case 0:
system("cls");
printf("欢迎下次游玩\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
结语:
敬请期待吧

&spm=1001.2101.3001.5002&articleId=151191365&d=1&t=3&u=c17bd189e5e647028952f6ec912d128e)
441

被折叠的 条评论
为什么被折叠?



