You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在构造函数中构建动态二维数组?——记忆游戏开发中的数组初始化问题咨询

解决记忆游戏中游戏面板二维数组初始化的问题

让我来帮你梳理代码里的问题,同时给出更简洁可靠的实现方案:

问题成因分析

你的代码里有几个关键错误,直接导致数组初始化失败:

  1. 局部变量覆盖成员变量
    你在构造函数里写了 Card gameBoard = new Card*[row];,这其实定义了一个和类成员gameBoard同名的局部变量。后续循环操作的都是这个局部变量,而类的成员变量gameBoard完全没被赋值。构造函数执行完后局部变量销毁,成员变量还是空指针,这是核心问题。

  2. 类型不匹配与语法错误
    循环里的 Card gameBoard[i] = new Card[col]; 存在两个问题:

    • 重复定义了gameBoard[i],且类型不兼容:new Card[col]返回Card*指针,但你试图赋值给Card类型变量,编译必然报错。
    • 正确写法应该直接给数组元素赋值,不需要重复声明Card类型。
  3. 整数除法导致列数计算错误
    col = ceil(size/4); 里的size/4是整数除法,比如size=6时,6/4结果是1,ceil(1)还是1,但4行1列只能放4张卡牌,根本放不下6张。你需要把size转为浮点类型再计算,才能得到正确列数。

修正后的原生数组实现

如果你坚持使用原生二维数组,下面是修正后的代码:

GameBoard.h 头文件修改

#ifndef GameBoard_h
#define GameBoard_h
#include "Deck.h"
#include <iostream>
using namespace std;

class GameBoard{
private:
    Card **gameBoard;
    Deck deck;
    // 移除不必要的Card成员,避免无意义构造
    // Card card;
    int CardsToDeal;
public:
    GameBoard(int size);
    GameBoard();
    // 添加析构函数,手动释放内存防止泄漏
    ~GameBoard();
    void initializeBoard();
};
#endif

GameBoard.cpp 实现文件修改

#include <iostream>
#include "GameBoard.h"
#include <cmath> // 使用C++标准的cmath替代C的math.h
using namespace std;

GameBoard::GameBoard(int size) {
    // 确保卡牌数量为偶数
    if (size % 2 != 0) {
        size++;
    }
    CardsToDeal = size;
    const int row = 4;
    // 转换为double计算,避免整数除法丢失精度
    int col = static_cast<int>(ceil(static_cast<double>(size) / row));
    
    // 直接初始化类成员gameBoard,不要定义局部变量
    gameBoard = new Card*[row];
    for (int i = 0; i < row; ++i) {
        // 为每一行分配列内存
        gameBoard[i] = new Card[col];
        // 若Card无默认构造函数,需调整初始化方式(如placement new)
        // 后续可通过gameBoard[i][j] = deck.dealCard();替换为实际卡牌
    }
}

// 默认构造函数初始化成员
GameBoard::GameBoard() : gameBoard(nullptr), CardsToDeal(0) {}

// 析构函数释放内存,防止内存泄漏
GameBoard::~GameBoard() {
    if (gameBoard != nullptr) {
        const int row = 4;
        for (int i = 0; i < row; ++i) {
            delete[] gameBoard[i];
        }
        delete[] gameBoard;
    }
}

更优的实现方案:使用C++容器vector

原生数组需要手动管理内存,容易出现泄漏或野指针问题。更推荐用C++标准库的vector<vector<Card>>实现二维面板,它会自动管理内存,代码更简洁安全:

修改后的头文件

#ifndef GameBoard_h
#define GameBoard_h
#include "Deck.h"
#include <iostream>
#include <vector>
using namespace std;

class GameBoard{
private:
    // 用二维vector替代原生二维数组
    vector<vector<Card>> gameBoard;
    Deck deck;
    int CardsToDeal;
public:
    GameBoard(int size);
    GameBoard();
    void initializeBoard();
};
#endif

修改后的实现文件

#include <iostream>
#include "GameBoard.h"
#include <cmath>
using namespace std;

GameBoard::GameBoard(int size) {
    if (size % 2 != 0) {
        size++;
    }
    CardsToDeal = size;
    const int row = 4;
    int col = static_cast<int>(ceil(static_cast<double>(size) / row));
    
    // 直接初始化二维vector:row行,每行col个Card对象
    gameBoard.resize(row, vector<Card>(col));
    // 后续替换卡牌时,直接通过gameBoard[i][j] = deck.dealCard(); 即可
}

// 默认构造函数无需手动初始化vector,它会自动为空
GameBoard::GameBoard() : CardsToDeal(0) {}

这种方式的优势:

  • 无需手动调用new/delete,彻底避免内存泄漏
  • vector自动处理内存扩容和释放,代码更安全
  • 可通过gameBoard.size()获取行数、gameBoard[i].size()获取列数,灵活性更高

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 13:37:50