You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何实现记忆配对游戏中用户自定义n×n配对矩阵的生成与读写

自定义规格配对记忆游戏实现方案

没问题,我帮你把原本固定6×6的记忆配对游戏改成支持用户自定义矩阵规格的版本,同时实现自动生成成对数字矩阵、写入文件再读取的完整流程。下面是具体的实现细节和完整代码:

一、核心需求拆解

首先明确我们要实现的功能:

  • 允许用户输入矩阵的行数和列数(注意:必须是偶数×偶数,因为要生成成对数字,总元素数得是偶数
  • 自动生成包含成对数字的随机矩阵,每个数字恰好出现两次
  • 将生成的矩阵写入grid.txt文件
  • 修改原有游戏逻辑,适配动态规格的矩阵

二、关键修改点说明

  1. 动态规格校验:添加了输入校验逻辑,确保用户输入的行×列结果是偶数,否则提示重新输入
  2. 随机矩阵生成:先用一维数组存储所有成对数字,再用random_shuffle打乱顺序,最后转成二维矩阵,保证每个数字刚好出现两次
  3. 文件读写适配:把所有硬编码的6替换成动态的rowscols变量,支持任意合法规格的矩阵
  4. 游戏输入优化:添加了用户输入的合法性检查,比如不能选已配对的单元格、不能超出矩阵范围,提升游戏体验

三、完整代码实现

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <fstream>
#include <string>
#include <numeric>
#include <limits>
using namespace std;

// 全局变量存储矩阵规格
int rows, cols;
// 游戏相关的二维向量
vector<vector<int> > game_grid;
vector<vector<int> > hidden_grid;
vector<vector<int> > guessed;

// 生成并写入配对矩阵到文件
void generate_and_write_grid() {
    // 校验矩阵规格合法性(总元素数必须为偶数)
    while (true) {
        cout << "请输入矩阵的行数:";
        cin >> rows;
        cout << "请输入矩阵的列数:";
        cin >> cols;
        if ((rows * cols) % 2 != 0) {
            cout << "错误:矩阵总元素数必须是偶数,请重新输入!" << endl;
        } else {
            break;
        }
    }

    // 初始化随机种子,保证每次生成不同矩阵
    srand(time(0));

    // 创建包含成对数字的一维数组
    int total_elements = rows * cols;
    vector<int> nums(total_elements);
    int num_pairs = total_elements / 2;
    for (int i = 0; i < num_pairs; ++i) {
        nums[2*i] = i + 1; // 用1开始的数字,避免和隐藏标记-1冲突
        nums[2*i + 1] = i + 1;
    }

    // 打乱数组顺序
    random_shuffle(nums.begin(), nums.end());

    // 转换为二维矩阵
    game_grid.clear();
    int idx = 0;
    for (int i = 0; i < rows; ++i) {
        vector<int> row;
        for (int j = 0; j < cols; ++j) {
            row.push_back(nums[idx++]);
        }
        game_grid.push_back(row);
    }

    // 写入文件
    ofstream output_file("grid.txt");
    if (output_file) {
        for (int i = 0; i < rows; ++i) {
            for (int j = 0; j < cols; ++j) {
                output_file << game_grid[i][j] << " ";
            }
            output_file << endl;
        }
        output_file.close();
        cout << "矩阵已成功生成并写入grid.txt!" << endl;
    } else {
        cout << "错误:无法写入文件!" << endl;
        exit(1);
    }
}

// 修改后的初始化函数,读取动态规格的矩阵
void initialize_grid() {
    ifstream input_file("grid.txt");
    if (!input_file) {
        cout << "Womp. File open failed!";
        exit(1);
    }

    game_grid.clear();
    hidden_grid.clear();
    guessed.clear();

    int num;
    for (int i = 0; i < rows; ++i) {
        vector<int> row; // 存储真实数字的网格
        vector<int> row2; // 隐藏网格,-1表示未翻开
        vector<int> row3; // 标记已配对的网格,1表示已配对
        for (int j = 0; j < cols; ++j) {
            if (input_file >> num) row.push_back(num);
            row2.push_back(-1);
            row3.push_back(0);
        }
        game_grid.push_back(row);
        hidden_grid.push_back(row2);
        guessed.push_back(row3);
    }
    cout << "Get ready, Challenger!" << endl << endl;
    input_file.close();
}

// 修改后的完整网格打印(调试用)
void print_grid() {
    cout << "Game grid (debug use)" << endl;
    cout << string(cols * 4 + 1, '-') << endl; // 动态生成分隔线
    for (int i = 0; i < rows; ++i) {
        cout << " | ";
        for (int j = 0; j < cols; ++j) {
            cout << game_grid[i][j] << " | ";
        }
        cout << endl << string(cols * 4 + 1, '-') << endl;
    }
    cout << endl;
}

// 修改后的隐藏网格打印,处理配对逻辑
void print_hidden_grid(int r1 = -1, int r2 = -1, int c1 = -1, int c2 = -1) {
    cout << "Attempt:" << endl;
    if (r1 != -1) {
        hidden_grid[r1][c1] = game_grid[r1][c1];
    }
    if (r2 != -1) {
        hidden_grid[r2][c2] = game_grid[r2][c2];
    }

    // 打印网格
    cout << string(cols * 4 + 1, '-') << endl;
    for (int i = 0; i < rows; ++i) {
        cout << " | ";
        for (int j = 0; j < cols; ++j) {
            if (hidden_grid[i][j] > -1) {
                cout << hidden_grid[i][j] << " | ";
            } else {
                cout << "  | "; // 空格对齐,保证网格美观
            }
        }
        cout << endl << string(cols * 4 + 1, '-') << endl;
    }
    cout << endl;

    // 处理配对结果
    if (r1 != -1) {
        if (game_grid[r1][c1] == game_grid[r2][c2]) {
            guessed[r1][c1] = 1;
            guessed[r2][c2] = 1;
            cout << "You have a match!" << endl << endl;
        } else {
            // 让用户看清数字后再隐藏
            cout << "No match... hiding numbers in 2 seconds..." << endl;
            system("pause"); // 跨平台可替换为this_thread::sleep_for(chrono::seconds(2))
            hidden_grid[r1][c1] = -1;
            hidden_grid[r2][c2] = -1;
        }
    }
    cout << endl << endl;
}

// 修改后的当前状态网格打印
void print_current_grid() {
    cout << "Current Grid:" << endl;
    cout << string(cols * 4 + 1, '-') << endl;
    for (int i = 0; i < rows; ++i) {
        cout << " | ";
        for (int j = 0; j < cols; ++j) {
            if (hidden_grid[i][j] > -1) {
                cout << hidden_grid[i][j] << " | ";
            } else {
                cout << "  | ";
            }
        }
        cout << endl << string(cols * 4 + 1, '-') << endl;
    }
    cout << endl << endl;
}

// 检查游戏是否结束(所有单元格已配对)
bool is_game_over() {
    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < cols; ++j) {
            if (guessed[i][j] == 0) {
                return false;
            }
        }
    }
    return true;
}

