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

C语言数组练习--扫雷

一.游戏规则

扫雷的基本规则

  1. 点击方格,如果是地雷,游戏失败;找到所有方格而不踩到地雷则游戏胜利。
  2. 左键翻开方格,右键标记地雷。
  3. 双击左键(或者左右键一起点)可以看到数字的可点击范围。
  4. 数字表示周围有几个雷,例如“2”周围有两个雷。

基于对规则的分析,我们对于代码的实现有了一点点小的思路:

1.要有棋盘的打印

2.扫雷游戏要存储布置好的雷的信息,需要一个二维数组

3.预计以9*9的数组为例,需要2个二维数组,一个存放雷的信息(10个雷)(mine数组),一个存放布置好的雷的信息(show数组)。

4.考虑到排查雷的时候是看其周围八个里面存在几个雷,为了防止统计统计坐标周围的雷的个数的时候越界,我们设计为11*11(以9*9的数组为例,浅绿色为显示的9*9数组,深绿色为我们加入的边框,当统计雷的时候,统计到四个角以及边框时会出现数组越界的情况,为了避免此情况的出现,我们采用了11*11数组)

 

二.代码实现

我们依旧采取分模块编写程序代码

test.c:测试游戏的代码

game.c:游戏实现代码

game.h:游戏函数的声明

三.具体代码详解

3.1 游戏进出及界面的实现

定义menu()函数完成菜单界面的编写

//开始界面,进入时的菜单
void menu()
{printf("*******************************\n");printf("************1. play ***********\n");printf("************0. exit ***********\n");printf("*******************************\n");
}

 

 在main()函数中,用do…while循环实现菜单使用,switch语句进行菜单选择

这点利用 input 这个变量,当用户输入 1 进行开始游戏时,input 值为1,同时switch语句中也依据 input 为1还是为0来进行判断。

int main()
{int input = 0;srand((unsigned int)time(NULL));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;
}

3.2 棋盘创建与打印

棋盘的创建,我们在此并没有把棋盘的初始化函数InitBoard()写死(只能用什么符号并没有非常固定),我们添加了一个set参数,想传什么参可以自己来定义。

//创建棋盘
//添加了一个set参数,自己确认想初始化的参数
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{int i = 0;for (i = 0; i < rows; i++){int j = 0;for (j = 0; j < cols; j++){board[i][j] = set;}}
}

 棋盘的打印:为了避免玩家在输入坐标时出错,我们给行和列添加了序号

//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{int  i = 0;printf("--------扫雷游戏-------\n");//给行标数for (i = 0; i <= col; i++){printf("%d ", i);}printf("\n");for (i = 1; i <= row; i++){printf("%d ", i);int j = 0;for (j = 1; j <= col; j++){printf("%c ", board[i][j]);}printf("\n");}
}

 

3.3 布置雷函数SetMine()

在game.c文件中实现布置雷函数,设置随机雷数EASY_COUNT,进入while循环每设置一个雷,EASY_COUNT减一,直到雷设置完毕跳出循环。为保证雷的随机性需生成随机坐标,判断设置雷是否重复,未重复设置雷”1“

void SetMine(char board[ROWS][COLS], int row, int col)
{//布置10个雷//生成随机的坐标,布置雷int count = EASY_COUNT;while (count){int x = rand() % row + 1;int y = rand() % col + 1;if (board[x][y] == '0'){board[x][y] = '1';count--;}}
}

3.4 排查雷函数FindMine()

玩家输入坐标后,首先确保坐标在棋盘范围内(否则重新输入),其次判断棋盘范围内坐标是否重复输入,未重复输入判断是否踩雷。

用GetMineCount函数统计周围雷个数

若踩雷”很遗憾炸死“,放入while循环,若雷没有排查完持续循环,若被炸死跳出循环。若所有雷被排查出则排雷成功。

 int GetMineCount()

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');
}

 FindMine()

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{//该位置不是雷,就统计这个坐标周围有几个雷int count = GetMineCount(mine, x, y);show[x][y] = count + '0';DisplayBoard(show, ROW, COL);win++;}}else{printf("坐标非法,重新输入\n");}}if (win == row * col - EASY_COUNT){printf("恭喜你,排雷成功\n");DisplayBoard(mine, ROW, COL);}
}

3.5 代码运行结果部分展示

排到雷

 

未排到雷

游戏结束可以选择是否要重新开始

 

3.6 所有源码

test.c:测试游戏的代码

#include "game.h"//开始界面,进入时的菜单
void menu()
{printf("*******************************\n");printf("************1. play ***********\n");printf("************0. exit ***********\n");printf("*******************************\n");
}void game()
{char mine[ROWS][COLS];//存放布置好的雷char show[ROWS][COLS];//存放排查出的雷的信息//初始化棋盘//1. mine数组最开始是全'0'//2. show数组最开始是全'*'InitBoard(mine, ROWS, COLS, '0');InitBoard(show, ROWS, COLS, '*');//打印棋盘//只需要打印show数组,存放雷的数组不需要打印//DisplayBoard(mine, ROW, COL);DisplayBoard(show, ROW, COL);//1. 布置雷SetMine(mine, ROW, COL);//DisplayBoard(mine, ROW, COL);//2. 排查雷FindMine(mine, show, ROW, COL);
}int main()
{int input = 0;srand((unsigned int)time(NULL));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;
}

