c语言扫雷游戏初阶版

目录

一.游戏介绍

二.游戏分析和实现

(一).数据结构分析

         (二).代码实现和分析

1.相关函数声明,变量定义和头文件:

2.为了能够多次玩扫雷游戏可以使用do-while循环和switch,代码如下:

3.棋盘初始化

4.布置雷

5.展示棋盘

6.排查雷

三.源代码

game.h

test.c

game.c

运行结果


一.游戏介绍

1.当所点击的位置是雷时,玩家被炸死,游戏失败

2.当所点击的位置不是雷,则显示周围八个格子中雷的个数

3.直到所有非雷被排查完,玩家胜利

而在本游戏中,采用的是9*9的格子,随机布置十个雷,玩家要将所有非雷的格子排查完才算胜利。在本篇博客中,会将游戏分为三个部分完成,便于用户管理,组织,以及理解。

game.h:用来存放函数的声明,头文件以及宏定义

time.c:实现游戏的基本框架

game.c:书写游戏过程中所需要的功能函数

二.游戏分析和实现

(一).数据结构分析

 如图,这个整体是一个11*11的棋盘,中间蓝色部分是9*9的棋盘,用来存放雷的信息,命名为mine,如果要布置雷,则在该位置上存放'1'表示雷,'0'则表示没有雷。

在进一步思考,如果排除的位置没有雷,那么这个位置就会显示周围8个格子中雷的个数,当周围雷的个数为'1'时,这个位置上就会显示'1',而这个'1'与表示雷的'1'重复了,就会造成误解,无法区分这个'1'的含义,因此我们又要再创建一个9*9的棋盘来存放周围雷的个数,这个棋盘可以命名为show,为了保持show棋盘的神秘和用户体验感可以将棋盘初始化为'*'

当我们对棋盘边框附近扫雷时会出现数组越界情况,如下图所示,很明显有一部分超出9*9棋盘,为了避免这种情况所以要将棋盘改为11*11格式


对应的数组:

char mine[11][11]={0}
char show[11][11]={0}

 (二).代码实现和分析

1.相关函数声明,变量定义和头文件:

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

#define ROW 9
#define COL 9

//设置行列的长度
#define ROWS ROW+2
#define COLS COL+2

//设置雷的个数
#define EASY_COUNT 10

//棋盘初始化
void IintBoard(char arr[ROWS][COLS], int rows, int cols, char set);

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

//显示棋盘
void DispayBoard(char arr[ROWS][COLS], int row, int col);

2.为了能够多次玩扫雷游戏可以使用do-while循环和switch,代码如下:

void test()
{
    int input = 0;
    //用于rand函数生成随机数所需要的种子
    srand((unsigned int)time(NULL));
    do
    {
        menu();
        printf("请选择->");
        scanf("%d", &input);
        switch (input)
        {
        case 0:
            printf("游戏结束,退出游戏\n");
            break;
        case 1:
            game();
            break;
        default:
            printf("选择错误,请重新选择!\n");
            break;
        }
    } while (input);
}

3.棋盘初始化

将mine棋盘全部初始化为'0',show棋盘全部初始化为'*'。形参中的set则是对应实参中的'0'和'*',这样的好处就是可以减少代码,一个自定义函数就可以将俩个棋盘初始化

void IintBoard(char arr[ROWS][COLS], int rows, int cols, char set)
{
    int i = 0;
    for (i = 0; i < rows; i++)
    {
        int j = 0;
        for (j = 0; j < cols; j++)
        {
            arr[i][j] = set;
        }
    }
}

4.布置雷

由上面的表格可以知道我们时在9*9的棋盘上随机布置十个雷,因此我们要用到rand函数生成1-9的随机数,然后将生成的随机数分别当作数组的坐标,在这81个格子中随机布置十个雷

void Setmine(char arr[ROWS][COLS], int row, int col)
{
    //count表示要布置的雷的个数
    int count = EASY_COUNT;
    while (count)
    {
        int x = rand() % row + 1;//生成行为1-9之间的随机数
        int y = rand() % col + 1;//生成列为1-9之间的随机数
        if (arr[x][y] == '0')//当mine棋盘该位置上为'0'时代表没有雷则可以布置雷
        {
            arr[x][y] = '1';
            count--;//每布置好一个雷个数减一
        }
    }
}

5.展示棋盘

void DispayBoard(char arr[ROWS][COLS], int row, int col)
{
    printf("-----扫雷游戏-----\n");
    int i = 0;
    //用来打印列,提高用户体验感,便于输入坐标
    for (i = 0; i <= col; i++)
    {
        printf("%d ", i);
    }
    printf("\n");
    for (i = 1; i <= row; i++)
    {
        printf("%d ", i);//用来打印行
        int j = 0;
        for (j = 1; j <= col; j++)
        {
            printf("%c ", arr[i][j]);
        }
        printf("\n");;
    }
}

6.排查雷

我们需要先在mine棋盘上排查这是否有雷,再将信息返回给show棋盘,因此再传参中需要将俩个数组都传给Findmine函数。当该位置没有雷则需要统计周围雷的个数,因此又需要写一个函数统计雷的数量

