欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

扫雷

程序员文章站 2022-04-07 13:58:19
...

一个简单的扫雷,纯黑白界面
说说这个游戏功能吧:①用户可自定义行列大小,雷的数量
②增加可玩性,第一次踩到雷不会死,系统会将雷转移到其他位置
③如传统扫雷一般,若该位置周围无雷则显示周围区域直至周围有雷停止

现在说说程序吧

头文件CleanMine.h,定义两个宏变量ROW,COL,代表雷盘的行列大小,用户可根据自己喜好修改

#ifndef __Game_h__
#define __Game_h__

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

#define ROW 5
#define COL 5

void PlayGame();
void InitInsideTable(char Table[ROW][COL], int mine_nuum);
void InitFaceTable(char Table[ROW][COL]);
void FirstNotDie(char Table[ROW][COL], int row, int col);
void UpdateInsideTable(char Table[ROW][COL]);
int  Is_Die(char Table[ROW][COL], int row, int col);
int Is_Win(char NowTable[ROW][COL]);
int  account_sign_num(char Table[ROW][COL],char sign, int row, int col);


#endif // !__Game_h__

然后就是功能函数的实现。Function.c

函数用来初始化玩家界面的棋盘,全部置为‘+’

void InitFaceTable(char Table[ROW][COL])//初始化玩家的桌面
{
    memset(Table, '+', ROW * COL * sizeof(char));
}

这个函数用来初始化后台棋盘,生成随机雷,用‘*’代表雷。之后调用UpdateInsideTable(Table)函数,更新其他非雷位置.

void InitInsideTable(char Table[ROW][COL], int mine_num)//初始化后台桌面
{
    int rand_row;
    int rand_col;


    srand((unsigned int)time(NULL));

    while (mine_num)
    {
        rand_row = rand() % ROW ;
        rand_col = rand() % COL ;

        if (Table[rand_row][rand_col] != '*')
        {
            Table[rand_row][rand_col] = '*';
        }
        else
            continue;

        mine_num--; 
    } 

    UpdateInsideTable(Table);

}