// 游戏主逻辑
void play_game() {
    while (!is_game_over()) {
        int r1, c1, r2, c2;
        print_current_grid();

        // 输入第一个坐标
        cout << "Enter first row (0 to " << rows-1 << "): ";
        while (!(cin >> r1) || r1 < 0 || r1 >= rows) {
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
            cout << "Invalid input! Enter first row (0 to " << rows-1 << "): ";
        }
        cout << "Enter first column (0 to " << cols-1 << "): ";
        while (!(cin >> c1) || c1 < 0 || c1 >= cols || guessed[r1][c1] == 1) {
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
            if (guessed[r1][c1] == 1) {
                cout << "This cell is already matched! Enter another column: ";
            } else {
                cout << "Invalid input! Enter first column (0 to " << cols-1 << "): ";
            }
        }

        // 显示第一个选中的单元格
        print_hidden_grid(r1, -1, c1, -1);

        // 输入第二个坐标
        cout << "Enter second row (0 to " << rows-1 << "): ";
        while (!(cin >> r2) || r2 < 0 || r2 >= rows || guessed[r2][c2] == 1) {
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
            if (guessed[r2][c2] == 1) {
                cout << "This cell is already matched! Enter another row: ";
            } else {
                cout << "Invalid input! Enter second row (0 to " << rows-1 << "): ";
            }
        }
        cout << "Enter second column (0 to " << cols-1 << "): ";
        while (!(cin >> c2) || c2 < 0 || c2 >= cols || (r2 == r1 && c2 == c1) || guessed[r2][c2] == 1) {
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
            if (r2 == r1 && c2 == c1) {
                cout << "Cannot choose the same cell! Enter another column: ";
            } else if (guessed[r2][c2] == 1) {
                cout << "This cell is already matched! Enter another column: ";
            } else {
                cout << "Invalid input! Enter second column (0 to " << cols-1 << "): ";
            }
        }

        // 处理配对并更新界面
        print_hidden_grid(r1, r2, c1, c2);
    }

    cout << "Congratulations! You've matched all pairs! Game over!" << endl;
}

int main() {
    generate_and_write_grid();
    initialize_grid();
    // print_grid(); // 如需调试查看完整矩阵,取消注释此行
    play_game();
    return 0;
}

四、使用说明

  1. 运行程序后,首先输入矩阵的行数和列数,必须保证两者乘积是偶数(比如3×4、10×10都可以)
  2. 程序会自动生成随机配对矩阵并写入grid.txt
  3. 游戏过程中,输入单元格的行和列索引(从0开始)来选择要翻开的数字
  4. 如果配对成功,数字会保持显示;如果失败,数字会在短暂停留后隐藏
  5. 所有数字配对完成后,游戏结束并显示恭喜信息

内容的提问来源于stack exchange,提问作者user8249477

火山引擎 最新活动