基于C语言扫雷游戏的实现(用到递归函数,循环语句,二维数组)(附带代码功能讲解)

扫雷游戏 我用到了递归函数 循环语句 二维数组 自定义函数为核心

1.首先是游戏的进入菜单界面

代码部分(不做讲解)

void menu()//菜单部分
{
    printf("*****************\n");
    printf("******1.play*****\n");
    printf("******0.exit*****\n");
    printf("*****************\n");
}

和游戏进入主函数口

 int main()
{
    int play ;
    do
    {
        menu();
        scanf("%d", &play);
        if (play == 1)
        {
            printf("游戏开始\n");
            game();//引用外部函数 用的头文字是自己定义的
        }
        else if(play != 1&& play !=0)
        {
            printf("输入错误请重新输入\n");
        }
    } while (play);
    printf("游戏结束\n");
    return 0;
}

然后是基础参数的设置

 

基于C语言扫雷游戏的实现(用到递归函数,循环语句,二维数组)(附带代码功能讲解)_第1张图片

 2.然后是最基础的游戏内的代码设置 (我全部批注在代码中)

基于C语言扫雷游戏的实现(用到递归函数,循环语句,二维数组)(附带代码功能讲解)_第2张图片

void game()
{
    srand((unsigned int)time(NULL));//设置随机数的基础值
    int x; int y; int z;
    char arr[X][Y] = { 0 };//这个是开棋盘
    char arr_1[X][Y] = { 0 };//这个是要生成雷的位置
    Init_game_sc(arr,X,Y);//初始化外棋盘
    Init_game_sc_l(arr_1, X, Y);//初始化内棋盘
    printf("   左上角第一个为1 1 第二个为 1 2\n");
    game_qp(arr, X, Y);//打印棋盘
    game_scqp(arr_1);//生成炸弹 生成炸弹周围的数字
    do//基础设置结束后游戏内部的代码
    {
        printf("请输入你要打开的位置>>");
        scanf("%d %d", &x, &y);
        while (1)
        {
            x -= 1; y -= 1;
            if (x >= X || x < 0 || y >= Y || y < 0)
            {
                printf("坐标输入错误请重新输入");
                printf("请输入你要打开的位置>>");
                scanf("%d %d", &x, &y);
            }
            else
            {
                break;
            }
        }
        int cango = game_pd(arr_1,arr, x, y);//判断是否合法,可以合并到这里面
        if (cango == 1)
        {
            game_kq(arr_1, arr, x, y);//打开棋盘内的空位置 并且变成0
        }
        else if (cango == -1)
        {
            printf("踩雷了,游戏失败");
            game_qp(arr_1, X, Y);
            break;
        }
        z = gameover(arr);//判断游戏是否结束
        if (z == L)
        {
            printf("游戏胜利\n");
            game_qp(arr_1, X, Y);
            break;
        }
        game_qp(arr, X, Y);
    } while (1);
    //game_qp(arr,X,Y);
}

3.逐个功能代码分析

初始化棋盘

void  Init_game_sc(char arr[X][Y],int x,int y)//初始化棋盘
{
    int i = 0; 
    int j = 0;
    for (i = 0; i < x; i++)
    {
        for (j = 0; j < y; j++)
        {
            arr[i][j] = '#';
        }
    }
}

void  Init_game_sc_l(char arr[X][Y], int x, int y)//初始化雷的棋盘
{
    int i = 0;
    int j = 0;
    for (i = 0; i < x+1; i++)
    {
        for (j = 0; j < y; j++)
        {
            arr[i][j] = ' ';
        }
    }
}

 我认为这里可以合并,可以进一步简化

打印棋盘

void game_qp(char arr[X][Y], int x, int y)//打印棋盘
{
    printf("\n");
    int i = 0; int j = 0; int z = 0;
    printf("     ");
    for (z = 0; z < x; z++)
    {
        printf("%2d ",z + 1);
        printf(" ");
    }
    printf("\n");
    printf("     ");
    for (z = 0; z < x; z++)
    {
        printf("---");
        printf(" ");
    }
    printf("\n");
    for (i = 0; i < y; i++)
    {
        printf(" %2d",i + 1);
        for (j = 0; j < x; j++)
        {
            printf(" | ", arr[i][j]);
            printf("%c", arr[i][j]);
        }
        printf(" | ", arr[i][j]);
        printf("\n");
        printf("     ");
        for (z = 0; z < x; z++)
        {
            printf("---");
            printf(" ");
        }
        printf("\n");

    }
}

 打印部分不做什么解释