game.c:游戏实现代码

#include "game.h"//创建棋盘
//添加了一个set参数,自己确认想初始化的参数
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{int i = 0;for (i = 0; i < rows; i++){int j = 0;for (j = 0; j < cols; j++){board[i][j] = set;}}
}//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{int  i = 0;printf("--------扫雷游戏-------\n");//给行标数for (i = 0; i <= col; i++){printf("%d ", i);}printf("\n");for (i = 1; i <= row; i++){printf("%d ", i);int j = 0;for (j = 1; j <= col; j++){printf("%c ", board[i][j]);}printf("\n");}
}void SetMine(char board[ROWS][COLS], int row, int col)
{//布置10个雷//生成随机的坐标,布置雷int count = EASY_COUNT;while (count){int x = rand() % row + 1;int y = rand() % col + 1;if (board[x][y] == '0'){board[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');
}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{//该位置不是雷,就统计这个坐标周围有几个雷int count = GetMineCount(mine, x, y);show[x][y] = count + '0';DisplayBoard(show, ROW, COL);win++;}}else{printf("坐标非法,重新输入\n");}}if (win == row * col - EASY_COUNT){printf("恭喜你,排雷成功\n");DisplayBoard(mine, ROW, COL);}
}

game.h:游戏函数的声明

#include<stdio.h>
#include <stdlib.h>
#include <time.h>#define EASY_COUNT 10#define ROW 9
#define COL 9
//为了打印方便,我们只需要打印9*9,儿不需要打印11*11
#define ROWS ROW+2
#define COLS COL+2//初始化棋盘
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 board[ROWS][COLS], int row, int col);//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【目标检测】Yolo5基本使用
  • 【SQL 新手教程 1/20】SQL语言MySQL数据库 简介
  • 为什么 OPC UA 很重要
  • Redis与缓存
  • go-kratos 学习笔记(8) redis的使用
  • OpenCV 图像基础
  • 养宠空气净化器哪家好?养宠空气净化器质量好的牌子推荐
  • Ubuntu一键导入openVPN配置文件
  • PHP多功能投票系统源码小程序
  • 用来跳转的<a> 标签,原来还有这么多强大又实用的功能
  • 通信原理-思科实验五:家庭终端以太网接入Internet实验
  • 征服 Docker 镜像访问限制:KubeSphere v3.4.1 成功部署全攻略
  • 【Redis进阶】集群
  • cf960(div2)
  • Gogs搭建免费好用的Git服务器
  • 【comparator, comparable】小总结
  • C++入门教程(10):for 语句
  • Django 博客开发教程 16 - 统计文章阅读量
  • GDB 调试 Mysql 实战(三)优先队列排序算法中的行记录长度统计是怎么来的(上)...
  • Idea+maven+scala构建包并在spark on yarn 运行
  • Java多线程(4):使用线程池执行定时任务
  • react-core-image-upload 一款轻量级图片上传裁剪插件
  • 互联网大裁员:Java程序员失工作,焉知不能进ali?
  • 技术:超级实用的电脑小技巧
  • 你真的知道 == 和 equals 的区别吗?
  • 手写双向链表LinkedList的几个常用功能
  • Unity3D - 异步加载游戏场景与异步加载游戏资源进度条 ...
  • ​LeetCode解法汇总1276. 不浪费原料的汉堡制作方案
  • ### RabbitMQ五种工作模式:
  • (1)安装hadoop之虚拟机准备(配置IP与主机名)
  • (1)常见O(n^2)排序算法解析
  • (5)STL算法之复制
  • (大众金融)SQL server面试题(1)-总销售量最少的3个型号的车及其总销售量
  • (一)C语言之入门:使用Visual Studio Community 2022运行hello world
  • (一)WLAN定义和基本架构转
  • (原創) 人會胖會瘦,都是自我要求的結果 (日記)
  • (原創) 如何刪除Windows Live Writer留在本機的文章? (Web) (Windows Live Writer)
  • (转)scrum常见工具列表
  • .java 9 找不到符号_java找不到符号
  • .NET CF命令行调试器MDbg入门(二) 设备模拟器
  • .net core MVC 通过 Filters 过滤器拦截请求及响应内容
  • .net dataexcel 脚本公式 函数源码
  • .NET学习教程二——.net基础定义+VS常用设置
  • .pyc文件是什么?
  • [ Python ]使用Charles对Python程序发出的Get与Post请求抓包-解决Python程序报错问题
  • []新浪博客如何插入代码(其他博客应该也可以)
  • []指针
  • [AHK V2]鼠标悬停展开窗口,鼠标离开折叠窗口
  • [BUUCTF]-PWN:[极客大挑战 2019]Not Bad解析
  • [BZOJ 4598][Sdoi2016]模式字符串
  • [C#学习笔记]LINQ
  • [C++] 从零实现一个ping服务
  • [CLR via C#]11. 事件
  • [Deepin] 简单使用 RustDesk 实现远程访问Deepin
  • [Doc][px4][ros2][gazebo][yolov8]PX4-ROS2-Gazebo-YOLOv8