C语言简单扫雷小游戏

前言

关于扫雷小游戏,整体代码还是比较简单的,比较适合刚学完c语言二维数组来练习,还可以巩固前面学习的基础知识。

游戏截图


一、代码实现

利用do while循环来实现,当玩家输入0 ,switch判断,0为假break跳到最后while里,再进行判断,为假就直接结束程序。为1时就进game函数,进行游戏。

    • 主函数

void menu()
{
    printf("#####################\n");
    printf("###### 1. play ######\n");
    printf("###### 0. exit ######\n");
    printf("#####################\n");
}

int main()
{
    int input = 0;
    srand((unsigned int)time(NULL));
    do
    {
        menu();
        printf("请选择:>");
        scanf("%d", &input);
        switch (input)
        {
        case 1:
            game();
            //printf("扫雷游戏\n");
            break;
        case 0:
            printf("退出游戏\n");
            break;
        default:
            printf("请正确输入\n");
            break;
        }
    } while (input);
    return 0;
}
    • game函数

这里的game函数,创建了两个数组,用于布置雷和排查雷。布置雷的棋盘可以隐藏,不让玩家看见,就把需要下棋的部分给他看就好。

    • 创建mine和show数组
void game()
{
    //mine数组用于存放布置雷的信息
    char mine[ROWS][COLS] = { 0 };
    //show数组用于存放排查雷的信息
    char show[ROWS][COLS] = { 0 };
}
    • 定义枚举常量

用于二维数组的行和列,ROWS和COLS加2是因为,扫雷需要判定周围8个格子的数量,在边缘的就少一部分,所以这边准备用11 * 11 的格子来进行判断,但是我们只显示9 * 9的格子。这样就很好的解决了边缘空格没有数据判断了,也方便了许多。

#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
    • InitBoard函数-初始化棋盘

    • InitBoard函数调用部分

把创建的数组传过去,进行初始化。传数组、数组的行和列,还有想要初始化的字符,这里布置雷的传的是0,排查雷传的是*。可以改成你想要的字符。

void game()
{
    //mine数组用于存放布置雷的信息
    char mine[ROWS][COLS] = { 0 };
    //show数组用于存放排查雷的信息
    char show[ROWS][COLS] = { 0 };
    //初始化棋盘
    InitBoard(mine, ROWS, COLS, '0');
    InitBoard(show, ROWS, COLS, '*');
}
    • InitBoard函数构造

通过for 循环不断把二维数组初始化传过来的字符串。

//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
    int i = 0;
    int j = 0;
    for (i = 0; i < rows; i++)
    {
        for (j = 0; j < cols; j++)
        {
            board[i][j] = set;
        }
    }
}
    • InitBoard函数声明
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
    • DisplayBoard函数-打印棋盘

    • DisplayBoard函数调用部分

把排查雷的数组传过去。这里的行和列是9 * 9因为打印的棋盘是这么大。

void game()
{
    //mine数组用于存放布置雷的信息
    char mine[ROWS][COLS] = { 0 };
    //show数组用于存放排查雷的信息
    char show[ROWS][COLS] = { 0 };
    //初始化棋盘
    InitBoard(mine, ROWS, COLS, '0');
    InitBoard(show, ROWS, COLS, '*');
    //打印棋盘
    DisplayBoard(show, ROW, COL);
}
    • DisplayBoard函数构造

第一个for循环打印0-9的数字用于显示坐标。第二个先打印行的数字坐标,然后进第三个循环打印棋盘。

//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col) 
{
    int i = 0;
    int j = 0;
    printf("****** 扫雷游戏 ******\n");
    for (j = 0; j <= col; j++)
    {
        printf("%d ", j);
    }
    printf("\n");
    for (i = 1; i <= row; i++)
    {
        printf("%d ", i);
        for (j = 1; j <= col; j++)
        {
            printf("%c ", board[i][j]);
        }
        printf("\n");
    }
}
    • DisplayBoard函数声明
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);
    • SetMine函数-布置雷

    • SetMine函数调用