判断是否合法

int game_pd(char arr_1[X][Y],char arr[X][Y], int x, int y)//是否合法
{
    if (arr_1[x][y] != '*')
    {
        return 1;
    }
    else if (arr_1[x][y] == '*')
    {
        return -1;
    }
}

 这里的判断是否踩到雷了,踩到雷返回-1 没踩到雷返回1 这个可以合并到游戏主程序里

炸弹生成代码 和 周边数字生成代码

void game_scqp(char arr_1[X][Y])//集成炸弹生成 炸弹周围数字检测生成
{
    for (int l = L;l > 0;l--)//炸弹生成 用的rand函数 
    {
        int x = (rand() % X + 1);//0-9
        int y = (rand() % Y + 1);//0-9
        if(arr_1[x][y] != '*')
        {
            arr_1[x][y] = '*';
        }
        else
        {
            l += 1;
        }
    }
    for (int i = 0; i < X; i++)//炸弹周围数字计数功能 
    {
        for (int j = 0; j < Y; j++)
        {

            if (arr_1[i][j] == '*')
            {
                continue;
            }
            else
            {
                int a;
                int b;
                int count = 0;
                for (a = -1; a < 2; a++)
                {
                    for (b = -1; b < 2; b++)
                    {
                        if (i + a < 0 || i + a >= X || j + b < 0 || j + b >= Y)
                        {
                            continue;
                        }
                        if (arr_1[i + a][j + b] == '*')
                        {
                            count++;
                        }
                    }
                }
                if (count != 0)
                {
                    arr_1[i][j] = count + '0';
                }
            }
        }
    }
}

 炸弹周围数字计数功能,我写的并不是最优解,但是我个人认为比较直观,先找到一个坐标 然后定义数字初始为0 然后以 3 * 3的方式挨个扫描周围 如果有雷 数字加一 几个雷加几个数 数完以后 把数字填写到这个坐标里(我个人认为写的比较麻烦,希望能有更优解)

判定是否胜利

int gameover(char arr[X][Y])
{
    int count = 0; int i = 0; int j = 0;
    for (i = 0; i < X; i++)
    {
        for (j = 0; j < Y; j++)
        {
            if (arr[i][j] == '#')
            {
                count++;
            }
        }
    }
    return count;
}

到最后没有扫的地方 是 # 那么当#的数量等于雷的数量就判断成功 

这里返回#的数量给后面的程序判断


然后是打开空格

这里用到递归函数

我的思路就是以十字打开 然后在打开过的非数字的地方变成0 到有数字的地方停止

void game_kq(char arr_1[X][Y], char arr[X][Y], int x, int y)//开启棋盘 打开空棋盘位置
{
    arr[x][y] = arr_1[x][y];
    if (arr_1[x][y] != '0')
    {
        if(arr_1[x][y] == ' ')
        arr_1[x][y] = '0';
        if (x > 0)
        {
            if (arr_1[x - 1][y] == ' ')
            {
                game_kq(arr_1, arr, x - 1, y);
            }
            if (arr_1[x - 1][y] != ' ' && arr_1[x - 1][y] != '*')
            {
                arr[x - 1][y] = arr_1[x - 1][y];
            }
        }
        if (x < X - 1)
        {
            if (arr_1[x + 1][y] == ' ')
            {
                game_kq(arr_1, arr, x + 1, y);
            }
            if (arr_1[x + 1][y] != ' ' && arr_1[x + 1][y] != '*')
            {
                arr[x + 1][y] = arr_1[x + 1][y];
            }
        }
        if (y > 0)
        {
            if (arr_1[x][y - 1] == ' ')
            {
                game_kq(arr_1, arr, x, y - 1);
            }
            if (arr_1[x][y - 1] != ' ' && arr_1[x][y - 1] != '*')
            {
                arr[x][y - 1] = arr_1[x][y - 1];
            }
        }
        if (y < Y - 1)
        {
            if (arr_1[x][y + 1] == ' ')
            {
                game_kq(arr_1, arr, x, y + 1);
            }
            if (arr_1[x][y + 1] != ' ' && arr_1[x][y + 1] != '*')
            {
                arr[x][y + 1] = arr_1[x][y + 1];
            }
        }
    }
}

 因为是十字 所以我写了四个方向的递归(希望有大佬可以给出简化版本,而且能让简化完之后给我的是空格而不是0)

