C语言简易版扫雷

Wesley13
• 阅读 472

扫雷

  • 一、问题描述
  • 二、基本流程
  • 三、步骤
    • 1.菜单界面
    • 2.创建地图
    • 3.初始化地图
    • 4.打印地图
    • 5.玩家翻开坐标
    • 6.判断是否为地雷
    • 7.更新地图
    • 8.判断是否胜利
  • 四、代码实现

一、问题描述

用C语言实现简易版扫雷。

二、基本流程

1.菜单界面。
2.创建地图 (两个地图)。
3.初始化地图。
4.打印地图。
5.程序读取玩家输入的要翻开位置的坐标,并校验。
6.如果不是地雷,统计当前位置周围雷的个数, 并显示到地图上.。
7.判定游戏是否胜利。

三、步骤

1.菜单界面

1.开始游戏 0.退出游戏

int menu(){
   
   
    printf("----------------------\n");
    printf("------1.开始游戏------\n");
    printf("------0.退出游戏------\n");
    printf("----------------------\n");
    int choice = 0;
    printf("请输入你的选择:");
    scanf("%d", &choice);
    return choice;
}

2.创建地图

我们需要两张地图,所以要创建两个二维数组。
第一个二维数组,表示玩家看到的地图。(show)
第二个二维数组,表示当前位置是不是地雷(1表示是地雷,0表示不是地雷)。(mine)

使用宏定义的原因:
1.推高代码可读性,后续代码中遇到9,方便理解含义。
2.提高扩展性,如果将来要修改棋盘尺寸,代码修改会很方便。

#define MAX_ROW 9
#define MAX_COL 9
    char show[MAX_ROW][MAX_COL] = {
   
    0 };
    char mine[MAX_ROW][MAX_COL] = {
   
    0 };

3.初始化地图

使用 * 表示未翻开的地。
show地图一开始全都是 * 。
mine地图是由0,1组成的。(1表示是地雷,0表示不是地雷)一开始都为0,随后由电脑随机在地图上生成1。
这里我们使用宏定义了DIFFICULTY,表示地雷的数量:10个。

#define DIFFICULTY 10
void init(char show[MAX_ROW][MAX_COL], char mine[MAX_ROW][MAX_COL]){
   
   
    for (int row = 0; row < MAX_ROW; row++){
   
   
        for (int col = 0; col < MAX_COL; col++){
   
   
            show[row][col] = '*';
            //初始化 mine,先全设为'0', 然后随机生成n个'1' 
            mine[row][col] = '0';
        }
    }
    int n = DIFFICULTY;
    while (n>0){
   
   
    // 生成雷的随机位置
        int row = rand() % MAX_ROW;
        int col = rand() % MAX_COL;
        if (mine[row][col] == '1'){
   
   
        // 如果当前位置已经有雷了,就直接进入下次循环, 重新产生随机位置
            continue;
        }
        mine[row][col] = '1';
        n--;
    }
}

4.打印地图

打印出地图。

void printMap(char themap[MAX_ROW][MAX_COL]){
   
   
    printf("  |");
    for (int col = 0; col < MAX_COL; col++) {
   
   
        printf("%d ", col);
    }
    printf("\n");
    printf("--+------------------\n");
    for (int row = 0; row < MAX_ROW; row++) {
   
   
        printf(" %d|", row);
        for (int col = 0; col < MAX_COL; col++) {
   
   
            printf("%c ", themap[row][col]);
        }
        printf("\n");
    }
}

5.玩家翻开坐标

玩家通过输入坐标的方式翻开土地。
注意:
1.输入坐标要在地图范围内。
2.不能重复翻开土地。

        //程序读取玩家输入的要翻开位置的坐标, 并校验
        int row = 0;
        int col = 0;
        printf("请输入翻开的坐标(row col):");
        scanf("%d %d", &row, &col);
        if (row < 0 || col < 0 || row >= MAX_ROW || col >= MAX_COL){
   
   
            printf("输入的坐标超过范围,重新输入:\n");
            continue;
        }
        if (show[row][col] != '*'){
   
   
            printf("已经翻开,请重新输入:\n");
            continue;
        }

6.判断是否为地雷

如果翻开的位置在mine上显示为1,那么翻到地雷了,输出被炸死,打印地雷地图,让玩家死得明白。
如果翻开的位置上在mine上不是1,那么继续下一步骤。

if (mine[row][col] == '1'){
   
   
            printf("你已经被炸死了!!!\n");
            printMap(mine);
            break;
        }

7.更新地图

计算周围的地雷数量,在翻开位置显示。

updateShow(show,mine,row,col);


// 根据当前 row, col 的位置, 计算出当前位置周围有几个雷
// 并且更新显示到 show 中
void updateShow(char show[MAX_ROW][MAX_COL], char mine[MAX_ROW][MAX_COL], int row, int col){
   
   
    int count = 0;
    for (int r = row - 1; r <= row + 1; r++) {
   
   
        for (int c = col - 1; c <= col + 1; c++) {
   
   
            if (r < 0 || r >= MAX_ROW
                || c < 0 || c >= MAX_COL) {
   
   
                continue;
            }
            if (mine[r][c] == '1') {
   
   
                count++;
            }
        }
    }
    //此时 count 里面就已经存好了 row, col 周围 八个格子 的雷的个数
    // 把这个结果写到 show 中即可. 
    // 需要把数字 count 转成对应的字符
    show[row][col] = count + '0';

}

8.判断是否胜利

定义一个变量safe,表示翻开的不是地雷的土地,每次更新地图后,safe加一。如果最后翻开的不是地雷的土地等于地图的大小减地雷数,那么排除所有地雷,确认安全。

        //记录翻开的格子的个数
        int safe = 0;
        updateShow(show,mine,row,col);
        safe++;
        if (safe == MAX_ROW*MAX_COL - DIFFICULTY){
   
   
            printf("已经排除所有的雷,你已经安全!!!\n");
            printMap(mine);
            break;
        }

