C实现扫雷

实现思路

  • 定义两个字符型数组
    -mine[11][11] 用来存放电脑随机布的雷,show[9][9]用来向玩家展示游戏的界面,玩家在看不到雷的数组输入坐标,然后在布雷的数组里判断输赢,在玩家看到的游戏数组里显示该坐标周围的雷数,展开一片。
  • 布置雷
    • 设置雷数,用rand()随机产生合法的坐标,坐标从1到9,rand()%9+1,使用rand时不能忘了加 srand((unsigned int)time(NULL))。
      雷用字符1表示,其余地方存为字符0.
  • 保证第一步 不会被炸死
    • 为了让这个游戏的可玩性增加,写一个safe函数,如果玩家第一步遇到雷,把这个位置改为不是雷,在其他非雷的地方再放一颗雷。
  • 排查雷
    • 玩家输入坐标,如果这个坐标不是雷,但是周围有雷,写一个GetMineCount函数,计算这个坐标周围8个坐标的总雷数,把这个数字返回到show数组里,显示给玩家。如果这个坐标不是雷,周围也没有雷,写一个Open函数,展开这个坐标及其周围,显示为空格,用函数的递归炸开一片,直到遇到一个坐标周围有雷,则不递归了,还是显示周围的雷数。
  • 判断输赢
    • 写一个IsWin函数,计算show数组里还未展开的格数,如果等于布置的雷数,则输出玩家赢,游戏结束。


一、打印游戏界面

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

}
void test()
{
    int input = 0;
    srand((unsigned int)time(NULL));
    do
    {
        menu();
        printf("请选择:>");
        scanf("%d", &input);
        switch (input)
        {
        case 1:
            game();
            break;
        case 0:
            printf("退出游戏\n");
            break;
        default:
            printf("选择错误\n");
            break;
        }

    } while (input);

}

这里写图片描述


二、定义两个二维数组,并打印

//头文件game.h
#define  EASY_COUNT 10          
#define  ROW 9
#define  COL 9

#define  ROWS ROW+2
#define  COLS COL+2
//源文件game.c
void InitBoard(char board[ROWS][COLS],int rows,int cols,char set)
{
    memset(board, set, rows*cols*sizeof(board[0][0]));
}
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
    int i = 0;
    int j = 0;
    for (i = 0; i <= row; i++)
    {
        printf("%d ", i);   //打印列号
    }
    printf("\n");
    for (i = 1; i <= row; i++)
    {
        printf("%d ", i);    //打印行号
        for (j = 1; j <= col; j++)
        {
            printf("%c ", board[i][j]);
        }
        printf("\n");
    }
    printf("\n");

}
//源文件test.c中的game函数
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
InitBoard(mine, ROWS, COLS,'0');
InitBoard(show, ROWS, COLS,'*');

三、埋雷

void SetMine(char board[ROWS][COLS], int row, int col)
{
    int x = 0;
    int y = 0;
    int count = EASY_COUNT;
    while (count)
    {
        x = rand() % 9 + 1;
        y = rand() % 9 + 1;
      if (board[x][y] == '0')
        {
            board[x][y] = '1';
            count--;

}

   }  
} 

这里写图片描述


四、输入坐标排雷

