如何在构造函数中构建动态二维数组?——记忆游戏开发中的数组初始化问题咨询
解决记忆游戏中游戏面板二维数组初始化的问题
让我来帮你梳理代码里的问题,同时给出更简洁可靠的实现方案:
问题成因分析
你的代码里有几个关键错误,直接导致数组初始化失败:
局部变量覆盖成员变量
你在构造函数里写了Card gameBoard = new Card*[row];,这其实定义了一个和类成员gameBoard同名的局部变量。后续循环操作的都是这个局部变量,而类的成员变量gameBoard完全没被赋值。构造函数执行完后局部变量销毁,成员变量还是空指针,这是核心问题。类型不匹配与语法错误
循环里的Card gameBoard[i] = new Card[col];存在两个问题:- 重复定义了
gameBoard[i],且类型不兼容:new Card[col]返回Card*指针,但你试图赋值给Card类型变量,编译必然报错。 - 正确写法应该直接给数组元素赋值,不需要重复声明
Card类型。
- 重复定义了
整数除法导致列数计算错误
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
相关产品推荐
相关产品推荐

