C语言小游戏——扫雷

article/2025/9/23 1:54:40

文章目录

  • 前言
  • 一、效果图(展示)
  • 二、整体结构及功能介绍
    • 需要思考的问题
  • 三、功能解析及代码实现
  • 四、完整源码展示
  • 总结


前言

“扫雷”相信小伙伴们都玩过吧,上机课偷偷玩机房的电脑,只有扫雷,纸牌等小游戏,打磨打磨上课的时间哈哈。
经过自己一段时间的学习后,接下来细讲一下我做的扫雷小程序吧!(附加区域展开效果哦~)


一、效果图(展示)

先展示一下程序运行效果图吧

打印菜单+初始化扫雷界面
在这里插入图片描述
接着扫雷游戏进行,输入排查坐标(如果该坐标附近区域无雷(全为0)即可展开附近一片)
在这里插入图片描述
接着继续输入坐标,如果该坐标是雷,则游戏结束,可选择继续游戏也可选择退出,继续游戏前可以按 2 实现清屏,以防上一局的游戏干扰视线
在这里插入图片描述
游戏结束后会展开所有坐标,查看雷或非雷的区域

二、整体结构及功能介绍

要想扫雷,首先得有一块足够埋雷的空间,扫雷时要想想该如何实现如果该格子周围八个格子都没有雷,该区域就会被清空;踩到雷,即游戏结束。

所以我们理清思路开始逐一实现
1、创建雷盘
2、初始化雷盘
3、打印雷盘
4、随机布置你定义的雷的数量
5、展开式排雷

程序文件还是与三子棋同样思路
test.c;game.c;game.h同三子棋

需要思考的问题

对这上一个小游戏三子棋的思想,想完成一个大的平台,我们可以利用二维数组来存放雷的信息。
首先要电脑实现随机分布各个雷的位置、位置信息只有开发者能看到和游戏结束时能看到

三、功能解析及代码实现

创建雷盘、布置雷盘、初始化、打印
最上面和最左边的数字代表的是列与行坐标,'0'代表没有雷,'1'则为雷,'*'表示的是该点坐标还未进行扫雷;

如果9X9 的平台,当输入坐标为 3,1 时,发现左边有三个位置是超出我们定义的 9X9 数组范围的,那么如果解决这个问题呢?
我们可以让9X9的范围行列都向外扩展一圈,此时9X9就变为 11X11的范围了,接着可以把外围的格子初始化为0然后不显示外围的数据,这样就可以避免后续排查雷的判断了。
在这里插入图片描述

