C/C++ 详细实现扫雷小游戏

1.前言:

本文是最基础的扫雷,排雷通过递归实现,这是原版游戏的链接扫雷基础版。本文尝试对基础版进行简单复刻。

2.代码:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef long double ld;
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define se second
#define fi first
#define endl '\n'
#define rep(i, a, b) for (int i=a;i<b;++i)
#define per(i, a, b) for (register int i=a;i>b;--i)
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const ll MOD = 998244353;
const int N = 1e5 + 10;
const int inf = 0x3f3f3f3f;
int a[11][11];
int b[11][11];
int c[8]={-1,-1,-1,0,1,1,1,0};
int d[8]={-1,0,1,1,1,0,-1,-1};
int vis[11][11];

int m,n;

void init_menu()
{
    printf("*******************\n");
    printf("****   1.play  ****\n");
    printf("****   0.exit  ****\n");
    printf("*******************\n");
    printf("请输入数字确定是否进入游戏\n");
}
void init_mine()
{    rep(i,0,10)
    {
        int x=rand()%9+1,y=rand()%9+1;
        if(!a[x][y])
        {
            a[x][y]=1;
        }
        else i--;
    }
}
void game_menu()
{
    printf("   ");
    rep(i,1,10)
        printf("%d ",i);
    printf("\n");
    rep(i,1,10) {
        printf("%d ", i);
        rep(j, 1, 10) {
            switch (b[i][j]) {
                case -1:
                    printf("  ");
                    break;
                case 0:
                    printf(" *");
                    break;
            }
            if (b[i][j] > 0)
                printf(" %d", b[i][j]);
        }
        printf("\n");
    }
}
int cnt=0;
void solve(int x,int y)
{
    if(x<1||x>9||y<1||y>9) return;//出界
    rep(i,0,8)
    {
        if(a[x+c[i]][y+d[i]])
            cnt++;
    }
    if(cnt==0)
        b[x][y]=-1;//这些是设置输出格式,方便game_menu调用
    else b[x][y]=cnt;
    cnt=0;
    if(b[x][y]>0)
        return ;
    rep(i,0,8)
    {
        if(!b[x+c[i]][y+d[i]])
            solve(x+c[i],y+d[i]);
    }
}
void input()
{
    while(1)
    {
        scanf("%d%d",&m,&n);
        if(m>0&&n<10&&m>0&&n<10&&b[m][n]!=-1)
            break;
        else printf("坐标非法,请重新输入\n");
    }
}
bool is_win()
{
    int count=0;
    rep(i,1,10)
    {
        rep(j,1,10)
        {
            if(b[m][n])
                count++;
        }
    }
    if(count==80)
        return true;
    return false;
}
void debug_menu()
{
    printf("\n");
    printf("  ");
    rep(i,1,10)
        printf("%d ",i);
    printf("\n");
    rep(i,1,10) {
        printf("%d ", i);
        rep(j, 1, 10) {
            printf("%d ",a[i][j]);
        }
        printf("\n");
    }
}
void game()
{
    init_mine();
    game_menu();
    debug_menu();
    while(1)
    {
        printf("请输入扫雷坐标\n");
        input();
        if(a[m][n])
        {
            printf("你被炸死了\n");
            return ;
        }
        solve(m,n);
        game_menu();

        if(is_win())
        {
            printf("恭喜你,挑战成功!\n");
            return;
        }
    }
}
int main() {

    int choose = 1;
    srand((uint) time(NULL));
    while (choose) {
        init_menu();
        scanf("%d", &choose);
        if (choose == 1) {
            game();
        } else if (choose != 0) {
            printf("输入数字错误,请重新输入\n");
        }
    }
    printf("游戏结束\n");
    return 0;
}

3.代码逻辑讲解:

1.总体游戏思路:

a数组埋雷,b数组通过game_menu函数显示游戏画面,通过solve函数进行递归排雷。

2.内部各函数讲解:

1.init_menu函数:

显示开始界面

void init_menu()
{
    printf("*******************\n");
    printf("****   1.play  ****\n");
    printf("****   0.exit  ****\n");
    printf("*******************\n");
    printf("请输入数字确定是否进入游戏\n");
}

2.init_menu函数:

通过srand((unsigned int) time(NULL))函数开始随机,通过rand函数随机坐标并埋雷。

void init_mine()
{    rep(i,0,10)
    {
        int x=rand()%9+1,y=rand()%9+1;
        if(!a[x][y])
        {
            a[x][y]=1;
        }
        else i--;
    }
}

3.game_menu函数:

通过b数组的改变改变游戏显示画面,如果未排则显示为'*',如果排过无雷显示‘ ’,如果有雷显示雷数量。

void game_menu()
{
    printf("   ");
    rep(i,1,10)
        printf("%d ",i);
    printf("\n");
    rep(i,1,10) {
        printf("%d ", i);
        rep(j, 1, 10) {
            switch (b[i][j]) {
                case -1:
                    printf("  ");
                    break;
                case 0:
                    printf(" *");
                    break;
            }
            if (b[i][j] > 0)
                printf(" %d", b[i][j]);
        }
        printf("\n");
    }
}

4.solve函数:

通过slove函数的递归,判断是否有雷得到cnt,cnt改变b数组,b数组判断是否返回。

int cnt=0;
void solve(int x,int y)
{
    if(x<1||x>9||y<1||y>9) return;//出界
    rep(i,0,8)
    {
        if(a[x+c[i]][y+d[i]])
            cnt++;
    }
    if(cnt==0)
        b[x][y]=-1;//这些是设置输出格式,方便game_menu调用
    else b[x][y]=cnt;
    cnt=0;
    if(b[x][y]>0)
        return ;
    rep(i,0,8)
    {
        if(!b[x+c[i]][y+d[i]])
            solve(x+c[i],y+d[i]);
    }
}

