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

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()函数的行间邻居指针逻辑,未发现明显问题,但打印时仍无法遍历所有行。

疑问

  1. link()函数中neighbours[4]的行链接逻辑是否有误?
  2. make_row()的网格单元格初始化是否存在问题?
  3. 如何调试确保行指针被正确赋值?

问题分析与解决

核心错误

build()函数末尾将input赋值为prev_row,而prev_row在循环结束后指向最后一行。print()函数从input开始,通过row->neighbours[4](向下方向)遍历下一行,但最后一行没有下方的行,因此row->neighbours[4]为nullptr,只能打印一行。

对疑问的解答

  1. link()函数中neighbours[4]逻辑正确:temp_above->neighbours[4] = temp_below确实将上一行单元格的向下指针指向对应下一行单元格,问题出在input的初始指向错误,而非链接逻辑。
  2. make_row()初始化无问题:该函数正确创建了单行内左右单元格的链接(neighbours[6]左、neighbours[2]右),行内遍历逻辑正常。
  3. 调试方法:
    • 在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 00:44:50