当前位置:网站首页>扫雷pro版2021-08-19
扫雷pro版2021-08-19
2022-07-26 10:36:00 【竹某】
#1代码
//头文件 game.h
#pragma once
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <time.h>
struct oneGame {//一次游戏所需要的数据,game()中的任何子函数都是围绕它修改
char* mineField = NULL;//雷区数组,考虑到计算数字和展示,以及节约空间(防止内存泄漏),所以使用char*。为了简化计算,所以实际行列数目要+2。
//元素为'#',表示雷;元素为‘0’或‘1’,表示数字区。‘0’说明未被展开,‘1’说明已被展开。用于减少递归算法的开销。
char* sweptField = NULL;//已扫雷区数组,根据后续的函数决定使用什么数据类型。
int row = 0;//雷区行数
int col = 0;//雷区列数
int mines = 0;//需要雷的数目
int mineNum = 0;//剩余雷的数目
};
int menu(void);//游戏起始菜单,从外部输入模式,并将之返回
void game(int mode);//根据输入的游戏模式(int),进行一次游戏。
/*
game函数有两个部分:
1、根据形参mode,生成不同的雷区。generateMineField。
2、用户扫一次雷(x,y外部输入),根据不同的条件,产生不同的结果。sweepOnce
失败:本次扫到的是雷===》打印死亡信息;展示雷区;退出game()
正确:本次扫到的不是雷===》打印正确信息;计算本格的数字compute;以本格为中心展开expansion;返回循环开头要求输入
成功:本次正确且已扫完===》打印完成信息;展开已扫雷区;退出游戏
至少需要记录:
1、雷区(答案)(二维数组,雷的数目,雷的分布,雷区长,雷区宽)
2、已扫区域(可以展示给玩家看的)(扫过的区域)
*/
void generateMineField(oneGame*);//生成指定长,指定宽,指定雷数,雷随机分布的雷区;生成已扫雷区并初始化。
/*实现上:生成雷区并初始化--》生成已扫雷区并初始化。
*/
int sweepOnce(oneGame*);//一次扫雷,返回结果。-1为失败,1为成功,0为正确。
int compute(oneGame*, int, int );
//计算给定坐标处的数字(在不是雷的前提下),写入sweptField,同时返回之。
void expansion(oneGame*, int, int);
void display(char*, oneGame*);
//打印二维数组
//1.将设计思路转化为流程图
//2.根据流程图分析出函数和使用的数据(只是停留在功能的层面,没有考虑如何实现)
//3.考虑函数的实现,同时也可以考虑使用的数据该用什么方式进行存储(根据使用方式决定存储方式)
//4.实现函数,可能还需要设计子函数
//源文件game.cpp
#include "game.h"
int menu() {
int mode = 0;
printf("###################################\n");
printf("###########请选择游戏难度##########\n");
printf("###########1、初级难度#############\n");
printf("###########2、中级难度#############\n");
printf("###########3、高级难度#############\n");
printf("###########你的选择>: ");
scanf("%d", &mode);
while (getchar() != '\n')
;//不做任何事情,用于情况输入缓冲区
return mode;
}
void game(int mode) {
int isDead = 0;
oneGame thisGame;
//根据mode选择模式
if (mode == 1) {//初级模式
thisGame.col = thisGame.row = 9 + 2;
thisGame.mines = 2;
thisGame.mineNum = 2;
}
if (mode == 2) {//中级模式
thisGame.col = thisGame.row = 16 + 2;
thisGame.mines = 40;
thisGame.mineNum = 40;
}
if (mode == 3) {
thisGame.col = 30 + 2;
thisGame.row = 16 + 2;
thisGame.mines = 99;
thisGame.mineNum = 99;
}
generateMineField(&thisGame);
display(thisGame.sweptField,&thisGame);
//display(thisGame.mineField,&thisGame);
while (isDead == 0) {
isDead = sweepOnce(&thisGame);
}
free(thisGame.mineField);
free(thisGame.sweptField);
return;
}
void generateMineField(oneGame* thisGame) {
//初始化雷区和已扫雷区
thisGame->mineField = (char*)malloc(thisGame->col*thisGame->row);
thisGame->sweptField = (char*)malloc(thisGame->col*thisGame->row);
for (int i = 0; i < thisGame->col*thisGame->row; ++i) {
*(thisGame->mineField + i) = '0';
*(thisGame->sweptField + i) = '#';
}
for (int i = 0; i < thisGame->row - 2; ++i) {
for (int j = 0; j < thisGame->col - 2; ++j) {
*((thisGame->sweptField + thisGame->col + 1) + j + i * (thisGame->col)) = ' ';
}
}
//随机分布的雷,分布在雷区中间,四周没有
srand((unsigned long)time(NULL));
for (int i = 0; i < thisGame->mines;) {
int x = rand() % (thisGame->row - 2);
int y = rand() % (thisGame->col - 2);
if (*((thisGame->mineField + thisGame->col + 1) + y + x * (thisGame->col)) == '#') {
;//不干什么
}
else {
*((thisGame->mineField + thisGame->col + 1) + y + x * (thisGame->col)) = '#';
++i;
}
}
}
int sweepOnce(oneGame* thisGame) {
//要求输入
printf("输入坐标>: ");
int x = 0;
int y = 0;
int choice = 0;
scanf("%d%d%d", &x, &y, &choice);
while (getchar() != '\n')
;//不做任何事情,用于情况输入缓冲区
//如果错误/失败
if (choice == 0) {
if (*((thisGame->mineField + thisGame->col + 1) + y - 1 + (x - 1) * (thisGame->col)) == '#') {
printf("扫雷失败,游戏结束!\n");
display(thisGame->mineField, thisGame);
return -1;
}
//如果正确
if (*((thisGame->mineField + thisGame->col + 1) + y - 1 + (x - 1) * (thisGame->col)) != '#') {
printf("本次成功,继续游戏!\n");
compute(thisGame, x, y);
expansion(thisGame, x, y);
system("cls");
display(thisGame->sweptField, thisGame);
}
}
if (choice == 1) {
if (*((thisGame->mineField + thisGame->col + 1) + y - 1 + (x - 1) * (thisGame->col)) != '#') {
printf("扫雷失败,游戏结束!\n");
display(thisGame->mineField, thisGame);
return -1;
}
//如果正确
if (*((thisGame->mineField + thisGame->col + 1) + y - 1 + (x - 1) * (thisGame->col)) == '#') {
--thisGame->mineNum;
printf("本次成功,继续游戏!\n");
*((thisGame->sweptField + thisGame->col + 1) + y - 1 + (x - 1) * (thisGame->col)) = '#';
system("cls");
display(thisGame->sweptField, thisGame);
}
//如果成功
if (thisGame->mineNum == 0) {
printf("扫雷成功,游戏结束!\n");
display(thisGame->sweptField, thisGame);
return 1;
}
}
return 0;
}
int compute(oneGame* thisGame, int x, int y) {
int count = 0;
if (*((thisGame->mineField + thisGame->col + 1) + y - 1 + (x - 1) * (thisGame->col) + 1) == '#')
++count;
if (*((thisGame->mineField + thisGame->col + 1) + y - 1 + (x - 1) * (thisGame->col) - 1) == '#')
++count;
if (*((thisGame->mineField + thisGame->col + 1) + y - 1 + (x - 1) * (thisGame->col) + thisGame->col) == '#')
++count;
if (*((thisGame->mineField + thisGame->col + 1) + y - 1 + (x - 1) * (thisGame->col) - thisGame->col) == '#')
++count;
if (*((thisGame->mineField + thisGame->col + 1) + y - 1 + (x - 1) * (thisGame->col) + thisGame->col + 1) == '#')
++count;
if (*((thisGame->mineField + thisGame->col + 1) + y - 1 + (x - 1) * (thisGame->col) - thisGame->col + 1) == '#')
++count;
if (*((thisGame->mineField + thisGame->col + 1) + y - 1 + (x - 1) * (thisGame->col) + thisGame->col - 1) == '#')
++count;
if (*((thisGame->mineField + thisGame->col + 1) + y - 1 + (x - 1) * (thisGame->col) - thisGame->col - 1) == '#')
++count;
*((thisGame->sweptField + thisGame->col + 1) + y - 1 + (x - 1) * (thisGame->col)) = count + '0';
return count;
}
void expansion(oneGame* thisGame, int x,int y) {
*((thisGame->mineField + thisGame->col + 1) + y - 1 + (x - 1) * (thisGame->col)) = '1';
//使用递归算法导致栈溢出,所以进行了反复修改,加了很多条件,尽量减少空间复杂度
if (*((thisGame->mineField + thisGame->col + 1) + y - 1 + (x - 1) * (thisGame->col) + 1) != '#') {
if(*((thisGame->sweptField + thisGame->col + 1) + y - 1 + (x - 1) * (thisGame->col) + 1) != '#'){
if(*((thisGame->mineField + thisGame->col + 1) + y - 1 + (x - 1) * (thisGame->col) + 1) != '1')
if(compute(thisGame, x, y + 1) == 0)
expansion(thisGame, x, y + 1);
}
}
if (*((thisGame->mineField + thisGame->col + 1) + y - 1 + (x - 1) * (thisGame->col) - 1) != '#') {
if(*((thisGame->sweptField + thisGame->col + 1) + y - 1 + (x - 1) * (thisGame->col) - 1) != '#')
if(*((thisGame->mineField + thisGame->col + 1) + y - 1 + (x - 1) * (thisGame->col) - 1) != '1')
if(compute(thisGame, x, y - 1) == 0)
expansion(thisGame, x, y - 1);
}
if (*((thisGame->mineField + thisGame->col + 1) + y - 1 + (x - 1) * (thisGame->col) + thisGame->col) != '#') {
if(*((thisGame->sweptField + thisGame->col + 1) + y - 1 + (x - 1) * (thisGame->col) + thisGame->col) != '#')
if(*((thisGame->mineField + thisGame->col + 1) + y - 1 + (x - 1) * (thisGame->col) + thisGame->col) != '1')
if(compute(thisGame, x + 1, y) == 0)
expansion(thisGame, x + 1, y);
}
if (*((thisGame->mineField + thisGame->col + 1) + y - 1 + (x - 1) * (thisGame->col) - thisGame->col) != '#') {
if(*((thisGame->sweptField + thisGame->col + 1) + y - 1 + (x - 1) * (thisGame->col) - thisGame->col) != '#')
if(*((thisGame->mineField + thisGame->col + 1) + y - 1 + (x - 1) * (thisGame->col) - thisGame->col) != '1')
if(compute(thisGame, x - 1, y) == 0)
expansion(thisGame, x - 1, y);
}
return;
}
void display(char* thisArray,oneGame* thisGame){
for (int i = 0; i < thisGame->col - 1; ++i) {
printf("%2d ", i);
}
printf("\n");
for (int i = 0; i < thisGame->row - 2; ++i) {
printf("%2d ", i + 1);
for (int j = 0; j < thisGame->col - 2; ++j) {
printf("%2c ", *((thisArray + thisGame->col + 1) + j + i * (thisGame->col)));
}
printf("\n");
}
}
//主函数test.cpp
#include "game.h"
int main() {
int choice = 0;
again:
int mode = menu();
game(mode);
printf("#########你想再完一把吗?\n");
printf("#########1.再玩一把\n");
printf("#########0.不玩了\n");
printf("你的选择>: ");
scanf("%d",&choice);
while (getchar() != '\n')
;//不做任何事情,用于情况输入缓冲区
if (choice == 0)
;//不做任何事情
else
goto again;
return 0;
}
#2游戏规则
按照提示进入游戏。之后输入x y choice。x代表横坐标,y代表纵坐标,choice表示选择(1表示此处有雷,0表示此处没有雷)。容错机制没有做,谨慎输入。
边栏推荐
- 将json文件中数组转换为struct
- Redis special data type usage scenarios
- Issue 5: the second essential skill for College Students
- [leetcode每日一题2021/2/13]448. 找到所有数组中消失的数字
- Redis docker instance and data structure
- 从蚂蚁的觅食过程看团队研发(转载)
- STM32 Alibaba cloud mqtt esp8266 at command
- Dry goods likeshop takeout order system is open source, 100% open source, no encryption
- 剑指Offer(二十):包含min函数的栈
- Introduction to data analysis | kaggle Titanic mission (I) - > data loading and preliminary observation
猜你喜欢
centos8(liunx)部署WTM(ASP.NET 5)使用pgsql
MLX90640 红外热成像仪测温传感器模块开发笔记(六)红外图像伪彩色编码
[Halcon vision] threshold segmentation
【论文下饭】Deep Mining External Imperfect Data for ChestX-ray Disease Screening
[leetcode每日一题2021/2/14]765. 情侣牵手
Navicat15 MySQL (centos7) connected to local virtual machine
第6期:大学生应该选择哪种主流编程语言
Comparison of packet capturing tools fiddler and Wireshark
【机器学习小记】【搭建循环神经网络及其应用】deeplearning.ai course5 1st week programming(keras)
【机器学习小记】【人脸识别】deeplearning.ai course4 4th week programming
随机推荐
.NET操作Redis String字符串
canvas上传图片base64-有裁剪功能-Jcrop.js
工厂模式详解
Redis implementation of distributed lock solution
Redis docker instance and data structure
Database functions
[转]ArcGIS中判断两个Geometry之间的关系
[leetcode每日一题2021/4/23]368. 最大整除子集
Parallelism, concurrency and several directions for high concurrency optimization
QRcode二维码(C语言)遇到的问题
Controller返回JSON数据
Navicat15 MySQL (centos7) connected to local virtual machine
Uninstall Meizu app store
JS对象赋值问题
【机器学习小记】【人脸识别】deeplearning.ai course4 4th week programming
剑指Offer(九):变态跳台阶
[leetcode每日一题2021/2/18]【详解】995. K 连续位的最小翻转次数
干货likeshop外卖点餐系统开源啦100%开源无加密
[leetcode每日一题2021/2/13]448. 找到所有数组中消失的数字
剑指Offer(十):矩形覆盖