基于c++的排雷小游戏二次开发

lian1642 / 2024-03-06 / 原文

源代码地址
https://blog.csdn.net/weixin_45906253/article/details/121237647?spm=1001.2101.3001.6650.9&utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~Rate-9-121237647-blog-129464051.235^v43^pc_blog_bottom_relevance_base7&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~Rate-9-121237647-blog-129464051.235^v43^pc_blog_bottom_relevance_base7&utm_relevant_index=16

内容简介

该程序是一款简易的扫雷小游戏,玩家开始游戏后,先初始化游戏棋盘,然后布置雷区,接着玩家根据提示输入坐标进行排雷操作,直到排除所有非雷区域或踩到雷结束游戏。

流程图

如图,该程序的不足是作为一款排雷游戏,其内容过于单一,只有一种模式,且没有计时功能,没有行列显示,用户选择时非常容易输错坐标,原代码中游戏界面比较简单,缺少美化和交互设计,玩家体验可能不够好。原代码没有成绩录入功能,玩家一次游玩后没有任何数据保存,无法让用户感受到每次游玩的不同与自身的进步

二次开发

针对以上问题,我为游戏增加了选择难度功能,计时功能,显示行列功能(有点没对齐=……=),把文件写入文件功能,可以为用户提供更好的游玩体验

选择难度功能,代码如下

点击查看代码
    int input = 0;
    srand((unsigned int)time(NULL));
    do
    {
        menu();
        cout << "请选择: ";
        cin >> input;
        switch (input)
        {
        case 1:
            cout << "选择难度级别:" << endl;
            cout << "1. 初级(10个雷,9x9棋盘)" << endl;
            cout << "2. 中级(20个雷,12x12棋盘)" << endl;
            cout << "3. 高级(30个雷,15x15棋盘)" << endl;
            int difficulty;
            cin >> difficulty;
            cout << "开始游戏" << endl;
            game(difficulty);
            break;
        case 0:
            cout << "退出游戏" << endl;
            break;
        default:
            cout << "选择错误。请重新选择" << endl;
            break;
        }
    } while (input);
    return 0;
}
void game(int difficulty)
{
    char lay_mine[16][16]; // 存放布雷信息
    char search_mine[16][16]; // 存放排查出雷的信息
    int size = 0;
    int num_mines = 0;
    if (difficulty == 1)
    {
        size = 9;
        num_mines = 10;
    }
    else if (difficulty == 2)
    {
        size = 12;
        num_mines = 20;
    }
    else if (difficulty == 3)
    {
        size = 15;
        num_mines = 30;
    }
    initialize_mineboard(lay_mine, '0', size);
    initialize_mineboard(search_mine, '*', size);
    print_mineboard(search_mine, size);
    set_laymine(lay_mine, num_mines);
    set_searchmine(lay_mine, search_mine, size, num_mines);
}

增加了计时功能,代码如下

点击查看代码
#include <chrono>
void set_searchmine(char lay_mine[][16], char search_mine[][16], int size, int num_mines)
{
    auto start = high_resolution_clock::now();
    int i = 0;
    int j = 0;
    int flag = 0;
    while (flag < size * size - num_mines)
    {
        cout << "请输入要排查的坐标:" << endl;
        cin >> i >> j;
        if ((i >= 1 && i <= size) && (j >= 1 && j <= size))
        {
            if (lay_mine[i][j] == 'X')
            {
                cout << "很遗憾,你所输入坐标为雷区,游戏失败!" << endl;
                print_mineboard(lay_mine, size);
                break;
            }
            else
            {
                search_mine[i][j] = mine_message(lay_mine, i, j) + '0';
                flag++;
                print_mineboard(search_mine, size);
            }
        }
        else
            cout << "输入坐标不合法,请重新输入" << endl;
    }
    auto stop = high_resolution_clock::now();
    auto duration = duration_cast<seconds>(stop - start);
    cout << "游戏结束,用时:" << duration.count() << " 秒" << endl;
    if (flag == size * size - num_mines)
    {
        cout << "恭喜你,排雷成功!" << endl;
        print_mineboard(lay_mine, size);
        record_score(duration.count(), true);
    }
    else
    {
        record_score(duration.count(), false);
    }
}

增加成绩录入功能

点击查看代码
#include<fstream>
void record_score(int time, bool success);
......
void record_score(int time, bool success)
{
    ofstream myfile("scores.txt", ios::app);
    if (myfile.is_open())
    {
        if (success)
        {
            myfile << "游戏成功,用时:" << time << " 秒" << endl;
        }
        else
        {
            myfile << "游戏失败,用时:" << time << " 秒" << endl;
        }
        myfile.close();
    }
    else
    {
        cout << "无法打开文件" << endl;
    }
}

改进后如图:



改进后代码

点击查看代码
#include<iostream>
#include<fstream>
#include<cstdlib>
#include<time.h>
#include<chrono>
using namespace std;
using namespace std::chrono;

void menu();
void game(int difficulty);
void initialize_mineboard(char mine[][16], char set, int size);
void print_mineboard(char mine[][16], int size);
void set_laymine(char lay_mine[][16], int num_mines);
void set_searchmine(char lay_mine[][16], char search_mine[][16], int size, int num_mines);
int mine_message(char lay_mine[][16], int i, int j);

void record_score(int time, bool success);