5.input函数:

输入坐标并做判断。

void input()
{
    while(1)
    {
        scanf("%d%d",&m,&n);
        if(m>0&&n<10&&m>0&&n<10&&b[m][n]!=-1)
            break;
        else printf("坐标非法,请重新输入\n");
    }
}

6.is_win函数:

判断游戏是否胜利

bool is_win()
{
    int count=0;
    rep(i,1,10)
    {
        rep(j,1,10)
        {
            if(b[m][n])
                count++;
        }
    }
    if(count==80)
        return true;
    return false;
}

7.debug_menu函数:

直接告诉你雷在哪,debug时使用。

void debug_menu()
{
    printf("\n");
    printf("  ");
    rep(i,1,10)
        printf("%d ",i);
    printf("\n");
    rep(i,1,10) {
        printf("%d ", i);
        rep(j, 1, 10) {
            printf("%d ",a[i][j]);
        }
        printf("\n");
    }
}

8.game函数:

游戏主体封装函数

void game()
{
    init_mine();
    game_menu();
    debug_menu();
    while(1)
    {
        printf("请输入扫雷坐标\n");
        input();
        if(a[m][n])
        {
            printf("你被炸死了\n");
            return ;
        }
        solve(m,n);
        game_menu();

        if(is_win())
        {
            printf("恭喜你,挑战成功!\n");
            return;
        }
    }
}

4.总结:

除了solve函数具有部分算法知识,其他主要还是以模拟为主,比较锻炼人的逻辑能力。

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
下面是一个用C++实现扫雷游戏,具体实现思路是使用二维数组来表示扫雷游戏的格子,其中0表示空格,1表示有地雷的格子,2表示已经翻开的格子,3表示标记为地雷的格子。在游戏过程中,使用递归算法来实现翻开空格的效果,同时需要判断游戏是否结束。 ```cpp #include <iostream> #include <vector> #include <ctime> #include <cstdlib> using namespace std; // 定义常量 const int BOARD_SIZE = 10; // 扫雷游戏的大小 const int MINE_NUM = 15; // 地雷的数量 // 定义二维数组表示扫雷游戏的格子 int board[BOARD_SIZE][BOARD_SIZE]; // 在指定位置放置地雷 void placeMine(int x, int y) { board[x][y] = 1; } // 随机放置地雷 void placeMines() { srand(time(nullptr)); int count = 0; while (count < MINE_NUM) { int x = rand() % BOARD_SIZE; int y = rand() % BOARD_SIZE; if (board[x][y] != 1) { placeMine(x, y); count++; } } } // 计算指定位置周围地雷数量 int countMines(int x, int y) { int count = 0; for (int i = -1; i <= 1; ++i) { for (int j = -1; j <= 1; ++j) { int nx = x + i; int ny = y + j; if (nx >= 0 && nx < BOARD_SIZE && ny >= 0 && ny < BOARD_SIZE && board[nx][ny] == 1) { count++; } } } return count; } // 打印游戏面板 void printBoard(bool showMine) { for (int i = 0; i < BOARD_SIZE; ++i) { for (int j = 0; j < BOARD_SIZE; ++j) { if (board[i][j] == 2) { cout << countMines(i, j) << " "; } else if (board[i][j] == 3) { cout << "F "; } else if (showMine && board[i][j] == 1) { cout << "* "; } else { cout << "- "; } } cout << endl; } } // 翻开指定位置的格子 bool click(int x, int y) { if (board[x][y] == 1) { return false; } else if (board[x][y] == 2) { return true; } else { board[x][y] = 2; if (countMines(x, y) == 0) { for (int i = -1; i <= 1; ++i) { for (int j = -1; j <= 1; ++j) { int nx = x + i; int ny = y + j; if (nx >= 0 && nx < BOARD_SIZE && ny >= 0 && ny < BOARD_SIZE) { click(nx, ny); } } } } return true; } } // 标记指定位置的格子 void mark(int x, int y) { if (board[x][y] == 3) { board[x][y] = 0; } else { board[x][y] = 3; } } // 判断游戏是否结束 bool isGameOver() { for (int i = 0; i < BOARD_SIZE; ++i) { for (int j = 0; j < BOARD_SIZE; ++j) { if (board[i][j] == 2) { continue; } else if (board[i][j] == 1) { continue; } else { return false; } } } return true; } int main() { // 初始化游戏面板 for (int i = 0; i < BOARD_SIZE; ++i) { for (int j = 0; j < BOARD_SIZE; ++j) { board[i][j] = 0; } } placeMines(); // 开始游戏 bool gameOver = false; while (!gameOver) { printBoard(false); cout << "请输入坐标和操作(x y c/m):"; int x, y; char op; cin >> x >> y >> op; if (op == 'm') { mark(x, y); } else if (op == 'c') { if (!click(x, y)) { gameOver = true; printBoard(true); cout << "游戏结束,你输了!" << endl; } else if (isGameOver()) { gameOver = true; printBoard(true); cout << "恭喜你,你赢了!" << endl; } } } return 0; } ``` 该程序可以实现一个简单的扫雷游戏,支持放置地雷、随机放置地雷、计算周围地雷数量、打印游戏面板、翻开格子、标记格子、判断游戏是否结束等操作。需要注意的是,由于该程序使用了递归算法来实现翻开空格的效果,可能会出现栈溢出的情况,因此需要设置递归深度的限制。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值