//第一步安全
void Safe(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
    int x = 0;
    int y = 0;
    int count = 0;
    int a = 0;
    int b = 0;
    printf("请输入要排查的坐标:");
    scanf("%d%d", &x, &y);
    a = x;
    b = y;
    if (mine[x][y] == '1')
    {
        mine[x][y] = '0';
        while(1)
        {
            x = rand() % 9 + 1;
            y = rand() % 9 + 1;
            if (mine[x][y] == '0')
            {
                mine[x][y] = '1';
            }
            break;
        }

    }
    Open(mine, show, a, b);
    //DisplayBoard(mine, row, col);
    DisplayBoard(show, row, col);
}
//计算输入坐标周围的雷数
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';  //返回坐标周围的雷数
}
//把坐标周围8个格子没有雷的地方展开,周围有雷的输出数字
void Open(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
    int ret = 0;
    ret = GetMineCount(mine, x, y);
    if (ret == 0)
    {
        show[x][y] = ' ';  //不是雷改为空格
        if (x - 1 > 0 && y > 0 && show[x - 1][y] == '*')
            Open(mine, show,x-1, y);

        if (x - 1 > 0 && y+1 <= COL && show[x - 1][y+1] == '*')
            Open(mine, show, x-1, y+1);

        if (x > 0 && y+1 <=COL && show[x][y+1] == '*')
            Open(mine, show, x, y+1);

        if (x + 1 <ROW && y+1 <=COL && show[x + 1][y+1] == '*')
            Open(mine, show, x+1, y+1);

        if (x + 1 <=ROW  && y > 0 && show[x + 1][y] == '*')
            Open(mine, show, x+1, y);

        if (x + 1<=ROW && y-1 > 0 && show[x + 1][y-1] == '*')
            Open(mine, show, x+1, y-1);

        if (x > 0 && y-1 > 0 && show[x][y-1] == '*')
            Open(mine, show, x, y-1);

        if (x - 1 > 0 && y-1 > 0 && show[x - 1][y-1] == '*')
            Open(mine, show, x-1, y-1);

    }  
       else
        {
            show[x][y] = GetMineCount(mine, x , y ) + '0';
             //x,y周围有雷,显示雷的个数
        }

}
//计算数组里*的个数,判断输赢
int IsWin(char show[ROWS][COLS], int row, int col)
{
    int i = 0;
    int j = 0;
    int c = 0;
    for (i = 1; i <= row; i++)
    {
        for (j = 1; j <= col; j++)
        {
            if (show[i][j] == '*')
            {
                c++;
            }
        }
    }
    return c;
}
//输入坐标排雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
    int x = 0;
    int y = 0;
    while (1)
    {
        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 = 0;
                count = GetMineCount(mine,x,y);
                show[x][y] = count + '0';
                Open(mine, show, x, y);
                DisplayBoard(show, row, col);
                if (IsWin(show, row, col) == EASY_COUNT)  //*数等于雷数
                {
                    printf("恭喜你,排雷成功!\n");
                    DisplayBoard(mine, row, col);
                    break;
                 }  
            }
        }
        else
        {
           printf("坐标非法\n");
        }
    }

}     


以上是扫雷的全部过程,下面附上完整代码
这里写图片描述

//game.h
#ifndef _GAME_H__
#define _GAME_H__


#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <time.h>

#define  EASY_COUNT 10
#define  ROW 9
#define  COL 9

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

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 board[ROWS][COLS], int row, int col);
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);


#endif //_GAME_H__#define _CRT_SECURE_NO_WARNINGS 1

//game.c
#include "game.h"