传mine数组,9 * 9 的行和列。

void game()
{
    //mine数组用于存放布置雷的信息
    char mine[ROWS][COLS] = { 0 };
    //show数组用于存放排查雷的信息
    char show[ROWS][COLS] = { 0 };
    //初始化棋盘
    InitBoard(mine, ROWS, COLS, '0');
    InitBoard(show, ROWS, COLS, '*');
    //打印棋盘
    DisplayBoard(show, ROW, COL);
    //布置雷
    SetMine(mine, ROW, COL);
    //这里调用DisplayBoard函数可以查看雷的位置,但是传过去的得是mine,因为只有这个是存放雷的
    //DisplayBoard(mine, ROW, COL);
}
    • SetMine函数构造

EASY_COUNT是创建的枚举常量,用于需要布置雷的数量。

rand是随机生成一个数字,% row + 1 是为了限定数字的大小。需要在主函数里调用一下srand((unsigned int)time(NULL));

if判断每次生成的随机坐标是否是字符0,是就改成1,作为雷,在count--一下。直到为0,跳出循环。

//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col)
{
    int count = EASY_COUNT;
    while (count)
    {
        int x = rand() % row + 1;
        int y = rand() % col + 1;
        if (mine[x][y] == '0')
        {
            mine[x][y] = '1';
            count--;
        }
    }
}
    • SetMine函数声明和EASY_COUNT枚举常量

#define EASY_COUNT 10雷的数量

#define EASY_COUNT 10
//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col);
    • FindMine函数和GetMineCount函数

    • FindMine函数调用

把布置雷和排查雷的数组传过去,

void game()
{
    //mine数组用于存放布置雷的信息
    char mine[ROWS][COLS] = { 0 };
    //show数组用于存放排查雷的信息
    char show[ROWS][COLS] = { 0 };
    //初始化棋盘
    InitBoard(mine, ROWS, COLS, '0');
    InitBoard(show, ROWS, COLS, '*');
    //打印棋盘
    DisplayBoard(show, ROW, COL);
    //布置雷
    SetMine(mine, ROW, COL);
    //这里调用DisplayBoard函数可以查看雷的位置,但是传过去得是mine,因为只有这个是存放雷的
    //DisplayBoard(mine, ROW, COL);
    //排查雷
    FindMine(mine, show, ROW, COL);
}
    • FindMine函数和GetMineCount函数构造

解释就写在代码里吧,比较容易看清哪里是哪里

int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
    //周围坐标相加- 8 * '0',统计周围雷的数量
    return (mine[x - 1][y] +
        mine[x - 1][y - 1] +
        mine[x][y - 1] +
        mine[x + 1][y - 1] +
        mine[x + 1][y] +
        mine[x + 1][y + 1] +
        mine[x][y + 1] +
        mine[x - 1][y + 1] - 8 * '0');
}

//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
    int x = 0;
    int y = 0;
    int win = 0;
    //当win小于row * col(9 * 9) - 雷的数量时,证明所有没有雷的地方都排完了,就结束循环。
    while (win < row * col - EASY_COUNT)
    {
        printf("请输入要排查的坐标:>");
        scanf("%d %d", &x, &y);
        //判断输入的坐标是否在棋盘内
        if (x >= 1 && x <= row && y >= 1 && y <= col)
        {
            //判断输入的坐标是否等于1,等于就就结束游戏,打印有雷的棋盘给他看。
            if (mine[x][y] == '1')
            {
                printf("不好意思,你没了\n");
                DisplayBoard(mine, ROW, COL);
                break;
            }
            //不等于1就进入GetMineCount函数判断坐标周围有几个雷。
            else
            {
                int count = GetMineCount(mine, x, y);
                show[x][y] = count + '0';
                DisplayBoard(show, ROW, COL);
                win++;
            }
        }
        //输入错误的结果
        else
        {
            printf("请正确输入坐标\n");
        }
    }
    //当所有没有雷的坐标排查完了之后,打印棋盘。
    if (win == row * col - EASY_COUNT)
    {
        printf("恭喜你,没被炸死\n");
        DisplayBoard(mine, ROW, COL);
    }
}
    • FindMine函数声明