之后是UpdateInsideTable(char Table[ROW][COL])函数,调用 account_sign_num(char Table[ROW]函数统计周围雷的数量,然后将雷数转换为对应字符数字赋值

void UpdateInsideTable(char Table[ROW][COL])
{
    int i;
    int j;

    for (i = 0; i < ROW; i++)
        for (j = 0; j < COL; j++)
        {
            if ('*' != Table[i][j])
            {
                Table[i][j] = account_sign_num(Table,'*', i, j) + 48;
            }
        }
}

之后就是上面代码所调用的account_sign_num(char Table[ROW]函数,统计周围雷的数量

int  account_sign_num(char Table[ROW][COL],char sign,int row, int col)//显示周围雷的数量
{
    int count = 0;
    int i;

    i = -1;
    while (i < 2)
    {
        if ((row - 1 < 0) || (col + i > COL - 1 || col + i < 0))
        {
            i++;
            continue;
        }

        else if (sign == Table[row - 1][col + i])
            count++;

        i++;
    }

    i = -1;
    while (i < 2)
    {
        if ((col + i < 0) || (col + i > COL - 1))
        {
            i++;
            continue;
        }

        else if (sign == Table[row][col + i])
            count++;

        i++;
    }

    i = -1;
    while (i < 2)
    {
        if ((row + 1 > ROW) || (col + i < 0) || (col + i > COL - 1))
        {
            i++;
            continue;
        }
        else if (sign == Table[row + 1][col + i])
            count++;

        i++;    
    }

    return count;
}

再之后就是展示棋盘的函数,也是打印盘的功能函数

void ShowTable(char Table[ROW][COL])//打印桌面
{
    int row;
    int col;
    int i = 0;

    printf("现在为您显示棋盘...\n");

    printf("  ");//雷盘第一行输出对应列标和格式
    for (i = 0; i < COL; i++)
    {
        printf("   %d", i);
    }
    printf("\n");
    printf("__");
    for (i = 0; i < COL; i++)
    {
        printf("____");
    }
    printf("\n");


    for (row = 0; row < ROW; row++)
    {
        printf("%d|", row);//第一列输出对应行标和格式
        for (col = 0; col < COL; col++)
        {   
            printf("%4c", Table[row][col]);
        }
        printf("\n");
        printf(" |\n");
    }
}

然后呢,是一个判断玩家是否死亡的功能函数,若为雷‘*’,则判死,否则不执行.

int Is_Die(char Table[ROW][COL],int row, int col)//判断是否死亡
{
    if ('*' == Table[row][col])
    {
        printf("瓜娃子,你炸咧...\n");
        return 1;
    }
    else
        return 0;
}

再之后就是增加可玩性的功能函数,该位置为‘*’,则将调用上面的account_sign_num()函数统计周围雷的数量重新赋值并随机生成雷,更新后台雷盘.

void FirstNotDie(char Table[ROW][COL], int row,int col)//扩展功能:让第一次踩雷不死,并在其他位置生成雷,在220-223行
{
    int mine_row;
    int mine_col;

    if (Table[row][col] == '*')
    {
        Table[row][col] = account_sign_num(Table,'*', row, col) + 48;//该位置为雷,计算周围雷的数量,重新赋值
        do
        {
            mine_row = rand() % ROW;
            mine_col = rand() % COL;
        } while (Table[mine_row][mine_col] == '*');
        Table[mine_row][mine_col] = '*';//将不是雷的随机位置变为雷
        UpdateInsideTable(Table);
    }
}

之后的ExpandAround()函数,便是判断该位置周围是否是雷,并扩展的功能函数

void ExpandAround(char BackTable[ROW][COL], char PlayerTable[ROW][COL], int row, int col)
{
    int expand_time = 0;
    int i;


    expand_time = account_sign_num(BackTable, '0', row, col);
    while (expand_time)
    {

        i = -1;
        while (i < 2)
        {
            if ((row - 1 < 0) || (col + i > COL - 1 || col + i < 0))
            {
                i++;
                continue;
            }
            else if ('+' == PlayerTable[row - 1][col + i])
            {
                if ('0' == BackTable[row - 1][col + i])
                {
                    PlayerTable[row - 1][col + i] = BackTable[row - 1][col + i];
                    ExpandAround(BackTable, PlayerTable, row - 1, col + i);
                }
                else
                {
                    PlayerTable[row - 1][col + i] = BackTable[row - 1][col + i];        
                }
            }           
            i++;    
        }

        i = -1;
        while (i < 2)
        {
            if ((col + i < 0) || (col + i > COL - 1))
            {
                i++;
                continue;
            }
            else if ('+' == PlayerTable[row][col + i])
            {
                if ('0' == BackTable[row][col + i])
                {
                    PlayerTable[row][col + i] = BackTable[row][col + i];
                    ExpandAround(BackTable, PlayerTable, row , col + i);
                }
                else
                {
                    PlayerTable[row][col + i] = BackTable[row][col + i];
                }
            }
            i++;
        }

        i = -1;
        while (i < 2)
        {
            if ((row + 1 > ROW) || (col + i < 0) || (col + i > COL - 1))
            {
                i++;
                continue;
            }
            else if ('+' == PlayerTable[row + 1][col + i])
            {
                if ('0' == BackTable[row + 1][col + i])
                {
                    PlayerTable[row + 1][col + i] = BackTable[row + 1][col + i];
                    ExpandAround(BackTable, PlayerTable, row + 1, col + i);
                }
                else
                {
                    PlayerTable[row + 1][col + i] = BackTable[row + 1][col + i];
                }
            }
            i++;
        }
        expand_time--;  
    }
}

Is_Win()判赢函数,很简单。遍历显示给用户的雷盘‘+’的数量,若等于雷‘*’的数量,则赢。

int Is_Win(char NowTable[ROW][COL])//判赢实现
{
    int i;
    int j;
    int count = 0;

    for(i = 0; i< ROW; i++)
        for (j = 0; j < COL; j++)
        {
            if ('+' == NowTable[i][j])
                count++;
            else
                continue;
        }
    return count;
}

最后的PlayGame()便是该文件的入口,调用多个函数实现游戏功能,用户可以在这里修改变量mine_num的来修改雷的数量.当然也可以放开第12的ShowTable(InsideTable)函数,来显示一次雷的位置.

void PlayGame()//游戏功能实现核心
{
    char InsideTable[ROW][COL];
    char FaceTable[ROW][COL];
    int mine_num = 5;//雷的数量,建议赋值不要大于行列之积的一半的大小
    int click_time = ROW*COL - mine_num;
    int player_row;
    int player_col;

    InitInsideTable(InsideTable,mine_num);//初始化两个雷盘
    InitFaceTable(FaceTable);
    //ShowTable(InsideTable);
    ShowTable(FaceTable);

    while (Is_Win(FaceTable)!=mine_num)//判断输赢
    {
        printf("输入你选择的坐标...\n");

        scanf("%d%d", &player_row, &player_col);
        if (player_row >= 0 && player_col >= 0 && player_row < ROW && player_col < COL)
        {
            if (click_time == ROW*COL - mine_num)//第一次踩雷不死
            {
                FirstNotDie(InsideTable, player_row, player_col);
            }

            if (Is_Die(InsideTable, player_row, player_col))//如果当前位置是雷,展示并跳出循环
            {
                ShowTable(InsideTable);
                break;
            }
            else
            {
                if (InsideTable[player_row][player_col] == '0')
                {
                    ExpandAround(InsideTable, FaceTable, player_row, player_col);
                    ShowTable(FaceTable);
                }
                else
                {
                    FaceTable[player_row][player_col] = InsideTable[player_row][player_col];
                    ShowTable(FaceTable);           
                }
                click_time--;
            }
        }
        else
            printf("输入有误,请重新输入...");
    }

    if (Is_Win(FaceTable) == mine_num)
    {
        printf("恭喜你排雷成功...\n");
        ShowTable(FaceTable);
    }


}

第三个文件GameAchieve.c,展示玩家界面,也是整个程序的入口。switch()函数根据玩家的选择做出相应的功能实现.

#define _CRT_SECURE_NO_WARNINGS
#include"CleanMine.h"

void Start()
{
    int choice = 0;


    while (1)
    {
        printf("*************1. Play     2 .Exit**********\n");
        printf("***************输入你的选择......*********\n");

        scanf("%d", &choice);
        switch (choice)
        {
        case 1: PlayGame();
            break;
        case 2:exit(1);
            break;
        default:
            printf("数字输入有误,请重新选择...\n");
            break;//如果default语句后面还有case则此处必须写break,若无则不可以不写
        }
    }

}

int main()
{
    Start();
}

最后展示一个贼菜的扫雷图,当然大家不要忘记评论,点赞,给我这篇博客提意见哦
扫雷

相关标签: 游戏 扫雷