void InitBoard(char board[ROWS][COLS],int rows,int cols,char set)
{
    memset(board, set, rows*cols*sizeof(board[0][0]));
}
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
    int i = 0;
    int j = 0;
    for (i = 0; i <= row; i++)
    {
        printf("%d ", i);
    }
    printf("\n");
    for (i = 1; i <= row; i++)
    {
        printf("%d ", i);
        for (j = 1; j <= col; j++)
        {
            printf("%c ", board[i][j]);
        }
        printf("\n");
    }
    printf("\n");

}
void SetMine(char board[ROWS][COLS], int row, int col)
{
    int x = 0;
    int y = 0;
    int count = EASY_COUNT;
    while (count)
    {
        x = rand() % 9 + 1;
        y = rand() % 9 + 1;
        if (board[x][y] == '0')
        {
            board[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 Open(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
    int ret = 0;
    ret = GetMineCount(mine, x, y);
    if (ret == 0)
    {
        show[x][y] = ' ';
        if (x - 1 > 0 && y > 0 && show[x - 1][y] == '*')
            Open(mine, show,x-1, y);

        if (x - 1 > 0 && y+1 <= COL && show[x - 1][y+1] == '*')
            Open(mine, show, x-1, y+1);

        if (x > 0 && y+1 <=COL && show[x][y+1] == '*')
            Open(mine, show, x, y+1);

        if (x + 1 <ROW && y+1 <=COL && show[x + 1][y+1] == '*')
            Open(mine, show, x+1, y+1);

        if (x + 1 <=ROW  && y > 0 && show[x + 1][y] == '*')
            Open(mine, show, x+1, y);

        if (x + 1<=ROW && y-1 > 0 && show[x + 1][y-1] == '*')
            Open(mine, show, x+1, y-1);

        if (x > 0 && y-1 > 0 && show[x][y-1] == '*')
            Open(mine, show, x, y-1);

        if (x - 1 > 0 && y-1 > 0 && show[x - 1][y-1] == '*')
            Open(mine, show, x-1, y-1);

    }
            else
        {
            show[x][y] = GetMineCount(mine, x , y ) + '0';

        }

}

int IsWin(char show[ROWS][COLS], int row, int col)
{
    int i = 0;
    int j = 0;
    int c = 0;
    for (i = 1; i <= row; i++)
    {
        for (j = 1; j <= col; j++)
        {
            if (show[i][j] == '*')
            {
                c++;
            }
        }
    }
    return c;
}

void Safe(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
    int x = 0;
    int y = 0;
    int count = 0;

    int a = 0;
    int b = 0;
    printf("请输入要排查的坐标:");
    scanf("%d%d", &x, &y);
    a = x;
    b = y;
    if (mine[x][y] == '1')
    {
        mine[x][y] = '0';
        while(1)
        {
            x = rand() % 9 + 1;
            y = rand() % 9 + 1;
            if (mine[x][y] == '0')
            {
                mine[x][y] = '1';
            }
            break;
        }

    }
    Open(mine, show, a, b);
    DisplayBoard(mine, row, col);
    DisplayBoard(show, row, col);
}

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
    int x = 0;
    int y = 0;
    while (1)
    {
        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 = 0;
                count = GetMineCount(mine,x,y);
                show[x][y] = count + '0';
                Open(mine, show, x, y);
                DisplayBoard(show, row, col);
                if (IsWin(show, r 
  ow, col) == EASY_COUNT)
                {
                    printf("恭喜你,排雷成功!\n");
                    DisplayBoard(mine, row, col);
                    break;
                 }  
            }
        }
        else
        {
            printf("坐标非法\n");
        }
    }

}
//test.c
#define _CRT_SECURE_NO_WARNINGS 1

#include "game.h"

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

}
void game()
{
    char mine[ROWS][COLS] = { 0 };
    char show[ROWS][COLS] = { 0 };
    InitBoard(mine, ROWS, COLS,'0');
    InitBoard(show, ROWS, COLS,'*');
    SetMine(mine, ROW, COL);
    DisplayBoard(mine, ROW, COL);
    DisplayBoard(show, ROW, COL);
    Safe(mine, show, ROW, COL); 
    FindMine(mine, show, ROW, COL);

}
void test()
{
    int input = 0;
    srand((unsigned int)time(NULL));
    do
    {
        menu();
        printf("请选择:>");
        scanf("%d", &input);
        switch (input)
        {
        case 1:
            game();
            break;
        case 0:
            printf("退出游戏\n");
            break;
        default:
            printf("选择错误\n");
            break;
        }

    } while (input);

}
int main()
{
    test();
    system("pause");
    return 0;
}

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

  • 4
    点赞
  • 3
    评论
  • 12
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

评论 3 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:创作都市 设计师:CSDN官方博客 返回首页

打赏作者

chlemon

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

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值