C语言 扫雷游戏

代码在一个项目里完成,分成三个.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;
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【学习记录】从0开始的Linux学习之旅——字符型设备驱动及应用

一、概述 Linux操作系统通常是基于Linux内核&#xff0c;并结合GNU项目中的工具和应用程序而成。Linux操作系统支持多用户、多任务和多线程&#xff0c;具有强大的网络功能和良好的兼容性。基于前面应用与驱动的开发学习&#xff0c;本文主要讲述如何在linux系统上把应用与驱动…

寒冬不再寒冷:气膜体育馆如何打造温馨运动天地

取暖季即将来临&#xff0c;随着气温逐渐下降&#xff0c;人们在寒冷的冬季里如何保持运动热情和身体的健康成为了一项挑战。而在这个时候&#xff0c;气膜体育馆成为了运动爱好者们的理想场所&#xff0c;提供如春般温暖舒适的运动环境。那么&#xff0c;让我们一起揭秘气膜体…

2023年8月8日 Go生态洞察:Go 1.21 版本发布探索

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

【Java】深入剖析Java枚举类

目录 定义1&#xff09;定义2&#xff09;内部实现3&#xff09;方法与源码 高级特性1&#xff09;switch用法2&#xff09;自定义传值与构造函数3&#xff09;枚举实现抽象方法4&#xff09;枚举注解属性5&#xff09;枚举实现接口 总结 定义 1&#xff09;定义 枚举类是Jav…

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;以下界面等同于命令…

蒙商出海考察“走出去”“引进来”,探索践行“一带一路”倡议

蒙商新思路&#xff0c;出海正当时&#xff0c;内蒙古自治区促进民营经济发展项目新加坡、马来西亚交流行圆满结束 2023年11月19日-11月25日&#xff0c;内蒙古自治区促进民营经济项目新加坡、马来西亚交流考察行顺利举行&#xff0c;此次出海考察行是自治区发展改革委、工商联…

VBA_MF系列技术资料1-237

MF系列VBA技术资料 为了让广大学员在VBA编程中有切实可行的思路及有效的提高自己的编程技巧&#xff0c;我参考大量的资料&#xff0c;并结合自己的经验总结了这份MF系列VBA技术综合资料&#xff0c;而且开放源码&#xff08;MF04除外&#xff09;&#xff0c;其中MF01-04属于定…

Qt开发学习笔记01

设置窗口背景图 在 .h 文件中添加引用和方法 #include <QPainter> #include <QPixmap> void paintEvent(QPaintEvent *);.cpp 文件中实现 paintEvent void sur_dev::paintEvent(QPaintEvent *ev) {QPainter painter(this);QPixmap pix;pix.load(":/image/bj01…

什么是接口测试?这篇文章让你明白!

要成为一名合格的测试工程师&#xff0c;接口测试相关的知识和技能&#xff0c;是不可缺少的。如今&#xff0c;我们随便打开一个大公司的JD&#xff0c;上面基本会要求接口测试经验。 那么&#xff0c;接口测试到底要测些什么&#xff1f; 我相信很多小伙伴跟几年前初入测试…

力扣题:公共前缀/单词-11.18

力扣题-11.18 [力扣刷题攻略] Re&#xff1a;从零开始的力扣刷题生活 力扣题1&#xff1a;14.最长公共前缀 解题思想&#xff1a;先找到最小的字符串长度&#xff0c;然后进行字符串的遍历即可 class Solution(object):def longestCommonPrefix(self, strs):""&qu…

cookie总结

cookie和session&#xff1a; 一、Cookie和Session二、使用Cookie保存用户上次的访问时间。三、Cookie常用方法总结乱码问题解决&#xff1a; 一、Cookie和Session 会话&#xff1a;用户从打开浏览器到关闭的整个过程就叫1次会话。 比如有的网站登录过一次&#xff0c;下次再进…

深入了解Java 8日期时间新玩法:DateTimeFormatter与ZoneOffset的使用

推荐语 在这篇文章中&#xff0c;我们将深入探讨Java中的DateTimeFormatter和ZoneOffset类的功能和使用方法。这些类是在Java 8中引入的新的日期时间API的一部分&#xff0c;它们为我们提供了更灵活、更易用的日期和时间处理能力。尽管这些类在Java 8中已经出现&#xff0c;但…

「Verilog学习笔记」同步FIFO

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 timescale 1ns/1ns /**********************************RAM************************************/ module dual_port_RAM #(parameter DEPTH 16,parameter WIDTH 8)(in…

机器人刚性碰撞任务的阻抗控制性能

问题描述 对于机器人刚性碰撞任务&#xff0c;阻抗控制可以有效地提高机器人的适应性和稳定性。 在刚性碰撞任务中&#xff0c;机器人在接触外部物体时需要快速适应并调整自身的运动轨迹和速度&#xff0c;以实现精确的操控和稳定的交互。阻抗控制可以通过调整机器人的阻抗参…

王炸升级!PartyRock 10分钟构建 AI 应用

前言 一年一度的亚马逊云科技的 re:Invent 可谓是全球云计算、科技圈的狂欢&#xff0c;每次都能带来一些最前沿的方向标&#xff0c;这次也不例外。在看完一些 keynote 和介绍之后&#xff0c;我也去亲自体验了一些最近发布的内容。其中让我感受最深刻的无疑是 PartyRock 了。…

MySQL生成UUID并去除-

uuid()函数 uuid() 函数可以使mysql生成uuid,但是uuid中存在-,如下图&#xff1a; 去除uuid的- 默认生成的uuid含有-&#xff0c;我们可以使用replace函数替换掉-&#xff0c;SQL如下 select replace(uuid(),"-","") as uuid;Insert语句中使用UUID 如果…

【ArcGIS Pro微课1000例】0052:基于SQL Server创建企业级地理数据库案例

文章目录 环境搭建创建企业级数据库连接企业级数据库环境搭建 ArcGIS:ArcGIS Pro 3.0.1Server.ecp:版本为10.7SQL Server:版本为SQL Server Developer 2019创建企业级数据库 企业级地理数据库的创建需要通过工具箱来实现。工具位于:数据管理工具→地理数据库管理→创建企业…

C语言第十七集(待修)

11.30的视频 1.结构体可以这样重新赋值 注:字符数组不能用来赋值 2.匿名结构体重新赋值方法: 注:在创建x时就已经使用过一次匿名结构体了 但是,在使用匿名结构体时,可以一次性创立多个变量 3.结构体内存对齐和对其规则详细搜: 4.总之,我们在创建结构体时,要将占用空间小的成…

溯源取证-WEB流量分析-简单

话不多说直接干&#xff1a; 题干&#xff1a; 开发团队在公司的一个 Web 服务器上发现了异常文件&#xff0c;开发团队怀疑该服务器上存在潜在的恶意活动&#xff0c;网络团队准备了一个包含关键网络流量的 pcap 文件&#xff0c;供安全团队分析&#xff0c;而你的任务是分析…

虾皮关键词广告怎么选

在虾皮&#xff08;Shopee&#xff09;平台上&#xff0c;关键词广告是提高商品曝光度和销量的有效手段。然而&#xff0c;选择合适的关键词对于广告效果至关重要。本文将为您提供一些建议&#xff0c;帮助您选择适合虾皮关键词广告的关键词。 先给大家推荐一款shopee知虾数据…