//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

二、整体代码

    • 主函数部分

#define _CRT_SECURE_NO_WARNINGS
#include "game.h"

void menu()
{
    printf("#####################\n");
    printf("###### 1. play ######\n");
    printf("###### 0. exit ######\n");
    printf("#####################\n");
}

void game()
{
    //mine数组用于存放布置雷的信息
    char mine[ROWS][COLS] = { 0 };
    //show数组用于存放排查雷的信息
    char show[ROWS][COLS] = { 0 };
    //初始化棋盘
    InitBoard(mine, ROWS, COLS, '0');
    InitBoard(show, ROWS, COLS, '*');
    //打印棋盘
    DisplayBoard(show, ROW, COL);
    
    //布置雷
    SetMine(mine, ROW, COL);
    //这里调用DisplayBoard函数可以查看雷的位置,但是传过去的得是mine,因为只有这个是存放雷的
    //DisplayBoard(mine, ROW, COL);
    //排查雷
    FindMine(mine, show, ROW, COL);
}

int main()
{
    int input = 0;
    srand((unsigned int)time(NULL));
    do
    {
        menu();
        printf("请选择:>");
        scanf("%d", &input);
        switch (input)
        {
        case 1:
            game();
            //printf("扫雷游戏\n");
            break;
        case 0:
            printf("退出游戏\n");
            break;
        default:
            printf("请正确输入\n");
            break;
        }
    } while (input);
    return 0;
}
    • 函数实现部分

#define _CRT_SECURE_NO_WARNINGS

#include "game.h"

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


//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col) 
{
    int i = 0;
    int j = 0;
    printf("****** 扫雷游戏 ******\n");
    for (j = 0; j <= col; j++)
    {
        printf("%d ", j);
    }
    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 SetMine(char mine[ROWS][COLS], int row, int col)
{
    int count = EASY_COUNT;
    while (count)
    {
        int x = rand() % row + 1;
        int y = rand() % col + 1;
        if (mine[x][y] == '0')
        {
            mine[x][y] = '1';
            count--;
        }
    }
}

int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
    return (mine[x - 1][y] +
        mine[x - 1][y - 1] +
        mine[x][y - 1] +
        mine[x + 1][y - 1] +
        mine[x + 1][y] +
        mine[x + 1][y + 1] +
        mine[x][y + 1] +
        mine[x - 1][y + 1] - 8 * '0');
}

//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
    int x = 0;
    int y = 0;
    int win = 0;
    while (win < row * col - EASY_COUNT)
    {
        printf("请输入要排查的坐标:>");
        scanf("%d %d", &x, &y);
        if (x >= 1 && x <= row && y >= 1 && y <= col)
        {
            if (mine[x][y] == '1')
            {
                printf("不好意思,你没了\n");
                DisplayBoard(mine, ROW, COL);
                break;
            }
            else
            {
                int count = GetMineCount(mine, x, y);
                show[x][y] = count + '0';
                DisplayBoard(show, ROW, COL);
                win++;
            }
        }
        else
        {
            printf("请正确输入坐标\n");
        }
    }
    if (win == row * col - EASY_COUNT)
    {
        printf("恭喜你,没被炸死\n");
        DisplayBoard(mine, ROW, COL);
    }
}
    • 函数声明部分

#pragma once

#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2

#define EASY_COUNT 10

//头文件
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

//函数声明
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);

//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);

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

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

总结

大部分地方代码还是比较简单,多看几遍代码就容易看明白了。

谢谢观看。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值