C++链接式网格导航异常:row->neighbours[4]首迭代后为nullptr
问题排查:C++链接式网格仅显示首行的问题
问题描述
使用C++开发游戏,通过指针创建链接结构的单元格网格,每个单元格有8个方向的邻居指针。打印网格时仅显示一行,切换下一行的row->neighbours[4]在首次迭代后变为nullptr。
完整代码
coffee_board.cc
// file coffee_board.cc #include <iostream> #include "coffee_board.h" using namespace std; //-------------------------------------------------------------------- // Inputs from user when typing in the desired option // Reads a character input while ignoring newlines char get_input() { char input; // Input from user input = cin.get(); // Read input from user while (input == '\n') { // Keeps going until first not enter input = cin.get(); // Reads first input not enter } return input; // returns first not enter input } // Reads a number input while ignoring newlines int get_number() { char input; input = get_input(); // Get input from user (not new line) int number = 0; // Number from user input initially at 0 int out_number = 0; // Number output while (input != '\n') { // Keep reading until enter if ('0' <= input && input <= '9') { // Numerical characters number = 10 * number + input - '0'; // Append new digits } if (number <= 1000) { // Sets number max to 1000 out_number = number; // If Number > 1000 no output change } input = cin.get(); // Get input from user } return out_number; // Return number <= 1000 } //-------------------------------------------------------------------- void coffee_board::get_height() { cout << "Enter the height of the board (minimum 1): "; height = get_number(); while (height < 1) { // Ensure height is valid cout << "Invalid input. Height must be at least 1. Enter again: "; height = get_number(); } } void coffee_board::get_width() { cout << "Enter the width of the board (minimum 1): "; width = get_number(); while (width < 1) { // Ensure width is valid cout << "Invalid input. Width must be at least 1. Enter again: "; width = get_number(); } } void coffee_board::get_percentage() { cout << "Enter the percentage of coffee cups (min:0 ; max:100): "; percentage = get_number(); while (percentage < 0 || percentage > 100) { cout << "Invalid input. Percentage must be between 0 and 100. Enter again: "; percentage = get_number(); } } void coffee_board::dimensions() { get_height(); // Call to get height get_width(); // Call to get width get_percentage(); // Call to get percentage of coffee } //-------------------------------------------------------------------- grid::grid ( ) { for(int i=0; i<8; i++){ neighbours[i]=nullptr; } } coffee_board::coffee_board ( ) { input = nullptr; } coffee_board::~coffee_board ( ) { // TODO } void coffee_board::make_row(grid*& input) { grid* head = nullptr; grid* tail = nullptr; for (int i = 1; i <= width; i++) { grid* temp = new grid(); temp->neighbours[6] = tail; if (tail != nullptr) { tail->neighbours[2] = temp; } else { head = temp; } tail = temp; } input = head; } void coffee_board::link(grid* upper_row, grid* lower_row) { grid* temp_above = upper_row; grid* temp_below = lower_row; while (temp_below != nullptr && temp_above != nullptr) { temp_above->neighbours[3] = temp_below->neighbours[2]; temp_above->neighbours[4] = temp_below; temp_above->neighbours[5] = temp_below->neighbours[6]; temp_below->neighbours[7] = temp_above->neighbours[6]; temp_below->neighbours[0] = temp_above; temp_below->neighbours[1] = temp_above->neighbours[2]; temp_below = temp_below->neighbours[2]; temp_above = temp_above->neighbours[2]; } } void coffee_board::build() { grid* prev_row = nullptr; grid* next_row = nullptr; make_row(next_row); // Create the first row prev_row = next_row; // Set the first row as previous for (int i = 1; i < height; i++) { make_row(next_row); // Create the next row link(prev_row, next_row); // Link the previous row to the current row prev_row = next_row; // Move to the next row } input = prev_row; // Set the last row as the board's starting point } void coffee_board::print() { if (input == nullptr) { cout << "Empty board\n"; return; } grid* row = input; grid* temp = nullptr; // Print column numbers cout << " "; for (int col_num = 1; col_num <= width; col_num++) { if (col_num <= 9) { cout << "0" << col_num << " "; } else { cout << col_num << " "; } } cout << endl; // Print the grid for (int row_num = 1; row_num <= height; row_num++) { // Print row numbers if (row_num <= 9) { cout << "0" << row_num << " "; } else { cout << row_num << " "; } temp = row; while (temp != nullptr) { cout << " ."; temp = temp->neighbours[2]; // Move to the next column in the same row } cout << endl; // Move to the next row if (row != nullptr) { row = row->neighbours[4]; // Move to the next row (downwards) } } }
coffee_board.h
// file coffee_board.h class grid { public: bool open; int number; // 7 0 1 grid* neighbours[8]; // 6 2 grid ( ); // 5 4 3 // TODO }; class coffee_board { private: grid* input; int height=15; // Board height int width=15; // Board width int percentage; int coffee_count; // New variable to track total coffees public: coffee_board(); // ~coffee_board(); // deconstructor void dimensions(); void get_height(); // Function to get height void get_width(); // Function to get width void get_percentage(); // Function to get percentage of coffee void make_row(grid*& input); void link(grid* upper_row, grid* lower_row); void build(); void print(); // TODO };
main.cc
// file main.cc #include <iostream> #include "coffee_board.h" using namespace std; int main ( ) { coffee_board Coffee_board; Coffee_board.dimensions(); Coffee_board.build(); Coffee_board.print(); return 0; }//main
Makefile
# makefile all: main.o coffee_board.o g++ -Wall -Wextra -o hetspel coffee_board.o main.o coffee_board.o: coffee_board.cc coffee_board.h g++ -Wall -Wextra -c coffee_board.cc main.o: main.cc coffee_board.h g++ -Wall -Wextra -c main.cc
问题现象
打印网格时仅显示一行,row = row->neighbours[4]语句中,row->neighbours[4]在首次迭代后变为nullptr,无法打印后续行。
已尝试操作
检查link()函数的行间邻居指针逻辑,未发现明显问题,但打印时仍无法遍历所有行。
疑问
link()函数中neighbours[4]的行链接逻辑是否有误?make_row()的网格单元格初始化是否存在问题?- 如何调试确保行指针被正确赋值?
问题分析与解决
核心错误
build()函数末尾将input赋值为prev_row,而prev_row在循环结束后指向最后一行。print()函数从input开始,通过row->neighbours[4](向下方向)遍历下一行,但最后一行没有下方的行,因此row->neighbours[4]为nullptr,只能打印一行。
对疑问的解答
link()函数中neighbours[4]逻辑正确:temp_above->neighbours[4] = temp_below确实将上一行单元格的向下指针指向对应下一行单元格,问题出在input的初始指向错误,而非链接逻辑。make_row()初始化无问题:该函数正确创建了单行内左右单元格的链接(neighbours[6]左、neighbours[2]右),行内遍历逻辑正常。- 调试方法:
- 在
build()中保存第一行的指针,打印input的地址,确认其指向第一行而非最后一行; - 在
link()函数中添加打印语句,对比temp_above->neighbours[4]和temp_below的地址,验证指针赋值是否一致; - 使用GDB调试器,在
print()函数的行遍历处设置断点,跟踪row和row->neighbours[4]的变化。
- 在
修改后的build()函数
void coffee_board::build() { grid* prev_row = nullptr; grid* next_row = nullptr; grid* first_row = nullptr; // 保存第一行的指针 make_row(next_row); // Create the first row prev_row = next_row; // Set the first row as previous first_row = prev_row; // 记录第一行 for (int i = 1; i < height; i++) { make_row(next_row); // Create the next row link(prev_row, next_row); // Link the previous row to the current row prev_row = next_row; // Move to the next row } input = first_row; // 将input设为第一行,而非最后一行 }
修改后,print()函数从第一行开始,通过row->neighbours[4]依次遍历到最后一行,即可完整打印所有行。
内容的提问来源于stack exchange,提问作者d0uble_a_b4ttery
相关产品推荐
相关产品推荐

