【C语言】扫雷小游戏详解

前言:
还记得大明湖畔的夏雨荷,电脑课上的扫雷吗?

———————————————————————————是 他 吗———————————————————————————

没错,就是他。你电脑课上偷偷玩过的扫雷,今天我们用C语言做一个扫雷小游戏。

《扫雷》是一款大众类的益智小游戏,于1992年发行。游戏目标是在最短的时间内根据点击格子出现的数字找出所有非雷格子,同时避免踩雷,踩到一个雷即全盘皆输。

接下来让我们进入代码的世界:

扫雷小游戏详解:

  • 一、想法与构思
    • 1.想法
    • 2.构思
  • 二、代码与实现
    • 1.代码分块
    • 2.test.c 源文件
    • 3.game.h头文件
    • 4.game.c源文件
      • 1.分函数实现
      • 2.InitBoard 初始化函数
      • 3.DisplayBoard 打印函数
      • 4.SetMine 随机布雷函数
      • 5.GetMineCount 返回雷数函数
      • 6.FindMine 扫雷游戏函数
  • 三、完整代码
    • 1.test.c
    • 2.game.h
    • 3.game.c

目录:

一、想法与构思

1.想法

首先想要做一个游戏就先明白游戏的规则和玩法,扫雷,就是在一个n*n的棋盘上操作,玩家通过点击格子出现的数字找出所有非雷格子,避免踩雷,当所以非雷的格子都被找出,那么玩家获胜,一旦踩到任意一颗雷,则玩家失败。

没错,这就是我们想写出来的游戏,那么接下来就是构思了↓

2.构思

写任意一个代码游戏的时候都要先构思,这样写出来的代码才是比较好的,能让你事半功倍。
                              ———沃·兹基硕德

构思好了当你开始写你的代码的时候到那个地方不对劲的时候你也可以比较快速的找到错误并纠正他

废话不多说,开锤!

首先我们要确定我们代码中要实现的:
(为了更好的说明我们制作一个简单难度的扫雷)

  1. 制作一个9 x 9的棋盘并初始化埋好雷。
  2. 制作一个9 x 9的棋盘显示信息。
  3. 输入坐标然后显示该坐标结果。
  4. 游戏结果判断。

完成构思接下来就进入我们的代码领域了。


二、代码与实现

1.代码分块

同样的,为了让整个代码更加可观,我们首先把代码分为三个板块:
1.test.c源文件
测试游戏和一些细节的补充。

2.game.h头文件
存放游戏函数的声明。

3.game.c源文件
整个游戏的实现。


2.test.c 源文件

首先我们来将代码的整体框架给写出来:

//先写一个菜单函数,让我们选择是否进入游戏
void menu()
{printf("***********************************\n");printf("***********   1. play     *********\n");printf("***********   0. exit     *********\n");printf("***********************************\n");
}void game()//游戏主体的代码
{}int main()//主函数
{int input = 0;do{menu();//引用上面的菜单函数printf("请选择>");scanf("%d", &input);//选择是否进入游戏switch (input){case 1://输入1进入游戏game();break;case 0://输入0退出游戏printf("已退出游戏!");break;default://输入其他会提示输入有误printf("选择错误,请重新选择!\n");break;}} while (input);return 0;
}

然后我们要补充好game()的部分:
按照构思,我们应该要把棋盘写出来,但是在这里需要想一想,是不是两个棋盘更好一点,所以我们可以分别写两个棋盘,一个棋盘放置的是我们扫雷里面哪个下标下是有雷的,然后另一个棋盘作为给玩家进行游戏时看到的棋盘,是只会显示提示附近有几颗雷或者无雷的棋盘。

然后还有一点,我们将数组作为每一个格子里面存放是否有地雷的容器,那当边框坐标要读取旁边有多少地雷的时候,是不是也读取旁边的8个坐标呢,但是边框旁边没有呀,那我们可以在边框上再围上一层边,然后这一层边上的不放雷就好了,所以是加上2的边框。

———————————>

那么直接写?不不不,还记得我们区分板块吗,在这里我们只需要命名几个函数,然后在game.c上写就可以啦(如果你是自己写的时候建议一边命名函数一边写,然后调试过后再写下一个,这里为了给大家写思路更流程一些才这样写!)

代码如下:

//这里是game.h头文件
#pragma once#include <stdio.h>#define ROW 9//定义我们的9 x 9简单难度扫雷棋盘
#define COL 9//当然你要难一点可以改数据哦#define ROWS ROW+2//让外面增加一圈,当该坐标扫描身边坐标时,使数组不越界
#define COLS COL+2
//这里是test.c源文件 void game()
{//既然要写两个棋盘那么就写两个不同的数组存放char Mine[ROWS][COLS] = { 0 };//创建初始后台数组char Show[ROWS][ROWS] = { 0 };//创建初始显示数组//  然后是写我们初始化棋盘的函数,这里因为都是棋盘所以我们可以用同一个//函数然后放入不同数据。InitBoard(Mine, ROWS, COLS, '0');//初始化后台InitBoard(Show, ROWS, COLS, '*');//初始化扫雷//那初始化后台之后呢,我们需要把雷给埋好吧?写一个函数布雷。SetMine(Mine, ROW, COL);//布雷//然后进入游戏首先要让玩家看到棋盘,后续也要进行打印进行游戏DisplayBoard(Show, ROW, COL);//打印棋盘//看到棋盘之后就开始游戏了,所以这里需要的是我们棋盘游戏的函数。FindMine(Mine, Show, ROW, COL);//排雷游戏开始
}

所以tese.c就是把我们的函数构思再完善一遍。然后每一个对应函数在game.h里面写,这样份块的优势就是清晰明了。


3.game.h头文件

头文件这里就没什么好说的了,就是把每一个函数都赋予声明,让它能正常运行,前面我们的test.c中game里面写了四个函数,我们只需要把他们分别声明,并且确定好函数的传参就可以了。

代码如下:


#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 board[ROWS][COLS], int row, int col);//排查(扫雷游戏开始)
void FindMine(char Mine[ROWS][COLS], char Show[ROWS][COLS], int row, int col);

然后接下来我们主要讲解的是game.c的思路。


4.game.c源文件

1.分函数实现

同样的,这里我们分为几个函数的讲解

  1. InitBoard 初始化函数(把棋盘数据初始化)
  2. DisplayBoard 打印函数(进行游戏时打印给玩家看)
  3. SetMine 随机布雷函数(棋盘初始化后需要进行布雷)
  4. GetMineCount 返回雷数函数(负责在游戏进行时,玩家输入坐标返回周围雷的数字提示)
  5. FindMine 扫雷游戏函数(进行游戏时判断游戏是否继续)

接下来–

2.InitBoard 初始化函数

这是一个初始化函数,目的就是把我们之前设置的二维数组里面每一个坐标下的内容初始化,比如我们的后台得先把他的初始化成0,然后待会的布雷函数随机放十个1进去就可以了。

那初始化两个数组要放置的内容不同怎么办,我们可以把他们需要初始化的字符作为传承传过去。

代码如下:

//这里我们的set变量就是接收在test.c中传过来的字符,然后初始化函数里面的内容
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++){//我们用两个for循环将每一个数组都触及board[i][j] = set;//初始化}}
}

这样我们就把Mine二维数组中的数字全部换成了’ 0 ‘,而显示数组Show中就全部换成了’ * '。


3.DisplayBoard 打印函数

首先我们要思考我们的打印出来的是什么样子的一个界面给别人玩?

是这样子的:

还是这样子的:

还是这样子的:

很明显,三者之间最后一个比较神似扫雷一点吧?同时也有第二个的前置坐标提示,不用担心游戏还没玩多久眼睛就瞎了的第一种。

