C语言 扫雷游戏

news2024/10/7 20:24:41

代码在一个项目里完成,分成三个.c.h文件(game.c,game.h,main.c)
在Clion软件中通过运行调试。

/大概想法/
主函数main.c里是大框架(菜单,扫雷棋盘初始化,随机函数生成雷,玩家扫雷)
game.h函数声明(除main函数和游戏函数外的一些函数声明)
game.c函数实现(除main函数和游戏函数外的一些函数实现)

/game.c实现/

①先对扫雷棋盘进行初始化(使用两个大小一样的字符数组作为扫雷棋盘
1.存储雷 2.展示给玩家的扫雷棋盘。为了避免在遍历中出现越界访问,棋盘尺寸设置为11*11,在9*9的尺寸里布置雷,展示给玩家的也是9*9的尺寸。相当于隐藏了第一行和最后一行,第一列和最后一列。)
1棋盘初始化为0 2棋盘初始化为*

②初始化完棋盘,显示棋盘
③随机函数生成雷存储到第一个字符数组里
④玩家扫雷实现包括 :玩家输入坐标位置是否是雷。坐标不是雷情况下周围一圈是否有雷。该坐标不是雷且周围也没有雷的情况下利用递归显示这些坐标为空。

以下是部分函数实现:

//判断周围多少雷(除输入坐标外一圈的八个位置获取雷数信息。
对于字符,某个字符-'0’就是整数.八个坐标减去八个’0’就是八个坐标里有几个雷)

//判断周围多少雷,返回雷数
int BombNumber(char mine[ROWS][COLS],int row,int col){

    return mine[row -1][col-1] + mine[row - 1][col] + mine[row - 1][col+1] + \
            mine[row][col-1] + mine[row][col+1] + \
            mine[row+1][col - 1] + mine[row+1][col] + mine[row+1][col+1] -8*'0';
}

本来在玩家输入的坐标不是雷,且周围八个坐标不是雷的情况下,想在函数里列举把九个坐标存为空再显示出来的。但是在学习视频里提到可以利用递归呈现出一片空白的棋盘。在网上查阅别人的代码学习到了如何使用递归呈现一片棋盘。

//假设是3*3的棋盘
	        show[row - 1][col - 1] = ' ';//第一行
            show[row - 1][col] = ' ';
            show[row - 1][col + 1] = ' ';
            show[row][col - 1] = ' ';//第二行
            show[row][col] = ' ';
            show[row][col + 1] = ' ';
            show[row + 1][col - 1] = ' ';//第三行
            show[row + 1][col] = ' ';
            show[row + 1][col + 1] = ' ';

递归呈现一片棋盘
//在这个代码里递归思想是1.该坐标不是雷 2.周围的八个坐标也不是雷
对玩家输入的坐标进行九次循环 判断每个坐标是否合法且没有雷也没有展示给玩家
坐标满足条件以后就调用判断一圈是否有雷的函数 假如循环中的某个坐标一圈没有雷就再次进入递归函数 再将该坐标的一圈坐标进行循环遍历 继续以上过程 假如坐标不满足条件时会结束递归 进入else语句 直到九次循环完事。

void BlankBoard(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col){
    int i=0,j=0,flag=0;
    show[row][col] = ' ';
    for(i=row-1;i<=row+1;i++) {
        for (j = col-1; j <=col+1; j++) {
            if((i>0&&i<=ROW)&&(j>0&&j<=COL)&&(mine[i][j]!='1')&&(show[i][j]=='*')) {
                flag = BombNumber(mine, i, j);//判断一圈是否是雷,返回的是雷的数量
                if(!flag)
                    BlankBoard(mine,show,i,j);//递归
                else
                    show[i][j]=flag+'0';//将得到的非0的雷数放到展示给玩家的棋盘里
            }
        }
    }
}

//玩家进行游戏的核心操作

