当前位置: 首页 > news >正文

简易版扫雷+代码分析

前言:

实验一个简易版的扫雷,也要两百来行的代码,因此为了代码整洁,维护起来方便,这里我们和前期实现的三子棋一样,也弄一个游戏的头文件game.h用来装各种头文件以及函数的声明以及宏定义、预处理信息,弄两个源文件,test.c用来作为主体代码,game.c用来实现具体函数。

首先是头文件:"game.h"

#pragma once
#pragma once#include <stdio.h>
#include <stdlib.h>
#include <time.h>#define ROW 9
#define COL 9#define ROWS ROW+2
#define COLS COL+2#define EASY_COUNT 10//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);//显示棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col);//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

用#difine 定义行数和列数,方便后期更改棋盘的大小,以及雷的个数count。

 

接着是实现游戏函数文件game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{int i = 0;int j = 0;for (i = 0; i < rows; i++){for (j = 0; j < cols; j++){board[i][j] = set;}}
}void DisplayBoard(char board[ROWS][COLS], int row, int col)
{int i = 0;int j = 0;printf("---------扫雷--------\n");for (i = 0; i <= col; i++){printf("%d ", i);}printf("\n");for (i = 1; i <= row; i++){printf("%d ", i);for (j = 1; j <= col; j++){printf("%c ", board[i][j]);}printf("\n");}printf("---------扫雷--------\n");
}void SetMine(char mine[ROWS][COLS], int row, int col)
{int count = EASY_COUNT;while (count){int x = rand() % row + 1;int y = rand() % col + 1;if (mine[x][y] == '0'){mine[x][y] = '1';count--;}}
}int GetMineCount(char mine[ROWS][COLS], int x, int y)
{/*return mine[x - 1][y] +mine[x - 1][y - 1] +mine[x][y - 1] +mine[x + 1][y - 1] +mine[x + 1][y] +mine[x + 1][y + 1] +mine[x][y + 1] +mine[x - 1][y + 1] - 8 * '0';*/int ret = 0;for (int i = x - 1; i <= x + 1; i++){for (int j = y - 1; j <= y + 1; j++){if (mine[i][j] == '1')ret++;}}return ret;
}void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{int x = 0;int y = 0;int win = 0;while (win < row * col - EASY_COUNT){printf("请输入要排查的坐标:>");scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col){if (mine[x][y] == '1'){printf("很遗憾,你被炸死了\n");DisplayBoard(mine, ROW, COL);break;}else{//不是雷,就统计x,y坐标周围有几个雷int c = GetMineCount(mine, x, y);show[x][y] = c + '0';DisplayBoard(show, ROW, COL);win++;}}else{printf("坐标非法,重新输入\n");}}if (win == row * col - EASY_COUNT){printf("恭喜你,排雷成功\n");DisplayBoard(mine, ROW, COL);}
}

在displayboard 的函数中,第一个循环和第二个循环的第一层都是为了把棋盘的坐标轴打印出来,方便玩家输入坐标,切记一点要换行。在记雷数的函数中,和之前写的一个扫雷编程题有点类似,这里你可以全部加一次,也可用循环一行行遍历得到。最后就是在找雷的函数中,因为是char类型的数组,你最终要将雷的数值转化为字符,所以这里又将'0'加上了c。

最后一个就是游戏的主体代码test.c

#define _CRT_SECURE_NO_WARNINGS 1#include "game.h"void menu()
{printf("***************************\n");printf("******  1. play     *******\n");printf("******  0. exit     *******\n");printf("***************************\n");
}void game()
{char mine[ROWS][COLS] = { 0 };char show[ROWS][COLS] = { 0 };InitBoard(mine, ROWS, COLS, '0');InitBoard(show, ROWS, COLS, '*');DisplayBoard(show, ROW, COL);//布置雷SetMine(mine, ROW, COL);//DisplayBoard(mine, ROW, COL);//排查雷FindMine(mine, show, ROW, COL);
}int main()
{srand((unsigned int)time(NULL));int input = 0;do{menu();printf("请选择>:");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("退出游戏\n");break;default:printf("选择错误,重新选择\n");break;}} while (input);return 0;
}

  和之前的三子棋代码实现类似,这个框架建议大家记下来,即先打印菜单,然后将输入的值作为判断条件放入while和switch中。这里之所以定义两个数组,主要还是方便计算雷数以及观感。开始还没进行游戏时,呈现的应该是全部为*的棋盘,

9e145f1d6ddb4a61a0451247b416fa77.png

最后,其实这也只是一个简易版的扫雷,因为实际扫雷游戏,当坐标附近无雷的时候,游戏会展开一片,函数比较难写,要用递归,还需判断边界这里不做阐述,有兴趣伙伴可以去试一下。

 

相关文章:

  • LuatOS-SOC接口文档(air780E)--pwm - PWM模块
  • Elasticsearch 聚合查询(Aggregation)详解
  • k8s中pod的hostport端口突然无法访问故障处理
  • ArcGIS中如何建立土地利用规划数据库
  • 【算法心得】When data range not large, try Bucket sort
  • 【Linux基础】Linux常见指令总结及周边小知识
  • 02-鸿蒙学习之4.0todoList练习
  • PTA: 螺旋矩阵
  • 计算机毕业设计 基于微信小程序的“共享书角”图书借还管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解
  • 9.Docker的虚悬镜像-Dangling Image
  • 爬虫爬取百度图片、搜狗图片
  • cocos2dx ​​Animate3D (一)
  • Java面试-微服务篇-SpringCloud
  • Python语言学习笔记之三(字符编码)
  • 独乐乐不如众乐乐(二)-某汽车零部件厂商IC EMC企业规范
  • crontab执行失败的多种原因
  • IIS 10 PHP CGI 设置 PHP_INI_SCAN_DIR
  • PHP变量
  • Vue.js-Day01
  • 关于 Cirru Editor 存储格式
  • 前言-如何学习区块链
  • 试着探索高并发下的系统架构面貌
  • ​ArcGIS Pro 如何批量删除字段
  • ​configparser --- 配置文件解析器​
  • ​HTTP与HTTPS:网络通信的安全卫士
  • ​iOS实时查看App运行日志
  • # Swust 12th acm 邀请赛# [ E ] 01 String [题解]
  • ###C语言程序设计-----C语言学习(6)#
  • #、%和$符号在OGNL表达式中经常出现
  • #pragma data_seg 共享数据区(转)
  • $GOPATH/go.mod exists but should not goland
  • (windows2012共享文件夹和防火墙设置
  • (附源码)spring boot公选课在线选课系统 毕业设计 142011
  • (附源码)springboot青少年公共卫生教育平台 毕业设计 643214
  • (简单) HDU 2612 Find a way,BFS。
  • (九)信息融合方式简介
  • (七)c52学习之旅-中断
  • (入门自用)--C++--抽象类--多态原理--虚表--1020
  • (一)基于IDEA的JAVA基础10
  • (转)Unity3DUnity3D在android下调试
  • (转)拼包函数及网络封包的异常处理(含代码)
  • *上位机的定义
  • ..thread“main“ com.fasterxml.jackson.databind.JsonMappingException: Jackson version is too old 2.3.1
  • .NET BackgroundWorker
  • .NET Reactor简单使用教程
  • .NET/C# 编译期间能确定的相同字符串,在运行期间是相同的实例
  • .Net环境下的缓存技术介绍
  • .net开源工作流引擎ccflow表单数据返回值Pop分组模式和表格模式对比
  • ::before和::after 常见的用法
  • @ModelAttribute 注解
  • @value 静态变量_Python彻底搞懂:变量、对象、赋值、引用、拷贝
  • [android] 切换界面的通用处理
  • [Angular] 笔记 9:list/detail 页面以及@Output
  • [BJDCTF2020]The mystery of ip
  • [BZOJ 1040] 骑士