我们先写第二种:
代码如下:

void DisplayBoard(char board[ROWS][COLS], int row, int col)
{int i = 0;for (i = 0; i <= 9; i++)//顶部数字坐标提示{if (i == 0){printf("0 ");}elseprintf("%d ", i);}printf("\n");for (i = 1; i <= row; i++)//这里传进来的row是9,所以可以打印1-9即是9 x 9棋盘上的内容{int j = 0;printf("%d ", i);//靠左数字坐标提示for (j = 1; j <= col; j++){printf("%c ", board[i][j]);//打印棋盘的显示}printf("\n");}
}

然后就是弄的好看一点嘛,把周围放上边框,加上小游戏,把他移动到不那么靠左的地方。(优化的地方我会标注上说明)

代码如下:

void DisplayBoard(char board[ROWS][COLS], int row, int col)
{int i = 0;printf("            扫雷小游戏      \n");//小游戏说明printf("       --------------------\n");//框的上部for (i = 0; i <= 9; i++){if (i == 0){printf("      |0 ");//其实把游戏字体右边移一点就是左边打印一些空格,这里我打了6个}elseprintf("%d ", i);}printf("|");//在上部数字提示那里打印框的右边最上面的一个printf("\n");for (i = 1; i <= row; i++){int j = 0;printf("      |");//打印框的左部printf("%d ", i);//打印框后才打印数字提示for (j = 1; j <= col; j++){printf("%c ", board[i][j]);}printf("|");//打印框的右部剩下的printf("\n");}printf("       --------------------\n");//打印框的下部
}

这样子就可以完好的打印出我们的显示界面了。

4.SetMine 随机布雷函数

随机布雷函数就比较简单了,我们已经初始化将后台表中所有数组内都变成了字符0了,那么我们只需要在数组范围内随机生成几个坐标然后把字符1替换进去就可以了。

void SetMine(char board[ROWS][COLS], int row, int col)
{int count = EASY_COUNT;//注意,这里我们直接对应是我们头文件中简单难度的10个雷while(count)//布一个雷就少一个,当count==0就不进入循环了{int x = rand() % row + 1;//随机生成x,y坐标布置int y = rand() % col + 1;if (board[x][y] != '1')//为了防止重复布雷进行一个if语句的筛查{board[x][y] = '1';//替换count--;}    }
}

以上就是我们的布雷函数了,如果想要扩大界面布置更多的雷可以将数据改一下就可以啦。


5.GetMineCount 返回雷数函数

这个是镶嵌在第五个就是FindMine 扫雷游戏函数中的,但为了下面的函数大家更好理解,我们就先将这个函数写了。

返回雷的个数就是我需要统计我输入坐标周围的8个坐标中是否有雷,那么这里就显现出我们当初设置空为字符0,雷为字符1的优势了,当我们要知道附近雷的个数,可以直接用周围的ASCII码值来进行计算。

比如:当右边是地雷字符1的时候,我们只需要计算他减去字符0就可以得到存在1个地雷了,当不是地雷时相减就是存在0个地雷。所以

代码如下:

int GetMineCount(char Mine[ROWS][COLS],int x,int y)
//假设我输入的坐标是x,y
{int ret = 0;//计算总和int i = 0;for (i = x - 1; i <= x + 1; i++){int j = 0;for (j = y - 1; j <= y + 1; j++){//表示周围8个就是两个for循环从减一到加一ret = ret + Mine[i][j] - '0';}}return ret;//这样我们就可以将多少个雷的提示返回}

6.FindMine 扫雷游戏函数

首先我们要明确这个函数要干什么:

1. 玩家输入坐标进行游戏
2. 判断玩家输入坐标是否在范围内
3. 判断玩家坐标是否为地雷
4. 判断玩家是否扫出所有地雷游戏胜利

那我们挨个实现:

代码如下:

void FindMine(char Mine[ROWS][COLS], char Show[ROWS][COLS], int row, int col)
{int x = 0;int y = 0;//创建x,y的变量表示坐标int win = 0;while (win < row * col - EASY_COUNT){printf("请输入要排查的坐标:>");//1.玩家输入坐标scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <=col)//2.判断玩家输入坐标是否在范围内{if (Mine[x][y] == '1')//3.是字符1就是地雷{printf("很遗憾,你被炸死了\n");DisplayBoard(Mine, ROW, COL);break;}else//不是地雷就要显示周围地雷数{int count = GetMineCount(Mine, x, y);//这时候就调用GetMineCount函数返回值了Show[x][y] = count + '0';DisplayBoard(Show, ROW, COL);//打印给玩家看结果win++;//不是雷就加1,当win是棋盘减雷数就获胜}}else{printf("坐标非法,请重新输入:\n");//输入坐标不在范围内}}if (win == row * col - EASY_COUNT)//获胜条件{printf("恭喜你赢得胜利!\n");DisplayBoard(Mine, ROW, COL);}
}

然后这就是我们的扫雷函数啦。


三、完整代码

1.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][ROWS] = { 0 };//创建初始扫雷数组InitBoard(Mine, ROWS, COLS, '0');//初始化后台InitBoard(Show, ROWS, COLS, '*');//初始化扫雷SetMine(Mine, ROW, COL);//布雷DisplayBoard(Mine, ROW, COL);//打印棋盘DisplayBoard(Show, 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("已退出游戏!");break;default:printf("选择错误,请重新选择!\n");break;}} while (input);return 0;
}

2.game.h


#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 board[ROWS][COLS], int row, int col);//排查(扫雷游戏开始)
void FindMine(char Mine[ROWS][COLS], char Show[ROWS][COLS], int row, int col);

3.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;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");printf("       --------------------\n");for (i = 0; i <= 9; i++)//顶部数字顺序{if (i == 0){printf("      |0 ");}elseprintf("%d ", i);}printf("|");printf("\n");for (i = 1; i <= row; i++){int j = 0;printf("      |");printf("%d ", i);//打印每一行前面的顺序数for (j = 1; j <= col; j++){printf("%c ", board[i][j]);//打印棋盘内}printf("|");printf("\n");}printf("       --------------------\n");
}//布雷
void SetMine(char board[ROWS][COLS], int row, int col)
{int count = EASY_COUNT;while(count){int x = rand() % row + 1;int y = rand() % col + 1;if (board[x][y] != '1'){board[x][y] = '1';count--;}    }
}int GetMineCount(char Mine[ROWS][COLS],int x,int y)
{int ret = 0;int i = 0;for (i = x - 1; i <= x + 1; i++){int j = 0;for (j = y - 1; j <= y + 1; j++){ret = ret + Mine[i][j] - '0';}}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{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);}
}

这就是扫雷小游戏的C语言写法啦,小白制作不易,有错的地方还请xdm指正,互相关注,共同进步。

还有一件事:

