面向对象蛇梯棋开发:如何正确使用已填充的指针数组作为函数参数
你遇到的问题核心出在指针数组的传递逻辑、函数参数定义,还有代码里的几个细节疏漏上,我来一步步帮你梳理修正:
1. 先解决局部变量遮蔽的隐患
你在startGame()里定义了局部的int tiles,这会直接遮蔽Game类的成员变量tiles,而且这个局部变量没初始化就用来定义数组Tiles * board[tiles];,属于未定义行为(数组大小随机,极易崩溃)。应该直接使用类的成员变量,去掉局部的int tiles定义:
void Game::startGame(){ int n1, n2, n3; // 仅保留需要的局部变量 // 直接用类成员变量tiles定义指针数组 Tiles * board[this->tiles]; // ... 后续填充逻辑 }
2. 修正错误的函数调用方式
你调用play()时传的是board[tiles],这是数组的第tiles个元素(数组索引从0开始,tiles是数组总长度,这属于越界访问),而不是数组的首地址。正确的传递方式是直接传数组名board(数组名会自动退化为指向第一个元素的指针):
// 错误写法:play(board[tiles], tiles); // 正确写法: play(board, tiles);
3. 调整play()函数的参数定义与访问方式
因为你要传递的是Tiles指针的数组(Tiles*[]),在函数参数中,数组会退化为「指向指针的指针」,所以play()的参数应该定义为Tiles** board或者Tiles* board[](两种写法等价),而不是Tiles* board(这仅代表单个Tiles指针,不是指针数组)。
另外,每个数组元素是Tiles*指针,调用成员函数时必须用->运算符(.用于直接访问对象实例,->用于指针指向的对象)。
修正后的play()代码:
头文件声明修改:
// 二选一即可 void play(Tiles** board, unsigned int nBoard); // 或者写成 void play(Tiles* board[], unsigned int nBoard);
实现代码修改:
void Game::play(Tiles** board, unsigned int nBoard){ cout<< "test" << endl; for (int i=0; i<nBoard; i++){ board[i]->showTile(); // 用->访问指针指向对象的成员函数 } }
4. 额外补充:随机数初始化
你在startGame()里用了rand(),记得在程序启动时(比如main()开头)调用srand(time(nullptr));初始化随机数种子,否则每次运行生成的蛇和梯子位置都会完全一样。
修正后的关键代码片段
startGame()完整修正版:
void Game::startGame(){ int n1 = this->tiles; // 初始全为正常格子,数量等于总格子数 int n2 = this->snakes; // 蛇的数量,直接用类成员变量 int n3 = this->ladders; // 梯子的数量,直接用类成员变量 int nTileS, nTileL; // 用类成员变量tiles定义指针数组 Tiles * board[this->tiles]; // 填充所有正常格子 for (int i=0;i<n1;i++){ board[i] = new Normal(i+1); } // 随机替换为蛇 for (int i2=0;i2<n2;i2++){ do { nTileS = rand() % this->tiles; }while (board[nTileS]->getType() != 'N'); board[nTileS] = new Snake(nTileS+1); } // 随机替换为梯子 for (int i3=0;i3<n3;i3++){ do { nTileL = rand() % this->tiles; }while (board[nTileL]->getType() != 'N'); board[nTileL] = new Ladder(nTileL+1); } // 正确调用play函数 play(board, this->tiles); }
这样修改后,play()函数就能正确遍历指针数组,调用每个Tile对象的showTile()方法了。
内容的提问来源于stack exchange,提问作者Alex López

