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

Prolog N皇后问题代码报错:参数实例化不足 求解

Prolog N皇后问题代码故障排查与修复

错误原因分析

你遇到的Arguments are not sufficiently instantiated错误,根源在attack/2谓词的变量顺序和逻辑错误:

  • 变量实例化顺序问题:Prolog中is/2要求右侧表达式必须完全实例化才能计算,你在abs(X-Y) =\= L之后才用L is length([Y|Ys])给L赋值,此时L是未绑定的变量,直接触发实例化错误。
  • 逻辑颠倒问题:attack/2的作用是判断两个皇后是否存在攻击,但你写的条件是“不同列且行差不等于列差”,这其实是不攻击的条件,和safe/1里\+attack(Q, Qs)的逻辑叠加后,完全搞反了判断逻辑。

修复后的代码

% 生成1到N的列表,也可以直接用Prolog内置的numlist(1, N, Board)替代
initliste(M,N,[M|Ns]) :- M < N, M1 is M+1, initliste(M1,N,Ns).
initliste(N,N,[N]).

safe([]).
safe([Q|Qs]) :- 
    \+attack(Q, Qs, 1),  % 增加第三个参数记录行差(从1开始,因为Qs是下一行的皇后)
    safe(Qs).

% attack(X, Ys, L): X和Ys中的某个皇后存在攻击,L是当前行差
attack(X, [Y|_], L) :- 
    X =:= Y;  % 同列攻击
    abs(X-Y) =:= L.  % 对角线攻击
attack(X, [_|Ys], L) :- 
    L1 is L+1,
    attack(X, Ys, L1).

n_queens(N, L) :- 
    initliste(1,N,Board),
    permutation(Board, L),
    safe(L).

关键修改说明

  1. 给attack增加第三个参数L,用来记录当前皇后与下一个皇后的行差(从1开始,因为Qs里的皇后是当前皇后的下一行),避免每次调用length/2计算行差,效率更高也解决了实例化问题。
  2. 修正attack的逻辑:只要同列(X =:= Y)或者行差等于列差(abs(X-Y) =:= L),就判定为存在攻击,符合谓词的语义。
  3. safe/1调用attack时传入初始行差1,保证行差计算准确。

测试验证

调用n_queens(4, L),会得到两个合法解:L = [2,4,1,3] 和 L = [3,1,4,2],符合需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 10:10:34