C语言---扫雷(Minesweeper)

2024-01-02 13:52
文章标签 语言 扫雷 minesweeper

本文主要是介绍C语言---扫雷(Minesweeper),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

扫雷

  • 1 了解扫雷游戏
    • 1.1 基本规则
    • 1.2 基础知识
      • 1.2.1字符相减
  • 2 实现过程
    • 1.1 棋盘设定
    • 1.2 初始化棋盘
    • 1.3 打印棋盘
    • 1.4 放置雷
    • 1.5 排查雷
    • 1.6 game()函数
  • 3 完整代码
    • 3.1 Minesweeper.h
    • 3.2 Minesweeper.c
    • 3.3 Test.c
  • 4 参考


1 了解扫雷游戏

点击右侧进入扫雷游戏网页版
在这里插入图片描述

1.1 基本规则

盘面上有许多方格,方格中随机分布着一些雷。你的目标是避开雷,打开其他所有格子。一个非雷格中的数字表示其相邻8格中的雷数,你可以利用这个信息推导出安全格和雷的位置。
例如,下图中“3”表示周围坐标8个坐标中有1个雷。“1”表示周围8个坐标有1个雷。
在这里插入图片描述

1.2 基础知识

C语言数组,函数封装,for循环,while循环

1.2.1字符相减

‘1’-‘0’–>1 ‘0’-‘0’–>0
字符1减去字符0,根据ASSIC码相加减,结果就是数字1

在这里插入图片描述
在这里插入图片描述

2 实现过程

1.1 棋盘设定

假设在一个99的方格,放10个雷。在棋盘的边界,为了简化代码逻辑,设置1111的方格,防止越界。
如下图,右下角这个必然是雷,两个边界的“1”依旧按照周围8方格来思考,实际上只要考虑5个方格,边界外3个方格必然不是雷。
在这里插入图片描述

//定义展示出来棋盘的大小
#define ROW 9
#define COL 9//定义设置棋盘的大小
//处理边界问题
#define ROWS ROW+2
#define COLS COL+2//定义难度
#define EASY_COUNT 10

1.2 初始化棋盘

创建9*9的数组,是布置好的雷的信息。假设是地雷,数组存放1,不是雷,存放0。边界防止越界,行列各自加2

char mine[ROWS][COLS];//放置雷的信息,初始化‘0’,mine 数组在没有布置雷的时候,都是'0'
char show[ROWS][COLS];//排查雷的信息,初始化‘*’,show 数组在没有排查雷的时候,都是'*',
//网页版扫雷是一个空白方块,这里设定成了"*"

我们准备了两份数组,一个放置雷的信息,一个排查雷的信息。
方格初始化成什么?是0还是*,所以说可以再添加一个参数,设定为set
初始化棋盘,就是在11*11的棋盘,填入设定好的set信息。

//1 初始化棋盘的函数
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;}}
}

1.3 打印棋盘

我们要展示出99的棋盘,而实际的棋盘是1111
传递数组,依旧是ROWS,不是ROW
打印九行九列,限制for起始值,
考虑到易找到行列号,打印的时候还要在第一行和第一列打印1-9

//2 打印棋盘的函数
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{int i = 0;int j = 0;printf("-------扫雷游戏的上边界-----\n");for (j = 0; j <= col; j++){printf("%d ", j);}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");}

在这里插入图片描述

1.4 放置雷

要设置地雷的个数,提前准备#define EASY_COUNT 10
填入地雷又需要随机数的生成,利用rand()实现。
我们约定,假设是地雷,数组存放1,不是雷,存放0。
SetMine(mine, ROW, COL);
实现这个函数,用while函数,找到合法坐标,在“0”上放置雷,然后雷的数目递减

//3 放置雷的函数
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--;}}
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

确定三次随机生成的雷位置不同

1.5 排查雷

输入排查雷的坐标注意越界问题,输入错误,重新输入,采用while循环
‘1’-‘0’–>1 ‘0’-‘0’–>0 字符1减去字符0,根据ASSIC码相加减,结果就是数字1
排查过的坐标不再排查,未被排查再进行以下逻辑
如果是雷,展示排查雷的棋盘,游戏结束。
如果不是雷,记录周围地雷的个数
验证游戏通关的时候更改EASY_COUNT个数,验证排雷成功
统计mine数组中x,y坐标周围有几个雷,需要将数字转换成数字字符。

