【C语言】 扫雷小游戏

扫雷游戏需要用到两个源文件(.c)和一个头文件(.h)

因此,创建了test.c、game.c文件与game.h文件


test.c(游戏逻辑)

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"

void mnue()
{
    printf("*******************\n");
    printf("***** 1. play  ****\n");
    printf("***** 0. exit  ****\n");
    printf("*******************\n");
}
void game()
{
    //定义两个二维字符数组,并且行列相同,这样做的目的是为了排查雷的时候更方便
    char arr1[ROWS][COLS] = { 0 };//arr1用于布置雷的雷数
    char arr2[ROWS][COLS] = { 0 };//arr2用于提供排查雷的信息
    //初始化雷盘
    My_play(arr1, ROWS, COLS, '0');//假设'0'为非雷,'1'为雷
    My_play(arr2, ROWS, COLS, '*');//假设'*'为未排查的地方
    //打印雷盘(这里打印ROW、COL的雷盘即可,因为我们只在此雷盘内排雷
    //My_cup(arr1, ROW, COL);
    My_cup(arr2, ROW, COL);
    //布置雷
    My_Live(arr1, ROW, COL);//在arr1雷盘内布置雷,同样也只需在ROW、COL内布置
    My_cup(arr1, ROW, COL);
    //排查雷
    My_Look(arr1, arr2, ROW, COL);//此处需将arr1,arr2数组都传过去,因为当排查一次,arr2数组
    //就得提供排查雷的信息
}
int main()
{
    int input = 0;
    //用do-while循环,实现游戏的开始和退出
    //随机数
    srand((unsigned int)time(NULL));
    do
    {
        //调用函数,打印游戏菜单
        mnue();
        printf("请选择:>");
        scanf("%d", &input);
        //利用switch语句,实现游戏
        switch (input)
        {
        case 1:
            game();//调用函数,实现游戏逻辑
            break;
        case 0:
            printf("退出游戏\n");
            break;
        default:
            printf("选择错误\n");
            break;
        }
    } while (input);

    return 0;
}

game.c(游戏实现)

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"

//初始化雷盘
void My_play(char board[ROWS][COLS], int rows, int cols, char set)
{
    //因为要布置更大的雷盘,因此我们行和列就得用ROWS、COLS
    int i = 0;
    int j = 0;
    for (i = 0; i < rows; i++)
    {
        for (j = 0; j < cols; j++)
        {
            board[i][j] = set;
        }
    }
}

//打印雷盘
void My_cup(char arr2[ROWS][COLS], int row, int col)
{
    printf("*****  扫雷  *****\n");
    int i = 0;
    int j = 0;
    //此处是为了给很列标上序号,让玩家明了的知道坐标
    for (j = 0; j <= col; j++)
    {
        printf("%d ", j);
    }
    printf("\n");//打印完列序号之和换行,之后打印行序号
    //打印我们实际排雷的雷盘,范围应该在1~9
    for (i = 1; i <= row; i++)
    {
        printf("%d ", i);//作用相同,给行标上序号
        for (j = 1; j <= col; j++)
        {
            printf("%c ", arr2[i][j]);
        }
        printf("\n");
    }
}

