基於c++的排雷小遊戲二次開發

鱼鱼游發表於2024-03-05

原始碼地址
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;
    }
}

改進後流程圖

心得

透過這次二次開發,我學習到開發小遊戲除了要完成基本功能外,還要儘可能提高使用者體驗,遊戲過於單一則遊戲壽命不會長久,要有創新思想,為遊戲增添新的功能以延長遊戲壽命,要事先調查使用者的需求,,瞭解使用者想要哪些功能,以便更好的開發遊戲,避免浪費時間做無用功。在修改程式碼時,要注意新增功能與之前的功能是否衝突,將程式碼分解為模組和函式,每個模組負責一個特定的功能,是個不錯的避免錯誤發生的方法。

相關文章