x-1,y-1x-1,yx-1,y+1
x,y-1x,yx,y+1
x+1,y-1x,y+1x+1,y+1
//4 排查雷的函数
int get_mine_count(char board[ROWS][COLS], int x, int y)
{return (board[x - 1][y] + board[x - 1][y - 1] + board[x][y - 1] + board[x + 1][y - 1] + board[x + 1][y] + board[x + 1][y + 1] + board[x][y + 1] + board[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 (show[x][y] != '*'){printf("该坐标被排查过了,不能重复排查\n");}else{//如果是雷if (mine[x][y] == '1'){printf("很遗憾,你被炸死了\n");DisplayBoard(mine, ROW, COL);break;}else//如果不是雷{win++;//统计mine数组中x,y坐标周围有几个雷int count = get_mine_count(mine, x, y);show[x][y] = count + '0';//转换成数字字符DisplayBoard(show, ROW, COL);}}}else{printf("输入的坐标非法,请重新输入\n");}}if (win == row * col - EASY_COUNT){printf("恭喜你,排雷成功\n");DisplayBoard(mine, ROW, COL);}
}

验证通关,只要把雷数目调整为80,再展示排查雷的信息的棋盘,就验证通过代码了。
在这里插入图片描述

1.6 game()函数

void game()
{char mine[ROWS][COLS] = { 0 };//存放布置好的雷的信息char show[ROWS][COLS] = { 0 };//存放排查出的雷的信息//初始化数组的内容为指定的内容//mine 数组在没有布置雷的时候,都是'0'InitBoard(mine, ROWS, COLS, '0');//show 数组在没有排查雷的时候,都是'*'InitBoard(show, ROWS, COLS, '*');//设置雷SetMine(mine, ROW, COL);DisplayBoard(show, ROW, COL);//玩游戏的时候注释下一行代码,测试的时候开启下一行代码DisplayBoard(mine, ROW, COL);//排查雷FindMine(mine, show, ROW, COL);
}

3 完整代码

3.1 Minesweeper.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>
#include <time.h>
#include <stdlib.h>//定义展示出来棋盘的大小
#define ROW 9
#define COL 9//定义设置棋盘的大小
//处理边界问题
#define ROWS ROW+2
#define COLS COL+2//定义难度
#define EASY_COUNT 80
#define MEDIUM_COUNT 30
#define TEXT_COUNT 50//1 初始化棋盘的函数
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
//2 打印棋盘的函数
void DisplayBoard(char board[ROWS][COLS], int row, int col);
//3 放置雷的函数
void SetMine(char board[ROWS][COLS], int row, int col);
//4 排查雷的函数
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

3.2 Minesweeper.c

#include "Minesweeper.h"
//1 初始化棋盘的函数
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;}}
}//2 打印棋盘的函数
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{int i = 0;int j = 0;printf("-------扫雷游戏的上边界-----\n");for (j = 0; j <= col; j++){printf("%d ", j);}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");}//3 放置雷的函数
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--;}}
}//4 排查雷的函数
int get_mine_count(char board[ROWS][COLS], int x, int y)
{return (board[x - 1][y] + board[x - 1][y - 1] + board[x][y - 1] + board[x + 1][y - 1] + board[x + 1][y] + board[x + 1][y + 1] + board[x][y + 1] + board[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 (show[x][y] != '*'){printf("该坐标被排查过了,不能重复排查\n");}else{//如果是雷if (mine[x][y] == '1'){printf("很遗憾,你被炸死了\n");DisplayBoard(mine, ROW, COL);break;}else//如果不是雷{win++;//统计mine数组中x,y坐标周围有几个雷int count = get_mine_count(mine, x, y);show[x][y] = count + '0';//转换成数字字符DisplayBoard(show, ROW, COL);}}}else{printf("输入的坐标非法,请重新输入\n");}}if (win == row * col - EASY_COUNT){printf("恭喜你,排雷成功\n");DisplayBoard(mine, ROW, COL);}
}

3.3 Test.c

#include "Minesweeper.h"void menu()
{printf("*************************\n");printf("*****   1. 开始游戏   ****\n");printf("*****   0. 退出游戏   ****\n");printf("*************************\n");
}void game()
{char mine[ROWS][COLS] = { 0 };//存放布置好的雷的信息char show[ROWS][COLS] = { 0 };//存放排查出的雷的信息//初始化数组的内容为指定的内容//mine 数组在没有布置雷的时候,都是'0'InitBoard(mine, ROWS, COLS, '0');//show 数组在没有排查雷的时候,都是'*'InitBoard(show, ROWS, COLS, '*');//设置雷SetMine(mine, ROW, COL);DisplayBoard(show, ROW, COL);//玩游戏的时候注释下一行代码//测试的时候开启下一行代码//DisplayBoard(mine, ROW, COL);//排查雷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;
}

4 参考

【比特鹏哥c语言2023完整版视频教程】P65 65.扫雷

这篇关于C语言---扫雷(Minesweeper)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/562640

相关文章

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

hihocoder1114 小Hi小Ho的惊天大作战:扫雷·一

1114 : 小Hi小Ho的惊天大作战:扫雷·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 故事背景:密室、监视器与充满危机的广场 “我们还是循序渐进,先来考虑这样一个简单化问题:”小Hi思索片刻,道:“在一个大小为2*N的广场,其中第一行里的某一些格子里可能会有至多一个地雷,而第二行的格子里全都为数字,表示第一行中距离与这个格子不超过2的格子里总共有多少个

C语言 | Leetcode C语言题解之第393题UTF-8编码验证

题目: 题解: static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num & MASK1) == 0) {return

MiniGPT-3D, 首个高效的3D点云大语言模型,仅需一张RTX3090显卡,训练一天时间,已开源

项目主页:https://tangyuan96.github.io/minigpt_3d_project_page/ 代码:https://github.com/TangYuan96/MiniGPT-3D 论文:https://arxiv.org/pdf/2405.01413 MiniGPT-3D在多个任务上取得了SoTA,被ACM MM2024接收,只拥有47.8M的可训练参数,在一张RTX

如何确定 Go 语言中 HTTP 连接池的最佳参数?

确定 Go 语言中 HTTP 连接池的最佳参数可以通过以下几种方式: 一、分析应用场景和需求 并发请求量: 确定应用程序在特定时间段内可能同时发起的 HTTP 请求数量。如果并发请求量很高,需要设置较大的连接池参数以满足需求。例如,对于一个高并发的 Web 服务,可能同时有数百个请求在处理,此时需要较大的连接池大小。可以通过压力测试工具模拟高并发场景,观察系统在不同并发请求下的性能表现,从而

C语言:柔性数组

数组定义 柔性数组 err int arr[0] = {0}; // ERROR 柔性数组 // 常见struct Test{int len;char arr[1024];} // 柔性数组struct Test{int len;char arr[0];}struct Test *t;t = malloc(sizeof(Test) + 11);strcpy(t->arr,

C语言指针入门 《C语言非常道》

C语言指针入门 《C语言非常道》 作为一个程序员,我接触 C 语言有十年了。有的朋友让我推荐 C 语言的参考书,我不敢乱推荐,尤其是国内作者写的书,往往七拼八凑,漏洞百出。 但是,李忠老师的《C语言非常道》值得一读。对了,李老师有个官网,网址是: 李忠老师官网 最棒的是,有配套的教学视频,可以试看。 试看点这里 接下来言归正传,讲解指针。以下内容很多都参考了李忠老师的《C语言非

C 语言基础之数组

文章目录 什么是数组数组变量的声明多维数组 什么是数组 数组,顾名思义,就是一组数。 假如班上有 30 个同学,让你编程统计每个人的分数,求最高分、最低分、平均分等。如果不知道数组,你只能这样写代码: int ZhangSan_score = 95;int LiSi_score = 90;......int LiuDong_score = 100;int Zhou

C 语言的基本数据类型

C 语言的基本数据类型 注:本文面向 C 语言初学者,如果你是熟手,那就不用看了。 有人问我,char、short、int、long、float、double 等这些关键字到底是什么意思,如果说他们是数据类型的话,那么为啥有这么多数据类型呢? 如果写了一句: int a; 那么执行的时候在内存中会有什么变化呢? 橡皮泥大家都玩过吧,一般你买橡皮泥的时候,店家会赠送一些模板。 上