以上是程序的各个部分


//全部函数程序

头文件

#pragma once
#include
#define X 10//长
#define Y 10//宽
#define L 1//雷的个数
 
void menu();
void game();

主函数

#define _CRT_SECURE_NO_WARNINGS
#include
#include "game.h"


int main()
{
    int play ;
    do
    {
        menu();
        scanf("%d", &play);
        if (play == 1)
        {
            printf("游戏开始\n");
            game();
        }
        else if(play != 1&& play !=0)
        {
            printf("输入错误请重新输入\n");
        }
    } while (play);
    printf("游戏结束\n");
    return 0;
}

 游戏函数

#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
#include
#include


void menu()//菜单部分
{
    printf("*****************\n");
    printf("******1.play*****\n");
    printf("******0.exit*****\n");
    printf("*****************\n");
}

void  Init_game_sc(char arr[X][Y],int x,int y)//初始化棋盘
{
    int i = 0; 
    int j = 0;
    for (i = 0; i < x; i++)
    {
        for (j = 0; j < y; j++)
        {
            arr[i][j] = '#';
        }
    }
}

void  Init_game_sc_l(char arr[X][Y], int x, int y)//初始化雷的棋盘
{
    int i = 0;
    int j = 0;
    for (i = 0; i < x+1; i++)
    {
        for (j = 0; j < y; j++)
        {
            arr[i][j] = ' ';
        }
    }
}

void game_qp(char arr[X][Y], int x, int y)//打印棋盘
{
    printf("\n");
    int i = 0; int j = 0; int z = 0;
    printf("     ");
    for (z = 0; z < x; z++)
    {
        printf("%2d ",z + 1);
        printf(" ");
    }
    printf("\n");
    printf("     ");
    for (z = 0; z < x; z++)
    {
        printf("---");
        printf(" ");
    }
    printf("\n");
    for (i = 0; i < y; i++)
    {
        printf(" %2d",i + 1);
        for (j = 0; j < x; j++)
        {
            printf(" | ", arr[i][j]);
            printf("%c", arr[i][j]);
        }
        printf(" | ", arr[i][j]);
        printf("\n");
        printf("     ");
        for (z = 0; z < x; z++)
        {
            printf("---");
            printf(" ");
        }
        printf("\n");

    }
}

int game_pd(char arr_1[X][Y],char arr[X][Y], int x, int y)//是否合法
{
    if (arr_1[x][y] != '*')
    {
        return 1;
    }
    else if (arr_1[x][y] == '*')
    {
        return -1;
    }
}

void game_kq(char arr_1[X][Y], char arr[X][Y], int x, int y)//开启棋盘 打开空棋盘位置
{
    arr[x][y] = arr_1[x][y];
    if (arr_1[x][y] != '0')
    {
        if(arr_1[x][y] == ' ')
        arr_1[x][y] = '0';
        if (x > 0)
        {
            if (arr_1[x - 1][y] == ' ')
            {
                game_kq(arr_1, arr, x - 1, y);
            }
            if (arr_1[x - 1][y] != ' ' && arr_1[x - 1][y] != '*')
            {
                arr[x - 1][y] = arr_1[x - 1][y];
            }
        }
        if (x < X - 1)
        {
            if (arr_1[x + 1][y] == ' ')
            {
                game_kq(arr_1, arr, x + 1, y);
            }
            if (arr_1[x + 1][y] != ' ' && arr_1[x + 1][y] != '*')
            {
                arr[x + 1][y] = arr_1[x + 1][y];
            }
        }
        if (y > 0)
        {
            if (arr_1[x][y - 1] == ' ')
            {
                game_kq(arr_1, arr, x, y - 1);
            }
            if (arr_1[x][y - 1] != ' ' && arr_1[x][y - 1] != '*')
            {
                arr[x][y - 1] = arr_1[x][y - 1];
            }
        }
        if (y < Y - 1)
        {
            if (arr_1[x][y + 1] == ' ')
            {
                game_kq(arr_1, arr, x, y + 1);
            }
            if (arr_1[x][y + 1] != ' ' && arr_1[x][y + 1] != '*')
            {
                arr[x][y + 1] = arr_1[x][y + 1];
            }
        }
    }
}

