C语言实现扫雷游戏(含注释详解)
作者:3 ERROR(s) 发布时间:2023-11-02 15:25:07
本文实例为大家分享了C语言实现扫雷游戏的具体代码,供大家参考,具体内容如下
前言
一、游戏规则介绍
扫雷是一个十分经典的游戏,一张棋盘中有很多个不确定是雷还是安全区域的格子,当点击之后若没有雷则会在该区域显示周围八个格子雷的数目,若有雷则游戏结束。今天我就跟大家分享一下如何用c语言实现初阶版扫雷。
二、基本思路流程介绍
1.创建一个用户交互菜单
2.创建一个Show_Mines棋盘用来埋雷并初始化
3.创建一个Show_Table 棋盘用来和用户交互并初始化
4.玩家选择想要扫描的坐标
5.判定游戏是否结束
6.若没有踩雷则在刚扫描的区域上显示周围八个区域的地雷数目并继续游戏
7.继续扫雷
8.判定游戏是否结束
…
9.若全部扫描完非雷区域则游戏结束
效果展示
三、代码实现
1.用户交互菜单(Menu函数)
Menu(){
printf("########################\n");
printf("# 1. Play 0.Exit #\n");
printf("########################\n");
}
2. Game函数
void Game()
{
srand((unsigned long)time(NULL)); //生成随机数种子
char show_board[ROW][COL];
char mines_board[ROW][COL];
memset(show_board, WHAT, sizeof(show_board));//生成并且初始化用户显示棋盘
memset(mines_board, '0', sizeof(mines_board));//生成并且初始化扫雷棋盘
SetMines(mines_board, ROW, COL);//放雷
int count = (ROW - 2)*(COL - 2) - NUM; //若扫完这些次 不触雷则胜利
while (count){
system("cls");
ShowBoard(show_board, ROW, COL);
printf("请选择你要扫描的区域坐标 ");
int x = 0;
int y = 0;
scanf("%d %d", &x, &y);
if (x < 1 || x > ROW-2 || y < 1 || y > COL-2){ //非法性输入判断
printf("输入错误!\n");
continue;
}
if (show_board[x][y] != WHAT){
printf("此处已经被扫过了,请从新输出\n");
continue;
}
if (mines_board[x][y] == '1'){
system("cls");
ShowBoard(mines_board, ROW, COL);
printf("踩雷了!游戏结束!\n");
break;
}
show_board[x][y] = CountMines(mines_board, x, y);
count--;
}
}
1.memset函数直接定义show_board函数并且初始化二维数组为全WHAT宏定义的*。
2.先向用户展示用户展示棋盘,用户输入一个坐标进行非法性判断。
3.把用户输入的坐标拿给放置雷的棋盘中,若该区域有雷则游戏结束,反之则继续
4.游戏胜利条件为扫描完所有非雷区域
3.放雷函数(SetMines函数)
void SetMines(char board[][COL], int row, int col){ //放雷函数
int count = NUM;
while (count){
int x = rand() % (row - 2) + 1;
int y = rand() % (col - 2) + 1;
if (board[x][y] == '0'){
board[x][y] = '1';
count--;
}
}
}
使用随机数种子生成1到 棋盘大小长宽-2的随机数,这些随机数组成的坐标放雷,循环次数就是雷的数目。因为随机数可能生成一样的,所以要进行一次非法性判断,当棋盘这个位置没有雷的情况下才能往里面放雷。
4.扫雷展示面板(ShowBoard函数和ShowLine函数)
void ShowBoard(char board[][COL], int row, int col){//扫雷展示面板
printf(" ");
for (int i = 1; i <= (col - 2); i++){ //打印表头数字
printf("%d ", i);
}
printf("\n");
ShowLine(col);//显示行线
for (int i = 1; i <= (row - 2); i++){
printf("%-3d|", i);
for (int j = 1; j <= (col - 2); j++){
printf(" %c |", board[i][j]);
}
printf("\n");
ShowLine(col);
}
}
void ShowLine(int col){ //显示横着的虚线,作为行间隔
for (int i = 0; i <= (col - 2); i++){
printf("----");
}
printf("\n");
}
5.统计周围雷的个数(CountMines函数)
CountMines(char board[][COL], int x, int y){ //统计周围雷的个数
return board[x - 1][y - 1] + 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] - 7 * '0';//本来减八个零,但是整形转字符加一个‘0'
}
由于数组中存放的是字符'0',周围是8个数字,所以-8*'0'才能返回雷数的int值,为了把数字也能打印出来,所以+‘0',否则打印的是数字作为的ASCLL码的值,最终的结果为-7*‘0'.
6.mine函数
int main()
{
int quit = 0;
int select = 0;
while (!quit){
Menu();
printf("请输入 ");
scanf("%d", &select);
switch (select){
case 1:
Game();
break;
case 0:
quit = 1;
break;
default:
printf("输入错误,请重试!\n");
break;
}
}
printf("byebye!\n");
system("pause");
return 0;
}
四、总代码
#ifndef __Test_H__
#define __Test_H__
#include<stdio.h>
#include<Windows.h>
#include <stdlib.h>
#include <time.h>
#define WHAT '*'
#define NUM 20
#define COL 10
#define ROW 10
void Game();
#pragma warning(disable:4996)
#endif //以上都是头文件
int main()
{
int quit = 0;
int select = 0;
while (!quit){
Menu();
printf("请输入 ");
scanf("%d", &select);
switch (select){
case 1:
Game();
break;
case 0:
quit = 1;
break;
default:
printf("输入错误,请重试!\n");
break;
}
}
printf("byebye!\n");
system("pause");
return 0;
}
void Game()
{
srand((unsigned long)time(NULL)); //生成随机数种子
char show_board[ROW][COL];
char mines_board[ROW][COL];
memset(show_board, WHAT, sizeof(show_board));
memset(mines_board, '0', sizeof(mines_board));
SetMines(mines_board, ROW, COL);
int count = (ROW - 2)*(COL - 2) - NUM; //若扫完这些次 不触雷则胜利
while (count){
system("cls");
ShowBoard(show_board, ROW, COL);
printf("请选择你要扫描的区域坐标 ");
int x = 0;
int y = 0;
scanf("%d %d", &x, &y);
if (x < 1 || x > ROW-2 || y < 1 || y > COL-2){ //非法性输入判断
printf("输入错误!\n");
continue;
}
if (show_board[x][y] != WHAT){
printf("此处已经被扫过了,请从新输出\n");
continue;
}
if (mines_board[x][y] == '1'){
system("cls");
ShowBoard(mines_board, ROW, COL);
printf("踩雷了!游戏结束!\n");
break;
}
show_board[x][y] = CountMines(mines_board, x, y);
count--;
}
}
CountMines(char board[][COL], int x, int y){ //统计周围雷的个数
return board[x - 1][y - 1] + 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] - 7 * '0';//本来减八个零,但是整形转字符加一个‘0'
}
void ShowBoard(char board[][COL], int row, int col){//扫雷展示面板
printf(" ");
for (int i = 1; i <= (col - 2); i++){
printf("%d ", i);
}
printf("\n");
ShowLine(col);//显示行线
for (int i = 1; i <= (row - 2); i++){
printf("%-3d|", i);
for (int j = 1; j <= (col - 2); j++){
printf(" %c |", board[i][j]);
}
printf("\n");
ShowLine(col);
}
}
oid SetMines(char board[][COL], int row, int col){ //放雷函数
int count = NUM;
while (count){
int x = rand() % (row - 2) + 1;
int y = rand() % (col - 2) + 1;
if (board[x][y] == '0'){
board[x][y] = '1';
count--;
}
}
}
void ShowLine(int col){
for (int i = 0; i <= (col - 2); i++){
printf("----");
}
printf("\n");
}
Menu(){ //用户交互函数
printf("########################\n");
printf("# 1. Play 0.Exit #\n");
printf("########################\n");
}
来源:https://blog.csdn.net/weixin_50302770/article/details/117574675
猜你喜欢
- 最近研究了一下如何在Android上实现CoverFlow效果的控件,其实早在2010年,就有Neil Davies开发并开源出了这个控件,
- 一、Flutter代码的启动起点我们在多数的业务场景下,使用的都是FlutterActivity、FlutterFragment。在在背后,
- 本文实例为大家分享了android自定义环形对比图的具体代码,供大家参考,具体内容如下1.首先在res/values里创建一个attr.xm
- 本文实例为大家分享了java使用字符画一个海绵宝宝的具体代码,供大家参考,具体内容如下用字符画一个海绵宝宝用" &ldqu
- Mybatis 复杂对象resultMap数据对象含有普通属性,一对一对象,一对多对象(2种情况:单一主键和复合主键)下面是resultMa
- 本文实例总结了Android开发中Toast显示消息的方法。分享给大家供大家参考,具体如下:Android中提供一种简单的Toast消息提示
- 定义与结构 备忘录(Memento)模式又称标记(Token)模式。GOF给备忘录模式的定义为:在不破坏
- 对于大文件的处理,无论是用户端还是服务端,如果一次性进行读取发送、接收都是不可取,很容易导致内存问题。所以对于大文件上传,采用切块分段上传,
- 在style中如下面那样定义:<style name="mystyle"> <item name=&
- 前言:我们每天都在编写Java代码,编译,执行。很多人已经知道Java源代码文件(.java后缀)会被Java编译器编译为字节码文件(.cl
- Java Function的使用一、方法介绍表示接受一个参数并产生结果的函数。参数类型 T - 函数输入的类型R - 函数的结果类型方法介绍
- 1 StringString:字符串常量,字符串长度不可变。2 StringBufferStringBuffer:字符串变量(Synchro
- 一、synchronized 有不足新事物的出现要不是替代老事物,要么就是对老事物的补充JUC 的 locks 就是对 synchroniz
- 前言最近在项目中使用到定时任务,之前一直都是使用Quartz 来实现,最近看Spring 基础发现其实Spring 提供 Spring Sc
- 这里我们以拨打电话申请权限来写个小例子,也就是CALL_PHONE,因为拨打电话会涉及用户手机的资费问题,因而被列为了危险权限,在Andro
- 本文实例为大家分享了java实现简单石头剪刀布游戏的具体代码,供大家参考,具体内容如下问题描述Alice, Bob和Cindy一起玩猜拳的游
- 如果想实现一个在桌面显示的悬浮窗,用Dialog、PopupWindow、Toast等已经不能实现了,他们基本都是在Activity之上显示
- 今天重新装了编译器,结果崩无极限,真是日了狗了了。刚刚才知道问题在哪边。好了,说正事,对于ios开发我没接触,不是很了解,百度了半天,差不多
- 本文实例讲述了C#中HttpWebRequest的用法。分享给大家供大家参考。具体如下:HttpWebRequest类主要利用HTTP 协议
- 最近要给一个 Winform 项目添加功能,需要一个能显示进度条的弹窗,还要求能够中止任务,所以就做了一个,在此做个记录总结。虽然用的是比较