关于范围:在Prolog中访问其谓词之外的列表

Accessing a list in Prolog outside of its predicate

我是Prolog的新手,正在从事给我带来巨大麻烦的任务。我必须编写一个解决n x n难题的程序;解决方案的谓词有两个参数,game(Size, SolList),其中Size是面板的大小,SolList是列表形式的难题的解决方案。这是教授提供的用于生成董事会的代码:

1
2
3
4
5
6
7
8
9
10
generate_board(N, Board) :-
  generate_board(N, N, Board), !.

generate_board(0, _, []).
generate_board(1, Columns, [LastRow]) :-
  row(Columns, LastRow).
generate_board(Rows, Columns, [R1|RestOfBoard]) :-
  row(Columns, R1),
  NewRows is Rows - 1,
  generate_board(NewRows, Columns, RestOfBoard).

解决难题需要"单击"板上的某些正方形。我想做的是生成一个正方形列表-例如,当Size = 5时,该列表的长度为25,从0到24,在generate_board/2谓词中(如果可能) 。然后,我希望Prolog记住该列表,并在使用其他谓词解决难题并提出解决方案时,在列表的必要元素上注册" clicks "并将其输出到控制台中。我不知道如何解决Prolog中列表的本地性的方法,因此我无所适从如何克服这一障碍。


如果您不能按照注释中的建议随意传递列表,则"断言"的一种好方法是通过断言和撤消它。

例如:

1
2
3
4
5
6
7
8
setup_board :-
   generate_board(5, L),
   assert(board(L)).

do_something :-
   retract(board(L)),
   process_board(L, L1),
   assert(board(L1)).

尽管如此,您必须要小心。如果process_board(L, L1)失败,则将撤回您的电路板,但不会声明新的电路板。

您可以通过使用prolog"如果->那么"来解决此问题:

1
2
3
do_something :-
   retract(board(L)),
   (process_board(L, L1) -> assert(board(L1)) ; assert(board(L))).

换句话说,如果process_board(L, L1)成功,则声明新板,否则重新声明旧板。