void game_scqp(char arr_1[X][Y])//集成炸弹生成 炸弹周围数字检测生成
{
    for (int l = L;l > 0;l--)//炸弹生成
    {
        int x = (rand() % X + 1);//0-9
        int y = (rand() % Y + 1);//0-9
        if(arr_1[x][y] != '*')
        {
            arr_1[x][y] = '*';
        }
        else
        {
            l += 1;
        }
    }
    for (int i = 0; i < X; i++)
    {
        for (int j = 0; j < Y; j++)
        {

            if (arr_1[i][j] == '*')
            {
                continue;
            }
            else
            {
                int a;
                int b;
                int count = 0;
                for (a = -1; a < 2; a++)
                {
                    for (b = -1; b < 2; b++)
                    {
                        if (i + a < 0 || i + a >= X || j + b < 0 || j + b >= Y)
                        {
                            continue;
                        }
                        if (arr_1[i + a][j + b] == '*')
                        {
                            count++;
                        }
                    }
                }
                if (count != 0)
                {
                    arr_1[i][j] = count + '0';
                }
            }
        }
    }
}

int gameover(char arr[X][Y])
{
    int count = 0; int i = 0; int j = 0;
    for (i = 0; i < X; i++)
    {
        for (j = 0; j < Y; j++)
        {
            if (arr[i][j] == '#')
            {
                count++;
            }
        }
    }
    return count;
}

void game()
{
    srand((unsigned int)time(NULL));//设置随机数的基础值
    int x; int y; int z;
    char arr[X][Y] = { 0 };//这个是开棋盘
    char arr_1[X][Y] = { 0 };//这个是要生成雷的位置
    Init_game_sc(arr,X,Y);//初始化外棋盘
    Init_game_sc_l(arr_1, X, Y);//初始化内棋盘
    printf("   左上角第一个为1 1 第二个为 1 2\n");
    game_qp(arr, X, Y);//打印棋盘
    game_scqp(arr_1);//生成炸弹 生成炸弹周围的数字
    do//基础设置结束后游戏内部的代码
    {
        printf("请输入你要打开的位置>>");
        scanf("%d %d", &x, &y);
        while (1)
        {
            x -= 1; y -= 1;
            if (x >= X || x < 0 || y >= Y || y < 0)
            {
                printf("坐标输入错误请重新输入");
                printf("请输入你要打开的位置>>");
                scanf("%d %d", &x, &y);
            }
            else
            {
                break;
            }
        }
        int cango = game_pd(arr_1,arr, x, y);//判断是否合法,可以合并到这里面
        if (cango == 1)
        {
            game_kq(arr_1, arr, x, y);//打开棋盘内的空位置 并且变成0
        }
        else if (cango == -1)
        {
            printf("踩雷了,游戏失败");
            game_qp(arr_1, X, Y);
            break;
        }
        z = gameover(arr);//判断游戏是否结束
        if (z == L)
        {
            printf("游戏胜利\n");
            game_qp(arr_1, X, Y);
            break;
        }
        game_qp(arr, X, Y);
    } while (1);
    //game_qp(arr,X,Y);
}

 后言,我的代码并不是最简化,按照直接的思路来写,希望大家能指出不好的地方,分享好的部分给我学习。

你可能感兴趣的:(#,C语言程序应用,C语言,c语言)