news 2026/6/24 5:50:52

手把手教你用C语言开发扫雷小游戏

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
手把手教你用C语言开发扫雷小游戏

C语言:扫雷游戏

  • 一.游戏逻辑分析与结构框架
    • 1.棋盘的创建
    • 2.布置炸弹
    • 3.排除炸弹
  • 二.游戏实现
    • 1.头文件game.h
    • 2.源文件game.c
    • 3.源文件test.c

在此之前我们已经对分支与循环语句、数组和函数有了一定得了解,接下来我们将写一个简单的扫雷游戏代码,在写之前得先对扫雷逻辑要有一定的了解。

游戏要求
1.电脑生成一个9x9的棋盘
2.在这9x9棋盘中随机部署10个炸弹
3.在游戏过程中如果踩到炸弹,游戏结束并且打印棋盘布局;如果没有,则统计其周围共有几个炸弹并继续游戏,直到把除10个雷之外的所有⾮雷都找出来,排雷成功,游戏结束。

扫雷游戏


一.游戏逻辑分析与结构框架

1.棋盘的创建

首先,我们得要创建一个9x9的棋盘来存放炸弹,这很简单,运用我们之前学的二维数组即可。

#defineROW9#defineCOL9

但是得想想,如果我们只是创建了一个9x9的棋盘就足够了吗?在这之前就已经说明了在游戏要求3中如果没有踩到炸弹,则统计其周围共有几个炸弹,那如果非炸弹刚好布置在棋盘边沿,有三个位置已经超出了棋盘范围了,又该如何统计其周围共有几个炸弹呢?

如下图所示(其中设0为非炸弹,1为炸弹):

遇到这种情况又该如何去解决?

仔细想想,既然超出的范围我们用不上,并且也为非雷区,何不将这9x9的棋盘边沿包围住并填充上0,在创建一个11x11的棋盘,解决了因为范围超出的问题。

#defineROWSROW+2#defineCOLSCOL+2

如下图所示:

创建棋盘代码参考:

voidInitBoard(charboard[ROWS][COLS],introws,intcols,charset);
voidInitBoard(charboard[ROWS][COLS],introws,intcols,charset){inti=0;for(i=0;i<rows;i++){intj=0;for(j=0;j<cols;j++){board[i][j]=set;}}}
InitBoard(mine,ROWS,COLS,'0');InitBoard(show,ROWS,COLS,'*');//在这里*是为了覆盖炸弹布置的位置

看到这里你会觉得有些迷茫,为什么这代码分开来的,这是因为第一份代码我放在叫game.h的头文件里,主要是写游戏需要的数据类型和函数声明等 ;第二份代码放在game.c文件里,主要是写游戏中函数的实现等;第三份代码放在test.c文件里,主要是写游戏的测试逻辑

如何操作呢?如下图所示:

右击源文件,添加,新建项,然后有两个选项,一个是.c后缀的c++文件,另一个是.h后缀的头文件。


通过这些操作我们就可以得到:

在这里我们又看到除了创建棋盘之外还顺便打印了行和列,只需在代码中加上这几句就行:

voidDisplayBoard(charboard[ROWS][COLS],introw,intcol){inti=0;printf("--------扫雷游戏-------\n");for(i=0;i<=col;i++)//<<----打印列{printf("%d ",i);}printf("\n");for(i=1;i<=row;i++){printf("%d ",i);//<<----打印行intj=0;for(j=1;j<=col;j++){printf("%c ",board[i][j]);}printf("\n");}}

2.布置炸弹

那接下来又应该如何布置我们的炸弹呢?想一想我们之前学过的猜数字游戏中想要得到一个随机数是如何做到的,这就不得不提rand、srand和time这三个函数了,并且炸弹布置的范围不能超过棋盘的范围,仔细缕一缕,思路不就来了吗

  1. 首先创建随机值:
srand((unsignedint)time(NULL));
  1. 接着设置范围:
a+rand()%(b-a+1);//⽣成a~b的随机数

但我们要的是9x9的范围,所以可以这样写:

intx=rand()%row+1;//rand() % row范围在0~row-1, +1后范围在1~rowinty=rand()%col+1;
  1. 最后布置炸弹
    设置数量count,运用while循环,将炸弹(1)随机赋值给9x9坐标任何一个,每布置完一个,count--,布置完后count==0,跳出循环
voidSetMine(charboard[ROWS][COLS],introw,intcol){intcount=EASY_COUNT;while(count){intx=rand()%row+1;//rand() % row范围在0~row-1, +1后范围在1~rowinty=rand()%col+1;if(board[x][y]=='0'){board[x][y]='1';count--;}}}

在这里我们要注意的是,棋盘布局是用char类型,所有0和1要写成'0''1'

3.排除炸弹

既然炸弹都布置完了,那接下来的操作便是找出棋盘中所有的炸弹💣

思路是这样的,首先得输入一个有效坐标,如果该坐标是 ‘1’ ,真倒霉,被炸了游戏结束并打印炸弹布局,是否再来一局;如果该坐标是 ‘0’ ,统计该坐标周围一共有几个炸弹,继续游戏,直至找出所有炸弹,恭喜您,通关了,是否再来一局。

根据上面的思路,我们就可这样写:

voidFindMine(charmine[ROWS][COLS],charshow[ROWS][COLS],introw,intcol){intx=0;inty=0;intwin=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{intcount=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);}}

那如果该坐标是 ‘0’ ,又该如何统计该坐标周围一共有几个炸弹呢?
我们可以在判断该坐标不为炸弹调用函数int count = GetMineCount(mine, x, y);来计算

因为我们在此之前设置炸弹为 ‘1’,非炸弹为 ‘0’,那我们就可以将选择的坐标(x,y)的周围8个坐标值加起来即可,如下所示:

intGetMineCount(charmine[ROWS][COLS],intx,inty){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');}

二.游戏实现

声明game.ctest.c的头文件在game.h里面,所有这两个文件顶端都要加上#include "game.h"

1.头文件game.h

#define_CRT_SECURE_NO_WARNINGS#pragmaonce#include<stdio.h>#include<stdlib.h>#include<time.h>#defineROW9#defineCOL9#defineROWSROW+2#defineCOLSCOL+2#defineEASY_COUNT10//设置炸弹数量voidInitBoard(charboard[ROWS][COLS],introws,intcols,charset);voidDisplayBoard(charboard[ROWS][COLS],introw,intcol);voidSetMine(charboard[ROWS][COLS],introw,intcol);voidFindMine(charmine[ROWS][COLS],charshow[ROWS][COLS],introw,intcol);

2.源文件game.c

#include"game.h"//初始棋盘voidInitBoard(charboard[ROWS][COLS],introws,intcols,charset){inti=0;for(i=0;i<rows;i++){intj=0;for(j=0;j<cols;j++){board[i][j]=set;}}}voidDisplayBoard(charboard[ROWS][COLS],introw,intcol){inti=0;printf("--------扫雷游戏-------\n");for(i=0;i<=col;i++)//打印列{printf("%d ",i);}printf("\n");for(i=1;i<=row;i++){printf("%d ",i);//打印行intj=0;for(j=1;j<=col;j++){printf("%c ",board[i][j]);}printf("\n");}}voidSetMine(charboard[ROWS][COLS],introw,intcol){intcount=EASY_COUNT;while(count){intx=rand()%row+1;//rand() % row范围在0~row-1, +1后范围在1~rowinty=rand()%col+1;if(board[x][y]=='0'){board[x][y]='1';count--;}}}intGetMineCount(charmine[ROWS][COLS],intx,inty){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');}voidFindMine(charmine[ROWS][COLS],charshow[ROWS][COLS],introw,intcol){intx=0;inty=0;intwin=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{intcount=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.源文件test.c

#include"game.h"//test.c 写游戏的测试逻辑//game.c 写游戏中函数的实现等//game.h 写游戏需要的数据类型和函数声明等voidmenu()//创建菜单{printf("********************\n");printf("***** 1.play *****\n");printf("***** 0.exit *****\n");printf("********************\n");}voidgame()//创建game{//用二维数组创建棋盘charmine[ROWS][COLS]={0};//存放好布置好的炸弹charshow[ROWS][COLS]={0};//存放排查出的炸弹的信息InitBoard(mine,ROWS,COLS,'0');InitBoard(show,ROWS,COLS,'*');//布置炸弹SetMine(mine,ROW,COL);//打印棋盘//DisplayBoard(mine, ROW, COL);//如果想看炸弹布局可将DisplayBoard前面//去掉DisplayBoard(show,ROW,COL);FindMine(mine,show,ROW,COL);}intmain(){intinput=0;srand((unsignedint)time(NULL));do{menu();//调用menu(菜单)printf("请选择:>");scanf("%d",&input);switch(input){case1:game();//调用gamebreak;case0:printf("退出游戏");break;default:printf("请重新选择!");break;}}while(input);return0;}

运行结果(部分截图):

以上为简单扫雷游戏代码,想要做到真正的扫雷还需跟进一步学习,最后可以动手去试试,实践出真知!

宝剑锋从磨砺出,梅花香自苦寒来。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/13 14:53:13

Pixel Language Portal 操作系统概念可视化:原理讲解与示例代码生成

Pixel Language Portal 操作系统概念可视化&#xff1a;原理讲解与示例代码生成 1. 操作系统学习的新方式 计算机专业的学生常常面临一个困境&#xff1a;操作系统课程中的概念太过抽象&#xff0c;课本上的理论描述难以转化为实际理解。进程调度、内存管理、文件系统这些核心…

作者头像 李华
网站建设 2026/6/7 18:15:35

ChanlunX缠论插件:3步实现专业级技术分析的终极指南

ChanlunX缠论插件&#xff1a;3步实现专业级技术分析的终极指南 【免费下载链接】ChanlunX 缠中说禅炒股缠论可视化插件 项目地址: https://gitcode.com/gh_mirrors/ch/ChanlunX 你是否厌倦了在复杂的K线图中手动绘制缠论结构&#xff1f;是否想要一个能够自动识别笔、段…

作者头像 李华
网站建设 2026/6/5 14:30:28

终极指南:如何在macOS上快速部署Xbox 360控制器驱动

终极指南&#xff1a;如何在macOS上快速部署Xbox 360控制器驱动 【免费下载链接】360Controller TattieBogle Xbox 360 Driver (with improvements) 项目地址: https://gitcode.com/gh_mirrors/36/360Controller 想要在Mac上畅玩Steam游戏却苦于手柄不支持&#xff1f;3…

作者头像 李华
网站建设 2026/6/7 20:15:03

12. typeof 在 TypeScript 里有什么作用?

目录 一、 第一层&#xff1a;双重身份&#xff08;定性回答&#xff09; 二、 第二层&#xff1a;三大核心应用场景&#xff08;技术深度&#xff09; 1. 从“值”推导“类型”&#xff08;避免重复定义&#xff09; 2. “王炸组合”&#xff1a;keyof typeof 3. 获取函数…

作者头像 李华
网站建设 2026/4/13 14:51:14

dify关键词优化技巧

在 Dify 中&#xff0c;“关键词优化”通常涉及两个层面&#xff1a;一是优化用户输入的查询关键词&#xff0c;以提升知识库检索的准确性&#xff1b;二是优化知识库本身的内容关键词&#xff0c;以提高被检索到的概率。以下是针对不同场景的实用技巧。&#x1f50d; 场景一&a…

作者头像 李华
网站建设 2026/4/13 14:51:07

Windows安卓应用安装器:告别模拟器,开启无缝跨平台体验

Windows安卓应用安装器&#xff1a;告别模拟器&#xff0c;开启无缝跨平台体验 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 你是否曾在电脑前想要使用某个心仪的安卓…

作者头像 李华