void StartBomb(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col)
{
    char array[5]="\0";//使用字符串接收玩家输入的信息
    int x,y,flag=0,win=0;

    while(win<(row*col-Bomb))
    //展示给玩家的坐标数量<整个棋盘的非雷坐标数就进入循环
    //直到玩家看到的非*坐标数量已经是所有非雷坐标
    {
        printf("玩家输入坐标,坐标形式为:x,y\n");
        gets(array);
        x=array[0]-'0';//字符-'0'为整数
        y=array[2]-'0';
        if((x>=1&&x<=ROW)&&(y>=1&&y<=COL)&&(show[x][y])=='*')//坐标合法且没有显示给玩家
        {
            if(mine[x][y]=='1')//在存储雷的棋盘中'1'代表是雷
            {
                printf("很遗憾,该坐标中放了雷,玩家被炸死");
                printf("雷分布如下:\n");
                Display(mine,ROW,COL);//显示存储雷的棋盘
                break;}
            else{
                flag=BombNumber(mine, x, y);//判断该坐标周围一圈是否是雷
                if(flag>0){//周围一圈有雷
                show[x][y]=flag+'0';
                Display(show,ROW,COL);}
                else{
                    BlankBoard(mine,show,x,y);
                    Display(show,ROW,COL);}
               winwin=Showboard(show,ROW,COL);}//判断展示给玩家的坐标数
        }
        else
            printf("坐标无效,请重新输入\n");
    }
    if(win==(row*col-Bomb)){
        printf("恭喜玩家排雷成功!\n");
        Display(mine,ROW,COL);
    }
}

//以下是完整代码(本人没玩过正常的扫雷游戏,对扫雷游戏的输赢理解可能不太对,但大概思路没啥问题)

//main.c


#include"game.h"

//初版扫雷

// 显示菜单
void menu(){
    printf("*********1.game***0.退出*********\n");
    printf("*********输入数字进行选择***********\n");
}
//游戏核心
//使用两个字符数组1->存放雷信息 2->用于输出到屏幕
//使用随机函数放置雷
//玩家排雷

void game() {
    char Mine [ROWS][COLS]={0};
    char Show [ROWS][COLS]={0};;
    //数组初始化
    Init(Mine,ROWS,COLS,'0');
    Init(Show,ROWS,COLS,'*');
    //显示
    //Display(Mine,ROWS,COLS);//显示初始化的雷棋盘
    Display(Show,ROWS,COLS);//显示玩家棋盘
    SetBomb(Mine,ROW,COL);//随机生成雷
    //Display(Mine,ROW,COL);//显示雷棋盘
    StartBomb(Mine,Show,ROW,COL);//玩家进行扫雷
}

int main()
{
    setbuf(stdout,NULL);//及时输出缓冲区内容
    int number=0;
    srand((unsigned int )time(NULL));//时间戳帮助生成棋盘上的随机坐标

    do{
        menu();
        scanf("%d",&number);
        getchar();//玩家输入的坐标使用字符串输入的,所以此时需要用getchar取走\n
        switch(number)
        {
            case 1:
                game();
                break;
            case 0:
                printf("正在退出\n");
                break;
            default:
                printf("选择错误,重新输入\n");
                break;
        }
    }while(number);

}


//game.h

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>

#define ROW 9
#define COL 9

#define ROWS (ROW+2)
#define COLS (COL+2)

#define Bomb 10

#ifndef TEXT1_GAME_H
#define TEXT1_GAME_H

void Init(char board[ROWS][COLS],int rows,int cols,char set);
void Display(char board[ROWS][COLS],int row,int col);
void SetBomb(char board[ROWS][COLS],int row,int col);
void StartBomb(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col);
int  BombNumber(char mine[ROWS][COLS],int row,int col);
void BlankBoard(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col);
int Showboard(char board[ROWS][COLS],int row,int col);
#endif

//game.c

#include"game.h"

