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

Prolog求解N皇后问题时仅失败一次即终止,原因何在?

分析你的N皇后问题代码问题

嗨,我来帮你排查这个问题~你的代码核心问题是缺少皇后位置的生成逻辑,导致Prolog没有候选的位置可以回溯尝试,直接因为自由变量的意外绑定而失败。

为什么你的代码会直接返回false?

当你执行n_queens(8, Ans)时:

  1. length(Ans, 8)只是创建了一个包含8个自由变量的列表,这些变量没有任何约束(比如X/Y应该在1-8之间)。
  2. 进入queens_are_safe检查时,第一个皇后是_X1/_Y1,第二个是_X2/_Y2。当检查not(same_column(_X1/_Y1, _X2/_Y2))时,Prolog会先尝试满足same_column的条件——也就是把_X1和_X2绑定成同一个值(比如调试里的_15108),然后not(...)就会失败。
  3. 关键是:你的代码没有告诉Prolog“去尝试其他不同的X值”,因为没有生成候选位置的逻辑,所以没有回溯的空间,直接返回false。

修正后的代码及解释

我帮你调整了代码,添加了位置生成逻辑,同时修正了对角线判断的小错误:

n_queens(NumQueens, Answer) :-
    length(Answer, NumQueens),
    % 给每个皇后生成合法的位置(行和列都在1到NumQueens范围内)
    maplist(queen_position(NumQueens), Answer),
    queens_are_safe(Answer).

% 生成单个皇后的合法位置:X和Y都是1到NumQueens的整数
queen_position(NumQueens, X/Y) :-
    between(1, NumQueens, X),
    between(1, NumQueens, Y).

queens_are_safe([]).
queens_are_safe([Queen | Queens]) :-
    queen_is_safe(Queen, Queens),
    queens_are_safe(Queens).

queen_is_safe(_, []).
queen_is_safe(NewQueen, [Queen | Queens]) :-
    not(same_column(NewQueen, Queen)),
    not(same_row(NewQueen, Queen)),
    not(diagonal(NewQueen, Queen)),
    queen_is_safe(NewQueen, Queens).

% 修正对角线判断:用=:=做算术比较,并且取绝对值覆盖两个对角线方向
diagonal(X/Y, X1/Y1) :-
    abs(Y1 - Y) =:= abs(X1 - X).

same_column(X/_, X/_).
same_row(_/Y, _/Y).

关键修正点:

  1. 添加位置生成逻辑:queen_position/2结合maplist/2,给每个皇后生成1到NumQueens之间的X/Y坐标,这样Prolog有大量候选值可以回溯尝试,而不是用无约束的自由变量。
  2. 修正对角线判断:原来的Y1 - Y = X1 - X用的是Prolog的统一绑定(=),这会把变量绑定成相等的表达式,而不是做算术比较。应该用=:=来判断数值相等,并且取绝对值,这样能覆盖左上到右下、右上到左下两种对角线情况。

现在你再执行n_queens(8, Ans).,Prolog就会开始枚举所有可能的位置组合,找到满足安全条件的解,甚至可以通过按;来查看更多解。

内容的提问来源于stack exchange,提问作者PopKernel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:23:46