C语言程序设计——数组:扫雷

同样根据鹏哥的讲解与思路,自己动手成功实现了扫雷的机制。

唯一难为住的地方:在用递归实现多个不是雷的位置连续显示,自己试着写了一下,结果难以算法自洽,bug很多,计算繁琐,无奈放弃。就在一筹莫展的时候玩了两把扫雷,在玩的过程中有了新的递归实现方法,最后终于实现!

失败的代码也以注释的形式放出来,毕竟是成功路上的一部分~

main.c

#include "game.h"

char mine[ROWS][COLS] = {0};
char show[ROWS][COLS] = {0};

int main()
{
    play();
    return 0;
}

game.h

#ifndef GAME_H_INCLUDED
#define GAME_H_INCLUDED



#endif // GAME_H_INCLUDED


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

#define ROW 9
#define COL 9

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

#define minecount 10

char mine[ROWS][COLS];
char show[ROWS][COLS];


void game();

int Howmany(char board[ROWS][COLS],int x,int y);

void Showing(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col,int x,int y);

void Minesweeper(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col);

void putmine(char board[ROWS][COLS],int row,int col);

void Displayboard(char board[ROWS][COLS],int row,int col);

void Initboard(char board[ROWS][COLS],int row,int col,char flag);

void play();

void menu();

test.c

#include "game.h"

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

void play()
{
    do
    {
        int input = 0;
        menu();
        printf("请输入:>");
        scanf("%d",&input);
        if(input == 1)
        {
            game();
        }
        else
        {
            if(input == 0)
            {
                printf("退出游戏\n");
                break;
            }
            else
            {
                printf("输入错误,请重新输入");
            }
        }
    }while(1);
}

//初始化,mine数组未放雷的地方是0,show没有打开的地方是*
void Initboard(char board[ROWS][COLS],int row,int col,char flag)
{
    int i = 0;
    int j = 0;
    for(i=0;i<row;i++)
    {
        for(j=0;j<col;j++)
        {
            board[i][j] = flag;
        }
    }
}

//打印棋盘界面,棋盘是9*9的尺寸
void Displayboard(char board[ROWS][COLS],int row,int col)
{
    int i = 0;
    int j = 0;
    int k = 0;
    printf("  ");
    for(k=1;k<=col;k++) //列号
    {
        printf("%d ",k);
    }
    for(i=1;i<=row;i++)
    {
        printf("\n");
        printf("%d ",i); //行号
        for(j=1;j<=col;j++)
        {
            printf("%c ",board[i][j]);
        }
    }
    printf("\n");
}

//布置雷,雷用1来表示
void putmine(char board[ROWS][COLS],int row,int col)
{
    srand((unsigned int)time(NULL));
    int count = 0;
    int x,y;
    while(count<minecount)
    {
        x = rand()%row + 1;
        y = rand()%col + 1;
        if(board[x][y] == '0')
        {
            board[x][y] = '1';
            count++;
        }
    }
}

//扫雷,用户输入坐标进行扫雷,如果是雷,游戏结束,否则提示用户该处九宫格雷的数量
void Minesweeper(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col)
{
    int in_x = 0;
    int in_y = 0;
    int remain = row * col;
    while(remain > minecount)
    {
        printf("\n请输入坐标(例:1 1):>");
        scanf("%d %d",&in_x,&in_y);
        if(in_x<=row&&in_x>0&&in_y<=col&&in_y>0)
        {
            if(show[in_x][in_y] == '*')
            {
                if(mine[in_x][in_y] == '0')
                {
                    //int ret = Howmany(mine,in_x,in_y);
                    //show[in_x][in_y] = ret + '0';
                    //remain--;
                    Showing(mine,show,row,col,in_x,in_y);
                    int i,j;
                    remain = 0;
                    for(i=1;i<=row;i++)
                    {
                        for(j=1;j<=col;j++)
                        {
                            if(show[i][j]=='*')
                            {
                                remain++;
                            }
                        }
                    }
                    Displayboard(show,ROW,COL);
                }
                else
                {
                    printf("踩雷啦,完蛋!\n");
                    break;
                }
            }
            else
            {
                printf("该坐标已经扫过啦,快换一个\n");
            }
        }
        else
        {
            printf("你看看你的坐标合理嘛,重新输!\n");
        }
    }
    if(remain == minecount)
    {
        printf("\n\n\n\n太厉害了,你做到了!!!\n\n");
        Displayboard(mine,ROW,COL);
        printf("\n");
        Displayboard(show,ROW,COL);
    }
}

//计算雷的数量,因为雷是用字符表示,所以变成数字需要字符之间做差
int Howmany(char board[ROWS][COLS],int x,int y)
{
    int i = 0;
    int j = 0;
    int sum = 0;
    for(i=x-1;i<=x+1;i++)
    {
        for(j=y-1;j<=y+1;j++)
        {
            sum += board[i][j]-'0';
        }
    }
    return sum;
}

//当给入一个坐标(该坐标已知不为雷),要求显示所有与之连续且周围雷数量为0的方格
void Showing(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col,int x,int y)
{
    int ret = Howmany(mine,x,y);
    show[x][y] = ret + '0';
    if(ret == 0)
    {
        int i = 0,j = 0;
        for(i = x-1;i<=x+1;i++)
        {
            for(j = y-1;j<=y+1;j++)
            {
                if(show[i][j] != '*'||i<=0||i>=ROWS||j<=0||j>=COLS)
                {
                    continue;
                }
                Showing(mine,show,row,col,i,j);
            }
        }
    }
//失败啦
//    int ret = Howmany(mine,x,y);
//    show[x][y] = ret + '0';
//    int X=x;
//    int Y=y;
//    if(show[x][y] == '0' && y<=col)
//    {
//        while(show[x][++Y]!='*' && Y<=col)
//        {}
//        Showing(mine,show,row,col,x,Y);
//    }
//    Y=y;
//    if(show[x][y] == '0'&& x<=row)
//    {
//        while(show[++X][y]!='*'&& X<=row)
//        {}
//        Showing(mine,show,row,col,X,y);
//    }
//    X=x;
//    if(show[x][y] == '0' && y>=1)
//    {
//        while(show[x][--Y]!='*' && Y>=1)
//        {}
//        Showing(mine,show,row,col,x,Y);
//    }
//    Y=y;
//    if(show[x][y] == '0' && x>=1)
//    {
//        while(show[--X][y]!='*'&& X>=1)
//        {}
//        Showing(mine,show,row,col,X,y);
//    }
//    X=x;
}

void game()
{
    //创建两个二维数组,一个用于存放雷的信息(mine),另一个用于存放扫雷的信息(show)

    //初始化
    Initboard(mine,ROWS,COLS,'0');
    Initboard(show,ROWS,COLS,'*');

    //打印棋盘界面
    Displayboard(mine,ROW,COL);
    Displayboard(show,ROW,COL);

    //布置雷
    putmine(mine,ROW,COL);

    //扫雷
    Minesweeper(mine,show,ROW,COL);
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

犀利卓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值