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

Prolog中如何遍历检查所有row、Column、number形式的cell事实?

问题:怎样正确遍历Prolog里的cell单元格事实?

我手头有一批用Prolog事实表示的单元格数据,每个cell/3事实包含行号、列号和对应单元格里的数字,想实现类似普通数组遍历的逻辑来检查这些单元格。我自己写了一段代码,但不仅跑不起来,还没法遍历到所有事实:

allcolored(X,Y) :- cell(X,Y,_), X1 is X - 1, Y1 is Y - 1, allcolored(X1,Y1).

问题出在哪?

这段代码有两个致命问题:

  1. 没有终止条件:递归会一直把X和Y减1,直到变成负数,这时候找不到对应的cell事实,直接就失败了,根本走不完所有可能的单元格。
  2. 遍历范围完全错了:你现在的逻辑是从(X,Y)往左上对角线递归,只能遍历到(X,Y)、(X-1,Y-1)这类在同一条对角线上的单元格,其他行或列的单元格根本碰不到。

给你两种可行的遍历方案

方案1:利用Prolog回溯特性快速遍历所有单元格

Prolog本身的回溯机制天生适合枚举所有事实,我们可以利用这个特性来遍历:

traverse_cells :-
    % 匹配一个cell事实
    cell(X, Y, Num),
    % 这里写你对每个单元格的检查逻辑,比如打印出来看看
    format('正在检查单元格(~w,~w): 数字是~w~n', [X,Y,Num]),
    % 用fail触发回溯,让Prolog去找下一个cell
    fail.
% 所有cell都遍历完后,这个子句会成功,结束遍历
traverse_cells.

调用traverse_cells.就能遍历所有cell事实,每匹配一个就执行你的检查操作,直到所有事实都被处理完。

方案2:按行/列的顺序遍历(模拟数组的遍历顺序)

如果需要像普通数组那样,先遍历第一行的所有列,再遍历第二行,这种有顺序的遍历,可以用下面的写法:

% 获取所有不重复的行号,排序后保证顺序
all_rows(Rows) :-
    findall(R, cell(R, _, _), TempRows),
    sort(TempRows, Rows).

% 获取某一行对应的所有列号,同样排序
row_cols(Row, Cols) :-
    findall(C, cell(Row, C, _), TempCols),
    sort(TempCols, Cols).

% 入口谓词:按行遍历所有单元格
traverse_by_rows :-
    all_rows(Rows),
    traverse_rows_list(Rows).

% 遍历行列表的递归终止条件:行列表为空时结束
traverse_rows_list([]).
% 遍历每一行:先处理当前行的所有列,再处理剩下的行
traverse_rows_list([CurrentRow|RestRows]) :-
    row_cols(CurrentRow, Cols),
    traverse_row_columns(CurrentRow, Cols),
    traverse_rows_list(RestRows).

% 遍历某一行的列列表的终止条件
traverse_row_columns(_, []).
% 遍历当前行的每一列:处理单元格,再处理下一列
traverse_row_columns(Row, [CurrentCol|RestCols]) :-
    cell(Row, CurrentCol, Num),
    format('检查单元格(~w,~w): 数字是~w~n', [Row,CurrentCol,Num]),
    traverse_row_columns(Row, RestCols).

这个方案会先把所有行号排序,然后逐行遍历每个行里的所有列,完全模拟普通二维数组的遍历顺序。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 09:02:43