//初始化
void Init(char board[ROWS][COLS],int rows,int cols,char set){
    int i=0,j=0;
    for(i=0;i<ROWS;i++){
        for(j=0;j<COLS;j++)
            board[i][j]=set;
    }
}

//显示函数
void Display(char board[ROWS][COLS],int row,int col)
{
    int i=0,j=0;
    //打印列数
    for(i=0;i<=COL;i++)
        printf("%d|",i);
    printf("\n");
    for(i=1;i<=ROW;i++){
        printf("%d|",i);//打印行数
        for(j=1;j<=COL;j++)
            printf("%c ",board[i][j]);
        printf("\n");
    }
}

//放置炸弹
void SetBomb(char board[ROWS][COLS],int row,int col)
{

  int numberBomb=1;
  while(numberBomb<=Bomb)
  {
      int x=(rand()%ROW)+1;
      int y=(rand()%COL)+1;
          if(board[x][y]=='0') {
              board[x][y] = '1';
              numberBomb++;}
  }
}

void StartBomb(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col)
{
    char array[5]="\0";
    int x,y,flag=0,win=0;

    while(win<(row*col-Bomb))
    {
        printf("玩家输入坐标,坐标形式为:x,y\n");
        gets(array);
        x=array[0]-'0';
        y=array[2]-'0';
        if((x>=1&&x<=ROW)&&(y>=1&&y<=COL)&&(show[x][y])=='*')
        {
            if(mine[x][y]=='1')
            {
                printf("很遗憾,该坐标中放了雷,玩家被炸死");
                printf("雷分布如下:\n");
                Display(mine,ROW,COL);
                break;}
            else{
                flag=BombNumber(mine, x, y);
                if(flag>0){
                show[x][y]=flag+'0';
                Display(show,ROW,COL);
                }
                else{
                    BlankBoard(mine,show,x,y);
                    Display(show,ROW,COL);}
               }
            win=Showboard(show,ROW,COL);
        }
        else
            printf("坐标无效,请重新输入\n");
    }
    if(win==(row*col-Bomb)){
        printf("恭喜玩家排雷成功!\n");
        Display(mine,ROW,COL);
    }
}

//判断周围多少雷
int BombNumber(char mine[ROWS][COLS],int row,int col){

    return mine[row -1][col-1] + mine[row - 1][col] + mine[row - 1][col+1] + \
            mine[row][col-1] + mine[row][col+1] + \
            mine[row+1][col - 1] + mine[row+1][col] + mine[row+1][col+1] -8*'0';
}

//1.该坐标不是雷 2.周围的八个坐标也不是雷
void BlankBoard(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col){
    int i=0,j=0,flag=0;
    show[row][col] = ' ';
    for(i=row-1;i<=row+1;i++) {
        for (j = col-1; j <=col+1; j++) {
            if((i>0&&i<=ROW)&&(j>0&&j<=COL)&&(mine[i][j]!='1')&&(show[i][j]=='*')) {
                flag = BombNumber(mine, i, j);
                if(!flag)
                    BlankBoard(mine,show,i,j);
                else
                    show[i][j]=flag+'0';
/*          show[row - 1][col - 1] = ' ';
            show[row - 1][col] = ' ';
            show[row - 1][col + 1] = ' ';
            show[row][col - 1] = ' ';
            show[row][col] = ' ';
            show[row][col + 1] = ' ';
            show[row + 1][col - 1] = ' ';
            show[row + 1][col] = ' ';
            show[row + 1][col + 1] = ' ';*/

            }
        }
    }
}


