(我们接上次扫雷练习继续去讲)
##前情提要##
之前已经留了个悬念
想实现插旗,领域展开,计时,难度选择四个功能
经过我结合互联网知识,写出了扫雷升级版,接下来我就来讲解我如何实现的
一、插旗子
1.我们先规定:输入坐标后再输入“F”或者是“f,是执行插旗子操作,输入“C”或者是“c,则进行排查雷操作
##示例输入:5 5 F←插旗子,6 6 C←排雷
2.我们还规定:假设这个地方已经插了旗子,你可以通过再输入“F”或者“f”来取消插旗,这样就恢复了棋盘最开始的“*”
3.当你输入“C”或者“c”执行排雷后,我们开始正常的排雷函数实现,这里不再赘述
二、计时
1.我们在开始游戏时候先记录下此刻的时间,我们再查找地雷函数中调用clock函数来计算时钟滴答数。
2.开始时我们记录一次,被雷炸死或者游戏胜利我们记录一次,我们再用double类型的双精度浮点型来计算时间差除上double类型的一秒钟的时钟周期来计算耗时多少秒,打印出来即可,在打印棋盘进行展示供玩家观看自己的胜利或者是失败原因
三、领域展开
1.前提是我们输入的坐标不是雷,没有被炸死
2.在排查雷函数中我们调用领域展开函数
3.在领域展开函数中,我们要判断这个坐标是不是在棋盘的范围内
4.在展开区域过程中,我们要判断这个地方到底是不是未知区域(即是不是“*”),如果不是未知区域我们就return返回不执行下面的代码
5.不满足第四个条件我们再来判断这个地方是不是雷,如果是雷我们也用return返回,下面代码不再执行,这样为后续递归如果是雷不至于被炸死,毕竟这个是系统自己的领域展开,而不是玩家的操作,因此如果是雷我们就略过这个区域
6.如果上述两点均未被执行,我们就可以执行领域展开函数,调用统计周围雷的数量的函数,借用“__?__:__”判别式来判断周围雷的数量是否为0,如果是0,就不用在当前区域存储雷数量,维持原样的字符'0'样式。而如果存在雷,则我们在统计完雷数量后再加上字符'0',存放在供玩家展示的棋盘中,展示雷的数量
7.假设周围雷的数量确定是0,我们展开周围区域,利用for循环在当前坐标位置周围9x9位置进行展开,不能展开中心区域(即当前x,y坐标位置),在循环的时候我们利用if函数判断这个地方是不是中心区域,如果是利用continue跳过本轮循环,否则我们进行递归函数,以上全部操作再重复执行,直到限制条件为止
四、选择难度
##由于这个地方难度很大,我还没学习,等以后学习了动态内存分配再来解释,这里就不多解释,我这里就是让AI帮我实现了想法
当然如果你会,你可以在讨论区告诉我或者给我推荐好文章,我会积极去学习的
五、代码展示
game.h函数声明头文件
#pragma once
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#include <time.h>
// 定义难度相关的宏
#define EASY_ROW 5
#define EASY_COL 5
#define EASY_TRUECOUNT 5
#define MEDIUM_ROW 8
#define MEDIUM_COL 8
#define MEDIUM_TRUECOUNT 15
#define HARD_ROW 10
#define HARD_COL 10
#define HARD_TRUECOUNT 30
// 定义默认难度
#define DEFAULT_ROW 9
#define DEFAULT_COL 9
#define DEFAULT_TRUECOUNT 10
// 声明全局变量
extern int selected_row;
extern int selected_col;
extern int selected_truecount;
// 函数声明
void arr(char** arr, int x, int y, char set);
void printfarr(char** arr, int x, int y);
void setarrmine(char** brr, int r, int c);
int countmine(char** crr, int x, int y);
void expand_area(char** mine, char** show, int x, int y);
void findarrmine(char** mine, char** show, int r, int c);
void select_difficulty();
game.c函数定义文件
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
// 初始化数组函数
void arr(char** arr, int x, int y, char set)
{
for (int i = 0; i < x; i++)
{
for (int q = 0; q < y; q++)
{
arr[i][q] = set;
}
}
}
// 打印数组函数
void printfarr(char** arr, int x, int y)
{
printf("------扫雷精简版-----\n");
for (int i = 0; i <= y; i++)
{
printf("%d ", i);
}
printf("\n");
for (int i = 1; i <= x; i++)
{
printf("%d ", i);
for (int q = 1; q <= y; q++)
{
printf("%c ", arr[i][q]);
}
printf("\n");
}
}
// 设置地雷函数
void setarrmine(char** brr, int r, int c)
{
int count = selected_truecount;
while (count) {
int x = rand() % r + 1;
int y = rand() % c + 1;
if (brr[x][y] == '0')
{
brr[x][y] = '1';
count--;
}
}
}
// 计算周围地雷数量函数
int countmine(char** crr, int x, int y)
{
int c = 0;
for (int i = -1; i <= 1; i++)
{
for (int q = -1; q <= 1; q++)
{
if (crr[x + i][y + q] == '1')
{
c++;
}
}
}
return c;
}
// 递归展开周围不是雷的区域
void expand_area(char** mine, char** show, int x, int y)
{
if (x < 1 || x > selected_row || y < 1 || y > selected_col)
return;
if (show[x][y] != '*')
return;
if (mine[x][y] == '1')
return;
int count = countmine(mine, x, y);
show[x][y] = count == 0 ? '0' : count + '0';
if (count == 0)
{
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
if (i == 0 && j == 0)
continue;
expand_area(mine, show, x + i, y + j);
}
}
}
}
// 查找地雷函数
void findarrmine(char** mine, char** show, int r, int c)
{
int x = 0,y = 0;
int win = 0;
char operation;
clock_t start_time = clock();
while (win < r * c - selected_truecount)
{
printf("请输入排查坐标及操作(F插旗/C排雷): ");
scanf("%d %d %c", &x, &y, &operation);
if (x > 0 && x <= r && y > 0 && y <= c)
{
if (operation == 'F' || operation == 'f')
{
if (show[x][y] == '*')
{
show[x][y] = 'F';
}
else if (show[x][y] == 'F')
{
show[x][y] = '*';
}
printfarr(show, r, c);
}
else if (operation == 'C' || operation == 'c')
{
if (mine[x][y] == '1')
{
printf("游戏结束\n");
printfarr(mine, r, c);
clock_t end_time = clock();
double duration = (end_time - start_time) / (double)CLOCKS_PER_SEC;
printf("游戏用时:%.2f 秒\n", duration);
break;
}
else
{
expand_area(mine, show, x, y);
printfarr(show, r, c);
win++;
}
}
}
else
{
printf("坐标非法,重新输入\n");
}
}
if (win == r * c - selected_truecount)
{
printf("恭喜你排雷成功\n");
printfarr(mine, r, c);
clock_t end_time = clock();
double duration = (end_time - start_time) / (double)CLOCKS_PER_SEC;
printf("游戏用时:%.2f 秒\n", duration);
}
}
try.c游戏主体文件
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
char operation; // 用于存储用户操作的全局变量
// 定义全局变量
int selected_row = DEFAULT_ROW;
int selected_col = DEFAULT_COL;
int selected_truecount = DEFAULT_TRUECOUNT;
// 菜单函数
void menu()
{
printf("----扫雷 精简版----\n");
printf("----1. 开始 ----\n");
printf("----2. 选择难度 ----\n");
printf("----0. 退出 ----\n");
printf("------------------\n");
}
// 游戏函数
void game()
{
// 动态分配内存
char** arrmine = (char**)malloc((selected_row + 2) * sizeof(char*));
for (int i = 0; i < selected_row + 2; i++)
{
arrmine[i] = (char*)malloc((selected_col + 2) * sizeof(char));
}
char** arrshow = (char**)malloc((selected_row + 2) * sizeof(char*));
for (int i = 0; i < selected_row + 2; i++)
{
arrshow[i] = (char*)malloc((selected_col + 2) * sizeof(char));
}
arr(arrmine, selected_row + 2, selected_col + 2, '0');
arr(arrshow, selected_row + 2, selected_col + 2, '*');
printfarr(arrshow, selected_row, selected_col);
setarrmine(arrmine, selected_row, selected_col);
findarrmine(arrmine, arrshow, selected_row, selected_col);
// 释放内存
for (int i = 0; i < selected_row + 2; i++)
{
free(arrmine[i]);
free(arrshow[i]);
}
free(arrmine);
free(arrshow);
}
// 难度选择函数
void select_difficulty()
{
int diff;
printf("请选择难度:\n");
printf("1. 简单\n");
printf("2. 中等\n");
printf("3. 困难\n");
scanf("%d", &diff);
switch (diff)
{
case 1:
selected_row = EASY_ROW;
selected_col = EASY_COL;
selected_truecount = EASY_TRUECOUNT;
break;
case 2:
selected_row = MEDIUM_ROW;
selected_col = MEDIUM_COL;
selected_truecount = MEDIUM_TRUECOUNT;
break;
case 3:
selected_row = HARD_ROW;
selected_col = HARD_COL;
selected_truecount = HARD_TRUECOUNT;
break;
default:
printf("无效的选择,使用默认难度。\n");
selected_row = DEFAULT_ROW;
selected_col = DEFAULT_COL;
selected_truecount = DEFAULT_TRUECOUNT;
}
}
// 主函数
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do {
printf("扫雷游戏加载中...\n");
Sleep(1000);
int sign = 1;
while (sign <= 3)
{
printf(".");
Sleep(1000);
sign++;
}
printf("\n");
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 2:
select_difficulty();
break;
case 0:
printf("您已退出");
break;
default:
printf("请重新选择");
break;
}
} while (input);
return 0;
}
此文章仅代表作者个人观点,如果你有更好意见,欢迎讨论
END
发布者:admin,转转请注明出处:http://www.yc00.com/web/1754416075a5156790.html
评论列表(0条)