【C语言】扫雷小游戏详解相关推荐

  1. c语言字符游动程序,C语言实现扫雷小游戏详解

    本文实例为大家分享了C语言实现扫雷小游戏的具体代码,供大家参考,具体内容如下 一.实现功能 首先显示一个小菜单,选择是否玩游戏.当用户选择退出时,程序运行结束,当用户选择玩游戏时,将提示用户输入扫雷位 ...

  2. C/C++语言扫雷小游戏(eaxyX图形库的应用)

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.扫雷的玩法,以及实现功能介绍 二.代码实现 1.引入库 2.宏定义部分 3.初始化游戏界面 4.加载图片 5.绘制 ...

  3. C语言扫雷小游戏(可选难度,可记录历史成绩)

    效果预览 下面附代码 #include<stdio.h> #include<time.h> #include<stdlib.h> #include <wind ...

  4. 100行实现《贪吃蛇》小游戏详解(Qt)

    目录 游戏说明 游戏效果展示 游戏代码详解 ​关键数据结构 初始化游戏界面 游戏部分 提示部分 蛇逻辑 小蛇的初始化 边界判断 蛇吃食物判断 随机生成食物 是否撞到自己 小蛇的移动 游戏主体逻辑 定时 ...

  5. bash shell实现2048小游戏详解

    目录 前言 重要变量 功能函数 退出处理 print_board generate_piece push_pieces apply_push check_moves key_react save_ga ...

  6. java闯关小游戏+详解+完整源代码+测试结果

    小游戏面向对象 一,问题分析 计算机输出字符串,玩家根据计算输出的内容重复输入,如果输入正确,进入一下关的练习 该过程记录玩家的积分,定义游戏的关卡,定义游戏的规则 1.1定义游戏的规则 游戏的关卡 ...

  7. HTML+Javascript制作拼图小游戏详解(一)

    本文章将分享一个来自前端菜鸟突发奇想的拼图游戏制作方法以及实现过程. 话不多说,先上图. 首先我们需要写好网页的基本布局(此处涉及简单的HTML和CSS知识). 网页一共分为三个区域,左侧时间显示区, ...

  8. C语言实现扫雷小游戏(排雷时可展开)

    游戏介绍 扫雷想必大家都听说过吧?我们今天写的小游戏就是扫雷,只不过我们只使用C语言写.我们能够做到的就是实现扫雷的基本逻辑,没有图形化界面. 源代码 这次游戏程序的写法和上一次的三子棋的模式很像,也 ...

  9. 【原创-更新完毕】|日历拼图游戏的解决方案(C语言-进阶应用)-详解连载2

    [原创]|日历拼图游戏的解决方案(C语言-进阶应用)-详解连载1_zhuyi8120的博客-CSDN博客 [原创]|日历拼图游戏的解决方案(C语言-进阶应用)-详解连载3_zhuyi8120的博客-C ...

最新文章

  1. NSCoding 的作用
  2. Xamarin.FormsShell基础教程(8)Shell的模版构成
  3. 图像处理与计算机视觉:基础,经典以及最近发展(3)计算机视觉中的信号处理与模式识别
  4. 青少年蓝桥杯_2020_每日一题_11.03_输出M与N之间符合要求的数据
  5. 全球及中国装饰花盆行业消费规模与投资商机研究报告2022版
  6. C#模拟POST表单提交 --- WebClient
  7. MUI 拍照和从系统相册选择图片上传
  8. curl_multi实现并发
  9. 华为数据库2019年度大盘点
  10. 以太网的分层架构_【新能源汽车专题】智能车时代的核心,电子架构系统深度解读,国内8股进入全球产业链(名单)...
  11. Java算法之寻找旋转数组中的最小值
  12. 笔记:Java 性能优化权威指南 第6章 Java 应用性能分析技巧
  13. 【Python】keras使用Lenet5识别mnist
  14. OJ:一道考察多态的题目
  15. 学生选课管理系统(Java)
  16. 最全的微信小程序代码大全
  17. QDir setSorting 文件排序
  18. 用php建站_九个常用的php建站系统
  19. 深入探访支付宝双11十年路,技术凿穿焦虑与想象极限
  20. Command python setup.py egg_info failed with error code 1 in /private/var/folders/14/4hz051qx0wqd3

热门文章

  1. 在html语言中br是什么标志,HTML: br 标签
  2. mac java applet_Mac OS X和多个Java版本
  3. php 魔术方法__get,php常用魔术方法
  4. 牛客小白月赛6 c 桃花
  5. 从职场新人到职场达人——工作邮件
  6. 一分钟教你熟悉国战流程
  7. 小程序客服消息怎么使用?小程序的消息推送有什么限制?
  8. 拉萨——哲蚌寺(一)
  9. pc解读4:初识南北桥
  10. 微信公众号开发使用weui上传图片