当前位置:网站首页>C语言实现扫雷游戏,附详解及完整代码
C语言实现扫雷游戏,附详解及完整代码
2022-06-30 09:36:00 【菠萝猫yena】
既来之,则安之。无论处于什么样的境地,都要尽可能调整自己的状态,让自己顺心,舒适地生活。
文章目录
前言
你的C语言学的如何了?今天,来跟随Yena做个小游戏测试一下吧~这个游戏需要一点函数和循环的基础,上手极其容易,主要练习的是我们的熟悉度和逻辑思维。
1.整体逻辑实现
1.1 准备阶段
首先,与五子棋游戏同理,我们需要一个test.c文件,用于实现游戏的整体逻辑,一个game.c文件,用于存放函数的定义,一个game.h头文件,用于存放整个项目所用到的头文件,和函数的声明。
1.2 游戏菜单及棋盘初始化
1.2.1菜单
开始之前需要一个菜单来确定是否开始游戏
选1,开始游戏,选0,退出游戏。注意,这是一个循环,用户玩完一局之后,选择1可继续新的一局,只有选择0,才会退出游戏。可通过while(输入)控制循环截止条件。实现如下,meau()为打印菜单的函数。
void menu()
{
printf("*************************\n");
printf("***** 1. play ****\n");
printf("***** 0. exit ****\n");
printf("*************************\n");
}
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
1.2.2 格子初始化
从用户的角度,开始游戏后,就会出现一个布有雷的网格,并且选择一个格子,会显示这个点附近有几个雷。如下图所示
点开一个点,显示此点附近有几个雷
所以,这里程序员需要完成·
两个char类型的二维数组
一个用于自己布置雷,初始化为‘ 0 ’。之后布置雷,‘1’表示雷,‘0’表示非雷,程序员能看到雷的分布。
另一个用于显示给用户,为表神秘,用户的点以’ * '表示。 点开一个点,可显示改点附近有几个雷。
由于两个棋盘初始化步骤一样,知识初始化的字符不同,所以,两个棋盘使用一个函数。格式为void InitBoard(char board[ROWS][COLS], int rows, int cols, char set),分别代表数组名,数组行数,列数,初始化字符
两个棋盘初始化代码实现
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.2.3 展示棋盘
棋盘做好后,为用户展示棋盘的做出形态,以便开始游戏
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.3 开始游戏
游戏的过程为,用户选择一个坐标,若该坐标符合要求,该坐标是雷,则游戏失败。若该坐标不是雷,则显示该坐标周围有几个雷,最后若排除所有的雷,则游戏胜利。
1.3.1 电脑随机布置雷
使电脑在行列范围内,随机布置坐标不同的雷。
while (count)//count为想布置的雷的个数,大小范围是0~81
{
int x = rand() % row + 1;//令电脑随机生成1~9的横坐标
int y = rand() % col + 1;//令电脑随机生成1~9的纵坐标
if (board[x][y] == '0')
{
board[x][y] = '1';//确定电脑选的坐标没有雷,则布置一个雷
count--;
}
}
srand((unsigned int)time(NULL));//时间戳,确定电
//脑不同时刻随机生成的雷的坐标都不同
//需要头文件
#include <time.h>
#include <stdlib.h>
1.3.2 开始排雷
需要判断坐标是否合理,并且该坐标未被排查过。若坐标合理,坐标是雷,游戏失败;坐标不是雷,显示坐标周围有几个雷。
1.3.3 判断坐标合理性
坐标需要满足的条件有:
- 坐标的数值要大于1且不能超出数组范围
- 坐标不能被排查过
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] != '*')
{
printf("该坐标被排查过了,不能重复排查\n");
}
1.3.3 排查坐标附近雷个数
上图为展示给程序员的布置雷的棋盘,如何排查坐标(6,3)附近有几个雷呢。只需遍历坐标附近的8个位置雷的个数。
那如何知晓坐标(1,9)附近有几个雷呢?位于边缘的元素周围是没有8个元素的,怎么解决呢?
我们声明棋盘的时候,把棋盘再增加一行一列,为边缘元素凑够8个遍历元素。但增加的一行一列的作用只是为遍历凑个数,它们不能是雷,也不用展示出来,因此,打印出来的棋盘依然是九行九列。
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');//将char类型转为int类型
}
1.3.4 判断输赢
- 若选择的坐标是雷,则输,游戏结束
- 若坐标不是雷,展示该坐标附近有几个雷,游戏继续
- 排查出所有的类,游戏胜利
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死了\n");
DisplayBoard(mine, ROW, COL);
break;
}
else//如果不是雷
{
win++;//win统计找的的非雷的个数
//统计mine数组中x,y坐标周围有几个雷
int count = get_mine_count(mine, x, y);
show[x][y] = count + '0';//转换成数字字符
DisplayBoard(show, ROW, COL);
}
if (win == row * col - EASY_COUNT)//剩下的全都是雷·
{
printf("恭喜你,排雷成功\n");
DisplayBoard(mine, ROW, COL);
}
2.完整代码展示
2.1 test.c原文件
存放游戏逻辑
#define _CRT_SECURE_NO_WARNINGS
#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][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;
}
2.2 game.h头文件
存放所有用到的头文件和函数声明
#pragma once
#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 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);
2.3 game.c原文件
存放所有函数的定义
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
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;
}
}
}
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");
}
void SetMine(char board[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
//1~9
//1~9
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
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);
}
}
总结
仔细思考,思维严谨,多多练习,深入观察。为了我们自己的未来,奋斗吧!!!
边栏推荐
- MySQL optimization
- Returnjson, which allows more custom data or class names to be returned
- MCU firmware packaging Script Software
- Xlnet (generalized autorefressive trainingfor language understanding) paper notes
- 栈题目:字符串解码
- 【Ubuntu-redis安装】
- Hospital integration platform super fusion infrastructure transformation scheme
- qmlplugindump executable not found. It is required to generate the qmltypes file for VTK Qml
- JVM memory common parameter configuration set
- ABAP time function
猜你喜欢
随机推荐
utils session&rpc
How to build an all-in-one database cloud machine that meets the needs of information innovation?
浏览器复制的网址粘贴到文档是超链接
抽象类和接口
[ubuntu-mysql 8 installation and master-slave replication]
直播带货源码开发中,如何降低直播中的延迟?
Enterprise data center "cloud" transformation solution
Shenhe thermomagnetic: Super fusion dual active cluster solution for MES system
Task summary in NLP
About the smart platform solution for business hall Terminal Desktop System
Difference between bow and cbow
Rider打开Unity脚本后没有提示
Small program development journey
MCU firmware packaging Script Software
Redis docker 主从模式与哨兵sentinel
oracle跨数据库复制数据表-dblink
【新书推荐】MongoDB Performance Tuning
小程序开发踩坑之旅
【新书推荐】Cleaning Data for Effective Data Science
LVS load balancing