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

基于栈实现的骑士巡游路径输出异常问题求助

修正骑士路径搜索程序的问题

你的代码存在几个核心问题导致路径输出异常,以下是修正后的knight.c代码,同时保留原栈实现(不修改gstack.c和gstack.h):

#include <stdio.h>
#include <stdlib.h>
#include "gstack.h"

int visited[8][8] = {0,};

typedef 
    enum {
        U2R1, U2L1, L2U1, L2D1, D2L1, D2R1, R2D1, R2U1
    } 
    dir;

char departure_h;
int departure_v;
char arrival_h;
int arrival_v;

void depart_to_arrival() {
    scanf(" %c %d", &departure_h, &departure_v);
    scanf(" %c %d", &arrival_h, &arrival_v);
    printf("---\n");
}

// 检查坐标是否合法且未访问
int is_valid(char h, int v) {
    return ('a' <= h && h <= 'h') && (1 <= v && v <= 8) && !visited[v-1][h-'a'];
}

// 计算骑士移动后的坐标
void move_knight(char h, int v, dir d, char *nh, int *nv) {
    *nh = h;
    *nv = v;
    switch(d) {
        case U2R1: *nh = h+1; *nv = v+2; break;
        case U2L1: *nh = h-1; *nv = v+2; break;
        case L2U1: *nh = h-2; *nv = v+1; break;
        case L2D1: *nh = h-2; *nv = v-1; break;
        case D2L1: *nh = h-1; *nv = v-2; break;
        case D2R1: *nh = h+1; *nv = v-2; break;
        case R2D1: *nh = h+2; *nv = v-1; break;
        case R2U1: *nh = h+2; *nv = v+1; break;
        default: break;
    }
}

void search() {
    gstack_t *hs = create_stack(64, sizeof(char));
    gstack_t *vs = create_stack(64, sizeof(int));
    // 保存每个节点已尝试到的方向,用于回溯
    gstack_t *ds = create_stack(64, sizeof(dir));

    int found = 0;

    char h = departure_h;
    int v = departure_v;
    dir current_dir = U2R1;

    // 标记起点并压入栈
    visited[v-1][h-'a'] = 1;
    push(hs, &h);
    push(vs, &v);
    push(ds, &current_dir);

    while (!is_empty(hs) && !found) {
        // 获取栈顶节点(不弹出)
        get_element(hs, get_size(hs)-1, &h);
        get_element(vs, get_size(vs)-1, &v);
        get_element(ds, get_size(ds)-1, &current_dir);

        if (h == arrival_h && v == arrival_v) {
            found = 1;
            break;
        }

        int moved = 0;
        // 遍历从当前方向开始的所有未尝试方向
        for (; current_dir <= R2U1; current_dir++) {
            char nh;
            int nv;
            move_knight(h, v, current_dir, &nh, &nv);

            if (is_valid(nh, nv)) {
                // 标记新节点为已访问
                visited[nv-1][nh-'a'] = 1;
                // 更新当前节点的已尝试方向
                pop(ds, &current_dir);
                current_dir++;
                push(ds, &current_dir);
                // 压入新节点和初始方向
                push(hs, &nh);
                push(vs, &nv);
                dir new_dir = U2R1;
                push(ds, &new_dir);
                moved = 1;
                break;
            }
        }

        if (!moved) {
            // 当前节点所有方向尝试完毕,回溯
            pop(hs, &h);
            pop(vs, &v);
            pop(ds, &current_dir);
            // 取消访问标记,允许其他路径复用
            visited[v-1][h-'a'] = 0;
        }
    }

    if (found) {
        // 顺序输出从起点到终点的路径
        for (int i = 0; i < get_size(hs); i++) {
            char h;
            int v;
            get_element(hs, i, &h);
            get_element(vs, i, &v);
            if (i > 0) printf(" ");
            printf("%c%d", h, v);
        }
        printf("\n");
    } else {
        printf("failed.\n");
    }

    // 释放栈资源
    delete_stack(hs);
    delete_stack(vs);
    delete_stack(ds);
}

int main(void) {
    depart_to_arrival();
    search();
    return EXIT_SUCCESS;
}

关键修改点说明

  1. 栈使用逻辑修正:

    • 不再一开始弹出节点,而是先处理栈顶节点,仅当所有方向尝试失败时才弹出回溯。
    • 新增方向栈记录每个节点的已尝试方向,避免重复遍历相同方向。
  2. 回溯机制完善:

    • 节点遍历完所有方向后,取消其访问标记,让其他路径可以重新访问该节点,避免遗漏可能的路径。
  3. 路径输出修复:

    • 按栈的索引顺序输出,确保路径从起点到终点的顺序正确,解决原代码倒序输出且范围错误的问题。
  4. 代码结构优化:

    • 提取is_valid和move_knight辅助函数,简化主逻辑,提升可读性。
    • 移除原代码中R2U1分支多余的d=U2R1赋值,避免逻辑干扰。

测试输入b7 e2时,程序会输出合法路径(骑士路径存在多条有效解,示例输出为b7 c5 a6 c7 e6 g7 h5 g3 e2,与你给出的预期路径均符合规则)。

内容的提问来源于stack exchange,提问作者김민성

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 03:25:55