//布置雷
void My_Live(char arr1[ROWS][COLS], int row, int col)
{
    int cont = Sum;//雷的总个数
    //利用循环,依次布置雷
    while (cont)
    {
        //利用随机值,生成雷的坐标
        int x = rand() % row + 1;//随机值%row = 0~8之间,再加1 = 1~9 之间
        int y = rand() % col + 1;//随机值%col = 0~8之间,再加1 = 1~9 之间
        if (arr1[x][y] == '0')//当雷盘位置为'0'时,代表没布置过
        {
            arr1[x][y] = '1';
            cont--;//直到布置完,退出循环
        }
    }
    
}
int My_Get(char arr1[ROWS][COLS],int x,int y)
{
    return (arr1[x - 1][y] +
        arr1[x - 1][y - 1] +
        arr1[x][y - 1] +
        arr1[x + 1][y - 1] +
        arr1[x + 1][y] +
        arr1[x + 1][y + 1] +
        arr1[x][y + 1] +
        arr1[x - 1][y + 1]) - 8 * '0';
}
//排查雷
void My_Look(char arr1[ROWS][COLS], char arr2[ROWS][COLS], int row, int col)
{
    //定义两个变量,用于排查雷的坐标
    int x = 0;
    int y = 0;
    int win = 0;//用于计算排查的次数
    while (win<row*col-Sum)//表达式的意思为,当win持续++后,直到大于(雷盘总数-雷的个数)时,代表排雷成功,跳出循环
    {
        printf("请选择要排查的坐标:>");
        scanf("%d %d", &x, &y);
        //判断输入坐标是否符合范围
        if (x >= 1 && x <= row && y >= 1 && y <= col)
        {
            //判断输入的坐标是否被占用
            if (arr2[x][y] == '*')//当坐标为'*'时,则代表该位置没被排查过
            {
                //判断输赢
                if (arr1[x][y] == '1')
                {
                    printf("很遗憾,你被炸死了\n");
                    //炸死后让玩家看雷的位置
                    My_cup(arr1, ROW, COL);
                    break;
                }
                else
                {
                    //调用函数,用于计算该坐标周围的雷数
                    int sum = My_Get(arr1, x, y);
                    //将周围雷的个数,更新到arr2雷盘上
                    arr2[x][y] = sum + '0';//这里sum + '0' 的作用是为了让数字变为字符数字
                    //打印arr2雷盘
                    My_cup(arr2, ROW, COL);
                    win++;//排查一个+1,直到跳出循环
                }
            }
            else
            {
                printf("坐标吧被占用\n");
            }
        }
        else
        {
            printf("超出范围\n");
        }
    }
    if (win >= row * col - Sum)
    {
        printf("恭喜你,排雷成功!\n");
    }
}

game.h(游戏所包含的头文件与函数声明)

#pragma once
#include<stdio.h>
//布置随机值的头文件
#include<stdlib.h>
#include<time.h>

//定义两个标识符,作为排雷的雷盘
#define ROW 9
#define COL 9
//再定义两个标识符,作为完整的雷盘,目的是为了防止计算周围雷个数时,越界了,
//因此需将原本的雷盘布置的更大一些,让排查靠边的雷时,不越界
#define ROWS ROW+2
#define COLS COL+2
//定义标识符,用于制定雷的个数
#define Sum 80

//初始化雷盘
void My_play(char board[ROWS][COLS],int rows,int cols,char set);
//这里形参部分多定义char set用于接受传过来的'0'或者'*',目的是为了同时初始化
//arr1雷盘和arr2雷盘
//因为arr1与arr2数组的行列都相同,所以我们调用一个函数就可以同时完成两个数组的初始化
 
//打印雷盘
void My_cup(char arr2[ROWS][COLS],int row,int col);

//布置雷
void My_Live(char arr1[ROWS][COLS],int row,int col);

//排查雷
void My_Look(char arr1[ROWS][COLS],char arr2[ROWS][COLS],int row,int col);

计算周围雷个数的方法以及数字转换为字符数字,字符数字转换为数字的方法

知道一处坐标后,周围的坐标如下:

数字转换为字符数字:

我们知道字符是以ASCll码存储的,并且在ASCll中,字符数字是连续存放的,

所以当我们要将数字转化为字符数字时,我们只需:

数字 + ‘0’= ‘数字’,数字为整型,字符的ASCll码也是整数,

‘0’的ASCll为48,当数字加上48后,其对应的字符数字也就是本身了

字符数字转换为数字:

也是相同的道理,当字符数字的ASCll码值 - ‘0’时,

所得到的就是数字了

因此,计算坐标周围雷的个数就显而易见了:

首先将周围坐标加起来,然后减去8个‘0’,得到数字,

这种表达式就是字符数字转换为数字,因为在最开始,我们定义arr1数组时说明

‘0’为非雷,‘1’为雷,这样就便利我们求出周围雷的个数了,

最后只需要将数字转换为字符数字,更新到arr2数组里即可


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值