四、代码实现

#define _CRT_SECURE_NO_WARNINGS
#define MAX_ROW 9
#define MAX_COL 9
#define DIFFICULTY 10
#include <stdio.h>
#include <time.h>
#include <stdlib.h>

int menu(){
   
   
    printf("----------------------\n");
    printf("------1.开始游戏------\n");
    printf("------0.退出游戏------\n");
    printf("----------------------\n");
    int choice = 0;
    printf("请输入你的选择:");
    scanf("%d", &choice);
    return choice;
}
void init(char show[MAX_ROW][MAX_COL], char mine[MAX_ROW][MAX_COL]){
   
   
    for (int row = 0; row < MAX_ROW; row++){
   
   
        for (int col = 0; col < MAX_COL; col++){
   
   
            show[row][col] = '*';
            mine[row][col] = '0';
        }
    }
    int n = DIFFICULTY;
    while (n>0){
   
   
        int row = rand() % MAX_ROW;
        int col = rand() % MAX_COL;
        if (mine[row][col] == '1'){
   
   
            continue;
        }
        mine[row][col] = '1';
        n--;
    }
}
void printMap(char themap[MAX_ROW][MAX_COL]){
   
   
    printf("  |");
    for (int col = 0; col < MAX_COL; col++) {
   
   
        printf("%d ", col);
    }
    printf("\n");
    printf("--+------------------\n");
    for (int row = 0; row < MAX_ROW; row++) {
   
   
        printf(" %d|", row);
        for (int col = 0; col < MAX_COL; col++) {
   
   
            printf("%c ", themap[row][col]);
        }
        printf("\n");
    }
}
void updateShow(char show[MAX_ROW][MAX_COL], char mine[MAX_ROW][MAX_COL], int row, int col){
   
   
    int count = 0;
    for (int r = row - 1; r <= row + 1; r++) {
   
   
        for (int c = col - 1; c <= col + 1; c++) {
   
   
            if (r < 0 || r >= MAX_ROW
                || c < 0 || c >= MAX_COL) {
   
   
                continue;
            }
            if (mine[r][c] == '1') {
   
   
                count++;
            }
        }
    }
    show[row][col] = count + '0';

}
void game(){
   
   
    char show[MAX_ROW][MAX_COL] = {
   
    0 };
    char mine[MAX_ROW][MAX_COL] = {
   
    0 };
    init(show, mine);
    int safe = 0;
    while (1){
   
   
        printMap(show);
        int row = 0;
        int col = 0;
        printf("请输入翻开的坐标(row col):");
        scanf("%d %d", &row, &col);
        if (row < 0 || col < 0 || row >= MAX_ROW || col >= MAX_COL){
   
   
            printf("输入的坐标超过范围,重新输入:\n");
            continue;
        }
        if (show[row][col] != '*'){
   
   
            printf("已经翻开,请重新输入:\n");
            continue;
        }
        if (mine[row][col] == '1'){
   
   
            printf("你已经被炸死了!!!\n");
            // 打印一遍地雷的地图, 让玩家死的明白
            printMap(mine);
            break;
        }
        updateShow(show, mine, row, col);
        safe++;
        if (safe == MAX_ROW*MAX_COL - DIFFICULTY){
   
   
            printf("已经排除所有的雷,你已经安全!!!\n");
            // 打印一遍地雷的地图, 让玩家知道雷在哪
            printMap(mine);
            break;
        }
    }
}
int main()
{
   
   
    srand((unsigned int)time(0));
    while (1){
   
   
        int choice = menu();
        if (choice == 1){
   
   
            game();
        }
        else if (choice == 0){
   
   
            printf("退出游戏,byebye!");
            break;
        }
        else{
   
   
            printf("输入错误,请重新输入:");
            continue;
        }

    }
}
点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
2年前
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解2016年09月02日00:00:36 \牧野(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fme.csdn.net%2Fdcrmg) 阅读数:59593
Stella981 Stella981
2年前
OpenCV检测轮廓极点(Python C++)
    今天分享一个OpenCV检测轮廓极点实例,原图如下,我们需要检测出地图中最大轮廓的上下左右四个极点,并进行标注显示。!(https://oscimg.oschina.net/oscnet/ae374a72c5404b00b0e976e499eedf36.png)    第一步:阈值处理分割出地图轮廓!(ht
Wesley13 Wesley13
2年前
Unity RPG游戏,场景任务的设计
0:讨论群qq群号:390313628unity4.6版本运行1场景任务的设计参考开源赛达尔传说游戏SolarusDX。每个地图存在一个控制脚本,脚本名字mapxxxxxx为地图ID。地图控制器提供标准接口,进入地图事件处理和退出地图事件处理。每次切换场景地图的时候,加载对应的脚本,脚本挂在一个Game
Stella981 Stella981
2年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Stella981 Stella981
2年前
Github标星5300+,专门为程序员开发文档开源管理系统,我粉了
!(https://oscimg.oschina.net/oscnet/a11909a041dac65b1a36b2ae8b9bcc5c432.jpg)码农那点事儿关注我们,一起学习进步!(https://oscimg.oschina.net/oscnet/f4cce1b7389cb00baaab228e455da78d0
Stella981 Stella981
2年前
Nginx反向代理upstream模块介绍
!(https://oscimg.oschina.net/oscnet/1e67c46e359a4d6c8f36b590a372961f.gif)!(https://oscimg.oschina.net/oscnet/819eda5e7de54c23b54b04cfc00d3206.jpg)1.Nginx反
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_