int Showboard(char board[ROWS][COLS],int row,int col){
    int i=0,j=0,number=0;
    for(i=1;i<=row;i++){
        for(j=1;j<=col;j++){
            if(board[i][j]!='*')
                number++;
        }
    }
    return number;
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1296790.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Kafka安全性探究:构建可信赖的分布式消息系统

在本文中&#xff0c;将研究Kafka的安全性&#xff0c;探讨如何确保数据在传输和存储过程中的完整性、机密性以及授权访问。通过详实的示例代码&#xff0c;全面讨论Kafka安全性的各个方面&#xff0c;从加密通信到访问控制&#xff0c;帮助大家构建一个可信赖的分布式消息系统…

品牌控价成本如何把控

品牌在发展&#xff0c;价格就需要持续关注&#xff0c;当出现乱价、低价、窜货时就应投入人力去治理&#xff0c;但企业生存&#xff0c;还要考虑成本&#xff0c;如何在保证控价效果的基础上&#xff0c;做到使用最低成本呢&#xff0c;这些问题除了控价本身外&#xff0c;也…

苹果IOS在Safari浏览器中将网页添加到主屏幕做伪Web App,自定义图标,启动动画,自定义名称,全屏应用pwa

在ios中我们可以使用Safari浏览自带的将网页添加到主屏幕上&#xff0c;让我们的web页面看起来像一个本地应用程序一样&#xff0c;通过桌面APP图标一打开&#xff0c;直接全屏展示&#xff0c;就像在APP中效果一样&#xff0c;完全体会不到你是在浏览器中。 1.网站添加样式 在…

去掉手机端顶部间隙

Unigui手机端打开时&#xff0c;在顶部有一条白色间隙 使用以下方法可以去除间隙 在ServerModule的customcss里添加以下代码 body{ margin:0!important; padding:0!important; }

文章解读与仿真程序复现思路——中国电机工程学报EI\CSCD\北大核心《考虑垃圾处理与调峰需求的可持续化城市多能源系统规划》

这个标题涵盖了城市多能源系统规划中的两个重要方面&#xff1a;垃圾处理和调峰需求&#xff0c;并强调了规划的可持续性。 考虑垃圾处理&#xff1a; 含义&#xff1a; 垃圾处理指的是城市废弃物的管理和处置。这可能涉及到废物分类、回收利用、焚烧或填埋等方法。重要性&…

使用pyftpdlib组件实现FTP文件共享

目录 一、引言 二、技术背景 三、实现逻辑 1、创建FTP服务器&#xff1a; 2、实现文件共享&#xff1a; 3、设置用户权限&#xff1a; 4、处理异常&#xff1a; 5、优化与扩展&#xff1a; 四、代码实现 五、测试与评估 测试用例&#xff1a; 评估方法&#xff1a;…

ubuntu22.04安装 nvidia-cudnn

nvidia-cudnn 是 NVIDIA CUDA 深度神经网络库&#xff08;CUDA Deep Neural Network library&#xff09;的缩写。这是一个由 NVIDIA 提供的库&#xff0c;用于加速深度学习应用程序。它包含了针对深度神经网络中常用操作&#xff08;如卷积、池化、归一化、激活层等&#xff0…

gcc tips - GCC使用技巧与高级特性

目录 1. 获取 GCC 编译器预定义的宏 2. 列出依赖的头文件 3. 保存预处理结果到文件&#xff08;展开define, 展开include header&#xff09; 4. 写回调跟踪记录函数运行 -finstrument-functions 5. -fdump-rtl-expand 画函数调用关系图 GCC&#xff0c;全称GNU Compiler …

内网环境下 - 安装linux命令、搭建docker以及安装镜像

一 内网环境安装docker 先在外网环境下载好docker二进制文件docker二进制文件下载&#xff0c;要下载对应硬件平台的文件&#xff0c;否则不兼容 如下载linux平台下的文件&#xff0c;直接访问这里即可linux版本docker二进制文件 这里下载docker-24.0.5.tgz 将下载好的文件…

LangChain+通义千问+AnalyticDB向量引擎保姆级教程

本文以构建AIGC落地应用ChatBot和构建AI Agent为例&#xff0c;从代码级别详细分享AI框架LangChain、阿里云通义大模型和AnalyticDB向量引擎的开发经验和最佳实践&#xff0c;给大家快速落地AIGC应用提供参考。 前言 通义模型具备的能力包括&#xff1a; 1.创作文字&#xf…

Oracle的错误信息帮助:Error Help

今天看手册时&#xff0c;发现上面有个提示&#xff1a; Error messages are now available in Error Help. 点击 View Error Help&#xff0c;显示如下&#xff0c;其实就是oerr命令的图形化版本&#xff1a; 点击Database Error Message Index&#xff0c;以下界面等同于命令…

Linux基础——进程初识(一)

1. 硬件 ①冯诺依曼体系 我们常见的计算机&#xff0c;如笔记本。我们不常见的计算机&#xff0c;如服务器&#xff0c;大部分都遵守冯诺依曼体系。其详细结构如下图所示 在这里有几点要说明 1. 这里的储存器实际上指的是内存 2. 输入设备与输出设备都属于外设 常见的输入设备…

分布式搜索引擎(Elastic Search)+消息队列(RabbitMQ)部署

一、分布式搜索引擎&#xff1a;Elastic Search Elastic Search的目标就是实现搜索。是一款非常强大的开源搜索引擎&#xff0c;可以帮助我们从海量数据中快速找到需要的内容。在数据量少的时候&#xff0c;我们可以通过索引去搜索关系型数据库中的数据&#xff0c;但是如果数…

【Linux下基本指令 —— 2】

Linux下基本指令 —— 2 十.more 指令语法&#xff1a;功能&#xff1a;常用选项&#xff1a;举例&#xff1a;Xshell7展示十一.less 指令语法&#xff1a;功能&#xff1a;选项&#xff1a;Xshell7展示 十二.head 指令语法&#xff1a;功能&#xff1a;选项&#xff1a;Xshell…

安卓1.0明显是基于linux内核开发的,安卓1.0是不是linux套壳?

安卓1.0明显是基于linux内核开发的&#xff0c;安卓1.0是不是linux套壳&#xff1f; 在开始前我有一些资料&#xff0c;是我根据自己从业十年经验&#xff0c;熬夜搞了几个通宵&#xff0c;精心整理了一份「安卓开发资料从专业入门到高级教程工具包」&#xff0c;点个关注&…

MyBatis下载

官网 MyBatis官网&#xff1a;https://mybatis.org/mybatis-3/ 介绍 MyBatis是一个持久化框架。 支持定制化SQL、存储过程、和高级映射。 MyBatis几乎省掉了所有的JDBC代码、手工参数设置、和结果取回。 MyBatis可以使用简单的XML或者注解进行配置、映射简单类型/接口/Java…

移动距离

//偶数行需要反转&#xff0c;判断行数时,最后一个需要特判,可以用向上取整 //也可以把传入的值减一,下标从0开始 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader;public class Main{static int w,m,n;static BufferedReader i…

(04730)电路分析基础之叠加原理

前言 在看今天的内容前&#xff0c;我建议大家先看一下这个列题&#xff0c;想一想这个I1电流为什么可以这样用&#xff01; 当然想不通也没关系&#xff08;当我学完基尔霍夫定律看这一题也很懵逼&#xff0c;不清楚i1为什么能够这样用&#xff09;&#xff0c;但是学完今天的…

DSGN:用于 3D 目标检测的深度立体几何网络

论文地址&#xff1a;https://www.jianshu.com/go-wild?ac2&urlhttps%3A%2F%2Farxiv.org%2Fpdf%2F2001.03398v3.pdf 论文代码&#xff1a;https://github.com/chenyilun95/DSGN 论文背景 大多数最先进的 3D 物体检测器严重依赖 LiDAR 传感器&#xff0c;因为基于图像的方…

C/C++,优化算法——双离子推销员问题(Bitonic Travelling Salesman Problem)的计算方法与源代码

1 文本格式 // C program for the above approach #include <bits/stdc.h> using namespace std; // Size of the array a[] const int mxN 1005; // Structure to store the x and // y coordinates of a point struct Coordinates { double x, y; } a[mxN]; //…