void init_board(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 display_board(char board[ROWS][COLS], int row, int col)
{int i = 0, 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");
}void set_mine(char mine[ROWS][COLS], int row, int col)
{// 布置10个雷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--;}}
}

接着就是扫雷了,这里我没有添加第一次排雷不被炸死功能,此功能可以先用if判断第一次输入的坐标是否为雷,如果是雷则可以在雷盘上重新找一个非雷的位置将开始的雷移到其他地方,小伙伴可以自行实现哦~
扫雷功能实现:玩家输入一个坐标,如果是雷,则游戏结束,如果不是雷,并且该附近区域无雷,则展开一篇,游戏继续,直到下一次排到雷或者所有非雷位置被排查完,则游戏结束

// 统计
int get_mine_count(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 Spread(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{int count_number = get_mine_count(mine, x, y);//排查该坐标附近雷的个数if (count_number == 0){show[x][y] = ' ';if ((x - 1 > 0 && x - 1 < 10) && (y - 1 > 0 && y - 1 < 10) && show[x - 1][y - 1] == '*'){Spread(mine, show, x - 1, y - 1);}if ((x - 1 > 0 && x - 1 < 10) && (y > 0 && y < 10) && show[x - 1][y] == '*'){Spread(mine, show, x - 1, y);}if ((x - 1 > 0 && x - 1 < 10) && (y + 1 > 0 && y + 1 < 10) && show[x - 1][y + 1] == '*'){Spread(mine, show, x - 1, y + 1);}if ((x > 0 && x < 10) && (y - 1 > 0 && y - 1 < 10) && show[x][y - 1] == '*'){Spread(mine, show, x, y - 1);}if ((x > 0 && x < 10) && (y + 1 > 0 && y + 1 < 10) && show[x][y + 1] == '*'){Spread(mine, show, x, y + 1);}if ((x + 1 > 0 && x + 1 < 10) && (y - 1 > 0 && y - 1 < 10) && show[x + 1][y - 1] == '*'){Spread(mine, show, x + 1, y - 1);}if ((x + 1 > 0 && x + 1 < 10) && (y > 0 && y < 10) && show[x + 1][y] == '*'){Spread(mine, show, x + 1, y);}if ((x + 1 > 0 && x + 1 < 10) && (y + 1 > 0 && y + 1 < 10) && show[x + 1][y + 1] == '*'){Spread(mine, show, x + 1, y + 1);}}else{show[x][y] = count_number + '0';}
}void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{// 1. 输入排查的坐标// 2. 检查坐标处是不是雷//	  (1)是雷     -  boom - game over //	  (2)不是雷    - 统计坐标周围有几个雷  -  存储排查雷的信息到show数组,游戏继续int x = 0;int y = 0;int win = 0;while (win < row * col - EASY_COUNT){printf("请输入要排查雷的坐标:");scanf("%d %d", &x, &y);// x -- (1,9)    y -- (1,9)//判断坐标的合法性if (x >= 1 && x <= row && y >= 1 && y <= col){if (show[x][y] == '*'){if (mine[x][y] == '1'){printf("很遗憾,你被炸死了!\n");display_board(mine, ROW, COL);break;}else{// 不是雷的情况下,统计x,y坐标周围有几个雷int count = get_mine_count(mine, x, y);show[x][y] = count + '0';Spread(mine, show, x, y);//显示排查出的信息display_board(show, ROW, COL);win++;}}else{printf("该坐标已排查过\n");}}else{printf("坐标输入有误,请重新输入\n");}}if (win == row * col - EASY_COUNT){printf("恭喜你,排雷成功!\n");display_board(show, ROW, COL);}
}

四、完整源码展示

test.c

#define _CRT_SECURE_NO_WARNINGS 1#include "game.h"void menu()
{printf(" -------------------\n");printf("|       1.play      |\n");printf("|       2.clear     |\n");printf("|       0.exit	    |\n");printf(" -------------------\n");
}void game()
{// 设计2个数组存放信息char mine[ROWS][COLS] = { 0 };char show[ROWS][COLS] = { 0 };// 初始化棋盘// mine初始化为全'0'// show初始化为全'*'init_board(mine, ROWS, COLS, '0');init_board(show, ROWS, COLS, '*');// 打印棋盘//display_board(mine, ROW, COL);//display_board(show, ROW, COL);// 布置雷set_mine(mine,ROW,COL);// 排雷//display_board(mine, ROW, COL);display_board(show, ROW, COL);find_mine(mine, show, ROW, COL);}int main()
{srand((unsigned)time(NULL));int input = 0;do{menu();printf("请选择:");scanf("%d", &input);switch (input){case 1:game();break;case 2:system("cls"); // 清屏break;case 0:printf("退出游戏\n");break;default:printf("选择错误,请重新选择\n");break;}} while (input);return 0;
}

game.h

#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable : 6031)#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <Windows.h>#define ROW 9
#define COL 9#define ROWS ROW+2
#define COLS COL+2// 默认雷
#define EASY_COUNT 20// 函数声明// 初始化
void init_board(char board[ROWS][COLS], int rows, int cols,char set);// 打印棋盘
void display_board(char board[ROWS][COLS], int row, int col);// 布置雷
void set_mine(char mine[ROWS][COLS], int row, int col);// 排查雷
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);// 展开
void Spread(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y);

game.c

#define _CRT_SECURE_NO_WARNINGS 1#include "game.h"void init_board(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 display_board(char board[ROWS][COLS], int row, int col)
{int i = 0, 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");
}void set_mine(char mine[ROWS][COLS], int row, int col)
{// 布置10个雷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 get_mine_count(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 Spread(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{int count_number = get_mine_count(mine, x, y);//排查该坐标附近雷的个数if (count_number == 0){show[x][y] = ' ';if ((x - 1 > 0 && x - 1 < 10) && (y - 1 > 0 && y - 1 < 10) && show[x - 1][y - 1] == '*'){Spread(mine, show, x - 1, y - 1);}if ((x - 1 > 0 && x - 1 < 10) && (y > 0 && y < 10) && show[x - 1][y] == '*'){Spread(mine, show, x - 1, y);}if ((x - 1 > 0 && x - 1 < 10) && (y + 1 > 0 && y + 1 < 10) && show[x - 1][y + 1] == '*'){Spread(mine, show, x - 1, y + 1);}if ((x > 0 && x < 10) && (y - 1 > 0 && y - 1 < 10) && show[x][y - 1] == '*'){Spread(mine, show, x, y - 1);}if ((x > 0 && x < 10) && (y + 1 > 0 && y + 1 < 10) && show[x][y + 1] == '*'){Spread(mine, show, x, y + 1);}if ((x + 1 > 0 && x + 1 < 10) && (y - 1 > 0 && y - 1 < 10) && show[x + 1][y - 1] == '*'){Spread(mine, show, x + 1, y - 1);}if ((x + 1 > 0 && x + 1 < 10) && (y > 0 && y < 10) && show[x + 1][y] == '*'){Spread(mine, show, x + 1, y);}if ((x + 1 > 0 && x + 1 < 10) && (y + 1 > 0 && y + 1 < 10) && show[x + 1][y + 1] == '*'){Spread(mine, show, x + 1, y + 1);}}else{show[x][y] = count_number + '0';}
}void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{// 1. 输入排查的坐标// 2. 检查坐标处是不是雷//	  (1)是雷     -  boom - game over //	  (2)不是雷    - 统计坐标周围有几个雷  -  存储排查雷的信息到show数组,游戏继续int x = 0;int y = 0;int win = 0;while (win < row * col - EASY_COUNT){printf("请输入要排查雷的坐标:");scanf("%d %d", &x, &y);// x -- (1,9)    y -- (1,9)//判断坐标的合法性if (x >= 1 && x <= row && y >= 1 && y <= col){if (show[x][y] == '*'){if (mine[x][y] == '1'){printf("很遗憾,你被炸死了!\n");display_board(mine, ROW, COL);break;}else{// 不是雷的情况下,统计x,y坐标周围有几个雷int count = get_mine_count(mine, x, y);show[x][y] = count + '0';Spread(mine, show, x, y);//显示排查出的信息display_board(show, ROW, COL);win++;}}else{printf("该坐标已排查过\n");}}else{printf("坐标输入有误,请重新输入\n");}}if (win == row * col - EASY_COUNT){printf("恭喜你,排雷成功!\n");display_board(show, ROW, COL);}
}

总结

以上就是C语言实现扫雷小游戏的分析了,还有部分功能期待小伙伴们能补全!
希望该文章能对小伙伴们有所帮助!留个赞👍再走吧~
(如有错误,望指出)


http://chatgpt.dhexx.cn/article/HT2gByQu.shtml

相关文章

c语言小游戏-飞机大战

&#xff08;创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 今天我们来尝试用easyx图形库实现c语言小游戏-飞机大战&#xff08;源代码和图片已经在结尾给出&#…

c语言小游戏百度云资源,c语言小游戏合集

这是c语言小游戏合集下载&#xff0c;这是我用c语言写的程序&#xff0c;我在大三上学期的劳动成果展示。我的其他资源都是免费的&#xff0c;是对于c语言初学者的帮助比较大的&#xff0c;其中有数据结构&#xff0c;window编程。我也在学c语言&#xff0c;每当我写完一个程序…

C语言俄罗斯方块

C语言俄罗斯方块 先看效果 代码如下 /************************************** 俄罗斯方块* 1. 游戏开始界面&#xff0c;显示界面* 2. 方块的产生,及判断方块产生的位置是否有方块&#xff0c;有就退出游戏* 3. 方块的移动&#xff0c;旋转&#xff0c;左右移动&#xff0c;…

C语言小游戏快速入门--弹跳小球

目录 一、前言二、弹跳小球的实现2.1、界面设置2.2、弹跳逻辑1、 game.h2、 game.c3、 test.c 三、总结 一、前言 相信很多小伙伴在学习完C语言语法之后就想要做几个小游戏&#xff0c;来练练手。弹跳小球就很适合C语言初学者&#xff0c;甚至你不需要学习到数组的知识就可以上…

【C语言】简单小游戏项目:《别踩白块儿》

序 突然喜欢惊鸿一瞥这个词&#xff0c;一见钟情太肤浅日久生情太苍白&#xff0c;别人眉来眼去&#xff0c;我只偷偷看你一眼。 嗨&#xff01;这里是狐狸~ 新的一周又开始了&#xff0c;时间过得还真快&#xff0c;不知道给大家分享点啥了&#xff0c;想发偏算法之类怕大家…

【C语言小游戏】走迷宫

偶然翻到了自己大一时候写的一些代码&#xff0c;代码冗余&#xff0c;但还是想保存下来&#xff0c;以作纪念。 文章目录 1.运行效果2.运行环境3.完整代码 1.运行效果 2.运行环境 源码(Dev5.4.0版本下可直接(.cpp文件)运行 gcc 4.7.2) 注意&#xff1a;由于部分代码为C11标准&…

C语言小游戏------贪吃蛇----小白专用

C语言贪吃蛇小游戏 视频正在随缘策划中。。。。 废话在后面直接上程序 该程序在VS2019上可完美运行。 #include<stdio.h> #include<stdlib.h> #include<Windows.h> #include<time.h> #include<conio.h> constexpr auto maphigh 28, mapwid…

bootstrap时间控件--时间选择器

对应上面的三个时间选择器&#xff0c;写法如下&#xff1a; 首先引入css和js&#xff1a; <link href"https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel"stylesheet"> <link href"https://cdn.bootcss.com/bootstrap-…

日期时间控件

标题 开发软件使用到日期时间控件的地方很多&#xff0c;但是很多时候Html5自带的时间控件无法满足开发的需要&#xff0c;所以使用这种时间控件完全没有问题 引用 很多时候我们开发引用别人的控件时候&#xff0c;发现老是出现错误&#xff0c;是因为我们引用出现错误&#x…

时间控件(Time Control)

之前在网上看时间控件&#xff0c;看到这个http://hi.baidu.com/fxh19860822/blog/item/dd17d923343556ae4623e8e9.html&#xff0c;感觉颜色蛮好的&#xff0c;后来觉得要是时针、分针、秒针也可以供用户交互就更好了&#xff0c;不管怎样&#xff0c;有了idea就试试吧。 老规…

时间日期选择控件

这篇blog带来一个感觉不错的时间日期选择控件&#xff0c;当然&#xff0c;该控件也可以自定义选项内容。但这里主要说下时间选择的功能&#xff01; github地址 跟着大神的脚步&#xff0c;总有一天会成为神&#xff01; 效果&#xff1a; 关键点&#xff1a; 该控件可以…

jqueryUI日期控件和时间控件

日期控件用法&#xff1a; <!DOCTYPE html> <head><meta charset"utf-8"><title>日期</title><link rel"stylesheet" href"css/jquery-ui.css"><script src"js/jquery-3.3.1.min.js"><…

Timer时间控件

第一步、创建一个Windows窗体&#xff0c; 第二步、创建样式&#xff0c;在工具箱中找到TextBox和Labell、Button、timer。 第三步、改变属性的Name和 Text&#xff08;就是改写名称&#xff09; 第四步、排版按钮 1&#xff1a;使用的控制器是Label&#xff1b;name改为lbl…

web前端时间控件使用

官方参考地址&#xff1a;http://www.layui.com/laydate/ 1.首先把下载的layDate文件夹放入项目目录下 2.在需要使用的页面引入/layDate/laydate.js 3.创建input并使用js初始化input&#xff0c;获取选择时间值时只需获取input的value即可 官方实例&#xff1a; 生成效果&a…

时间日期控件的使用

在Android中&#xff0c;时间日期控件相对来说还是比较丰富的。其中&#xff0c;DatePicker用来实现日期输入设置&#xff0c;TimePicker用来实现时间输入设置。DatePickerDialog用来显示日期对话框&#xff0c;TimePickerDialog用来显示时间对话框。AnalogClock用来显示一个指…

Android中日期和时间控件的使用

本文主要讲述Android中的日期控件和时间控件的使用&#xff0c;以一个Demo的例子来展示日期和时间控件的使用&#xff0c;先看下如下效果图&#xff1a; 从效果图中可以看到该Demo是通过单击【选择日期】按钮和【选择时间】按钮弹出日期或者时间的对话框&#xff0c;然后设置日…

前端时间控件

1.My97 Datepicker js引入&input标签编写 <script type"text/javascript" src"<%request.getContextPath() %>/js/My97DatePicker/WdatePicker.js"></script> <input style"width: 80%" id"showStartDate&quo…

Android开发之日期时间控件选择

Android开发之日期时间控件选择 文章目录 前言一、创建弹出Layout1.1 新建Layout&#xff0c;修改样式为LinearLayout1.2 Layout中添加日期和时间控件 二、新建DateTimeDialog2.1 创建静态方法2.1.1 创建SetDateDialog&#xff0c;用于选择日期2.1.2 SetDateDialog中绑定textVi…

Web前端-时间日期控件

需求&#xff1a;同时可以选择 时间 和 日期 通过设置type属性为datetime&#xff0c;即可在同一个选择器里同时进行日期和时间的选择 <template><div class"block"><span class"demonstration">默认</span><el-date-pickerv…

android时间控件

原文地址&#xff1a;http://www.360doc.com/content/14/0617/16/18203124_387517665.shtml 前言 这一篇博客分别讲解Android平台下&#xff0c;关于日期和时间的几个相关控件。包括DatePicker&#xff08;日期选择控件&#xff09;、TimePicker&#xff08;时间选择控件&…