void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
    int x = 0;
    int y = 0;
    int win = 0;
    //win的值小于没有雷的个数则一直循环
    while (win < row * col - EASY_COUNT)
    {
        printf("请输入坐标:>");
        scanf("%d %d", &x, &y);
        //判断输入的zuobiao1是否合法
        if (x >= 1 && x <= row && y >= 1 && y <= col)
        {
            //判断该坐标是否被排查过
            if (show[x][y] == '*')
            {
                if (mine[x][y] == '1')
                {
                    printf("很遗憾,你被炸死了\n");
                    //展示mine棋盘
                    DispayBoard(mine, ROW, COL);
                    break;
                }
                else
                {
                    //统计周围雷的个数
                    int count = GetMineCount(mine, x, y);
                    //将整形转化为字符型,与棋盘类型一致
                    show[x][y] = count + '0';
                    //展示show棋盘
                    DispayBoard(show, ROW, COL);
                    win++;
                }
            }
            else
                printf("该坐标已被排查\n");
        }
        else
            printf("非法坐标,重新输入\n");
    }
    //表示所有雷已被排查完
    if (win == row * col - EASY_COUNT)
    {
        printf("恭喜你,扫雷成功\n");
        DispayBoard(mine, ROW, COL);
    }
}

//统计周围雷的个数
static int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
    int i = 0;
    int count = 0;
    for (i = x - 1; i <= x + 1; i++)
    {
        int j = 0;
        for (j = y - 1; j <= y + 1; j++)
        {
            count += (mine[i][j] - '0');
        }
    }
    return count;
}

三.源代码

game.h

#pragma once
#include<stdio.h>
#include<time.h>
#include<stdlib.h>

#define ROW 9
#define COL 9

//设置行列的长度
#define ROWS ROW+2
#define COLS COL+2

//设置雷的个数
#define EASY_COUNT 10

//棋盘初始化
void IintBoard(char arr[ROWS][COLS], int rows, int cols, char set);

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

//显示棋盘
void DispayBoard(char arr[ROWS][COLS], int row, int col);

//排除雷
void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"

void game()
{
    char mine[ROWS][COLS] = { 0 };
    char show[ROWS][COLS] = { 0 };
    //棋盘初始化
    IintBoard(mine, ROWS, COLS, '0');//全部初始化为字符0
    IintBoard(show, ROWS, COLS, '*');//全部初始化为*
    //布置雷
    Setmine(mine, ROW, COL);
    //打印棋盘
    DispayBoard(show, ROW, COL);
    //排查雷
    Findmine(mine, show, ROW, COL);
}

void menu()//菜单
{
    printf("******************\n");
    printf("***** 1.play *****\n");
    printf("***** 0.exit *****\n");
    printf("******************\n");
}
void test()
{
    int input = 0;
    //用于rand函数生成随机数所需要的种子
    srand((unsigned int)time(NULL));
    do
    {
        menu();
        printf("请选择->");
        scanf("%d", &input);
        switch (input)
        {
        case 0:
            printf("游戏结束,退出游戏\n");
            break;
        case 1:
            game();
            break;
        default:
            printf("选择错误,请重新选择!\n");
            break;
        }
    } while (input);
}
int main()
{
    test();
    return 0;
}

game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"

//用于将mine棋盘和show棋盘分别初始化为'0'和'*'
void IintBoard(char arr[ROWS][COLS], int rows, int cols, char set)
{
    int i = 0;
    for (i = 0; i < rows; i++)
    {
        int j = 0;
        for (j = 0; j < cols; j++)
        {
            arr[i][j] = set;
        }
    }
}

void Setmine(char arr[ROWS][COLS], int row, int col)
{
    //count表示要布置的雷的个数
    int count = EASY_COUNT;
    while (count)
    {
        int x = rand() % row + 1;//生成行为1-9之间的随机数
        int y = rand() % col + 1;//生成列为1-9之间的随机数
        if (arr[x][y] == '0')//当mine棋盘该位置上为'0'时代表没有雷则可以布置雷
        {
            arr[x][y] = '1';
            count--;//每布置好一个雷个数减一
        }
    }
}
void DispayBoard(char arr[ROWS][COLS], int row, int col)
{
    printf("-----扫雷游戏-----\n");
    int i = 0;
    //用来打印列,提高用户体验感,便于输入坐标
    for (i = 0; i <= col; i++)
    {
        printf("%d ", i);
    }
    printf("\n");
    for (i = 1; i <= row; i++)
    {
        printf("%d ", i);//用来打印行
        int j = 0;
        for (j = 1; j <= col; j++)
        {
            printf("%c ", arr[i][j]);
        }
        printf("\n");;
    }
}

void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
    int x = 0;
    int y = 0;
    int win = 0;
    //win的值小于没有雷的个数则一直循环
    while (win < row * col - EASY_COUNT)
    {
        printf("请输入坐标:>");
        scanf("%d %d", &x, &y);
        //判断输入的zuobiao1是否合法
        if (x >= 1 && x <= row && y >= 1 && y <= col)
        {
            //判断该坐标是否被排查过
            if (show[x][y] == '*')
            {
                if (mine[x][y] == '1')
                {
                    printf("很遗憾,你被炸死了\n");
                    //展示mine棋盘
                    DispayBoard(mine, ROW, COL);
                    break;
                }
                else
                {
                    //统计周围雷的个数
                    int count = GetMineCount(mine, x, y);
                    //将整形转化为字符型,与棋盘类型一致
                    show[x][y] = count + '0';
                    //展示show棋盘
                    DispayBoard(show, ROW, COL);
                    win++;
                }
            }
            else
                printf("该坐标已被排查\n");
        }
        else
            printf("非法坐标,重新输入\n");
    }
    //表示所有雷已被排查完
    if (win == row * col - EASY_COUNT)
    {
        printf("恭喜你,扫雷成功\n");
        DispayBoard(mine, ROW, COL);
    }
}

//统计周围雷的个数
static int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
    int i = 0;
    int count = 0;
    for (i = x - 1; i <= x + 1; i++)
    {
        int j = 0;
        for (j = y - 1; j <= y + 1; j++)
        {
            count += (mine[i][j] - '0');
        }
    }
    return count;
}

运行结果

  • 12
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值