int main()
{
    int input = 0;
    srand((unsigned int)time(NULL));
    do
    {
        menu();
        cout << "请选择: ";
        cin >> input;
        switch (input)
        {
        case 1:
            cout << "选择难度级别:" << endl;
            cout << "1. 初级(10个雷,9x9棋盘)" << endl;
            cout << "2. 中级(20个雷,12x12棋盘)" << endl;
            cout << "3. 高级(30个雷,15x15棋盘)" << endl;
            int difficulty;
            cin >> difficulty;
            cout << "开始游戏" << endl;
            game(difficulty);
            break;
        case 0:
            cout << "退出游戏" << endl;
            break;
        default:
            cout << "选择错误。请重新选择" << endl;
            break;
        }
    } while (input);
    return 0;
}

void menu()
{
    cout << "**********************" << endl;
    cout << "****** 扫雷游戏 ******" << endl;
    cout << "******* 1.play *******" << endl;
    cout << "******* 0.exit *******" << endl;
    cout << "**********************" << endl;
}

void game(int difficulty)
{
    char lay_mine[16][16]; // 存放布雷信息
    char search_mine[16][16]; // 存放排查出雷的信息
    int size = 0;
    int num_mines = 0;
    if (difficulty == 1)
    {
        size = 9;
        num_mines = 10;
    }
    else if (difficulty == 2)
    {
        size = 12;
        num_mines = 20;
    }
    else if (difficulty == 3)
    {
        size = 15;
        num_mines = 30;
    }
    initialize_mineboard(lay_mine, '0', size);
    initialize_mineboard(search_mine, '*', size);
    print_mineboard(search_mine, size);
    set_laymine(lay_mine, num_mines);
    set_searchmine(lay_mine, search_mine, size, num_mines);
}

void initialize_mineboard(char mine[][16], char set, int size)
{
    int i = 0;
    int j = 0;
    for (i = 0; i <= size; i++)
        for (j = 0; j <= size; j++)
            mine[i][j] = set;
}

void print_mineboard(char mine[][16], int size)
{
    int i = 0;
    int j = 0;
    cout << "   ";
    for (i = 1; i <= size; i++)
    {
        cout << "  " << i;
    }
    cout << endl;
    for (i = 1; i <= size; i++)
    {
        if (i < 10)
        {
            cout << " " << i << " ";
        }
        else
        {
            cout << i << " ";
        }
        for (j = 1; j <= size; j++)
            cout << "----";
        cout << endl;
        cout << " ";
        for (j = 1; j <= size; j++)
            cout << "| " << mine[i][j] << " ";
        cout << "|" << endl;
    }
    cout << " ";
    for (j = 1; j <= size; j++)
        cout << "----";
    cout << endl;
}

void set_laymine(char lay_mine[][16], int num_mines)
{
    int n = num_mines; // 布置雷的数量
    while (n)
    {
        int i = rand() % 15 + 1; // 随机布雷
        int j = rand() % 15 + 1;
        if (lay_mine[i][j] == '0')
        {
            lay_mine[i][j] = 'X'; // 雷的标志设为‘X’
            n--;
        }
    }
}

void set_searchmine(char lay_mine[][16], char search_mine[][16], int size, int num_mines)
{
    auto start = high_resolution_clock::now();
    int i = 0;
    int j = 0;
    int flag = 0;
    while (flag < size * size - num_mines)
    {
        cout << "请输入要排查的坐标:" << endl;
        cin >> i >> j;
        if ((i >= 1 && i <= size) && (j >= 1 && j <= size))
        {
            if (lay_mine[i][j] == 'X')
            {
                cout << "很遗憾,你所输入坐标为雷区,游戏失败!" << endl;
                print_mineboard(lay_mine, size);
                break;
            }
            else
            {
                search_mine[i][j] = mine_message(lay_mine, i, j) + '0';
                flag++;
                print_mineboard(search_mine, size);
            }
        }
        else
            cout << "输入坐标不合法,请重新输入" << endl;
    }
    auto stop = high_resolution_clock::now();
    auto duration = duration_cast<seconds>(stop - start);
    cout << "游戏结束,用时:" << duration.count() << " 秒" << endl;
    if (flag == size * size - num_mines)
    {
        cout << "恭喜你,排雷成功!" << endl;
        print_mineboard(lay_mine, size);
        record_score(duration.count(), true);
    }
    else
    {
        record_score(duration.count(), false);
    }
}

int mine_message(char lay_mine[][16], int i, int j)//所输入坐标周围雷的个数
{
    int count = 0;
    for (int x = i - 1; x <= i + 1; x++)
    {
        for (int y = j - 1; y <= j + 1; y++)
        {
            if (lay_mine[x][y] == 'X')
                count++;
        }
    }
    return count;
}

void record_score(int time, bool success)
{
    ofstream myfile("scores.txt", ios::app);
    if (myfile.is_open())
    {
        if (success)
        {
            myfile << "游戏成功,用时:" << time << " 秒" << endl;
        }
        else
        {
            myfile << "游戏失败,用时:" << time << " 秒" << endl;
        }
        myfile.close();
    }
    else
    {
        cout << "无法打开文件" << endl;
    }
}

改进后流程图

心得

通过这次二次开发,我学习到开发小游戏除了要完成基本功能外,还要尽可能提高用户体验,游戏过于单一则游戏寿命不会长久,要有创新思想,为游戏增添新的功能以延长游戏寿命,要事先调查用户的需求,,了解用户想要哪些功能,以便更好的开发游戏,避免浪费时间做无用功。在修改代码时,要注意新增功能与之前的功能是否冲突,将代码分解为模块和函数,每个模块负责一个特定的功能,是个不错的避免错误发生的方法。