gpt4 book ai didi

debugging - 为什么prolog进入无限循环?

转载 作者:行者123 更新时间:2023-12-05 00:27:24 25 4
gpt4 key购买 nike

我正在开发一个项目,它基本上是一个具有游戏逻辑的 prolog 服务器,它与一个 c++ openGL 程序通信,该程序呈现从 prolog 接收到的信息以进行游戏绘图。

这是服务器循环,连接成功后开始:

serverLoop(Stream) :-
repeat,
write('reading'), nl,
read(Stream, ClientMsg),
write('Received: '), write(ClientMsg), nl,
write('Parsing'), nl,
parse_input(ClientMsg, MyReply),
write('formatting'), nl,
format(Stream, '~q.~n', [MyReply]),
write('Wrote: '), write(MyReply), nl,
write('flushing'), nl,
flush_output(Stream),
write('end condition'), nl,
(ClientMsg == quit; ClientMsg == end_of_file), !.

它充满了写入,因为我已经调试了几个小时。

这里需要注意的重要部分是:
parse_input(ClientMsg, MyReply)

这是我发送从 C++ 收到的所有消息的地方,目前我对 parse_input 的方法如下:
parse_input(putpieceHuman(BOARD, PIECE, LINE, COLUMN), Answer) :-
write('Parsing putpieceHuman'), nl,
drawBoard(BOARD), nl,
putpieceHuman(BOARD, PIECE, LINE, COLUMN, Answer).

parse_input(putpiecePC(BOARD, PIECE, AI), Answer):-
write('Parsing putpiecePC'), nl,
drawBoard(BOARD), nl,
putpiecePC(BOARD, PIECE, Answer, AI).

它们非常相似。第一个是播放器播放(指定播放位置),第二个是电脑播放(AI是我想让电脑拥有的智能值,我们只考虑0值,这是完全随机的)

这些是解析器调用的谓词:
putpieceHuman(BOARD, PIECE, LINE, COLUMN, NEXTBOARD):-
putPiece(BOARD, PIECE, LINE, COLUMN, NEXTBOARD).

putpiecePC(BOARD, PIECE, NEXTBOARD, 0):-
write('enter putpiecePC'), nl,
random(0, 6, LINE),
random(0, 6, COLUMN),
putPiece(BOARD, PIECE, LINE, COLUMN, NEXTBOARD).
putpiecePC(BOARD, PIECE, NEXTBOARD, 0):- write('putpiecePC failed'), putpiecePC(BOARD, PIECE, NEXTBOARD, 0).

我确实意识到 putpieceHuman 有点多余,但这是为了保持模式。因此,putPiece 是在用新游戏修改棋盘后返回棋盘的谓词,如果已经有棋子可以玩,它就会失败。

当人类放置一块时,C++ 程序会过滤错误的输入,因此 putPiece 不可能失败,因此它可以直接使用,如您所见。另一方面, putpiecePC 是由随机完成的,因此它可能会失败我添加了一个基本重复第一个的 perdicate,如果它失败了。

问题是:当我使用 putpieceHuman 玩游戏时,它工作得很好,但是当我尝试使用 putpiecePC 时,它会进入无限循环。

这是在人类 putpiece 之后的 Sicstus 日志,人类旋转(忽略这个),最后是一个 pc putpiece,请注意我上面写的内容被翻译了,日志不是所以请注意以下几点:
colocaHumano = putpieceHuman
rodaHumano -> ignore this
colocaPC = putpiecePC

好的,现在日志:
| ?- server.                                           
Accepted connection
reading
Received: colocaHumano([[[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0]]],1,5,0)
Parsing
Parsing colocaHumano
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0

formatting
Wrote: [[[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[1,0,0]],[[0,0,0],[0,0,0],[0,0,0]]]
flushing
end condition
reading
Received: rodaHumano([[[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[1,0,0]],[[0,0,0],[0,0,0],[0,0,0]]],2,1)
Parsing
Parsing rodaHumano
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
1 0 0 0 0 0

formatting
Wrote: [[[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0]],[[1,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0]]]
flushing
end condition
reading
Received: colocaPC([[[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0]],[[1,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0]]],2,0)
Parsing
Parsing colocaPC
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
1 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0

enter colocaPC
formatting
Wrote: [[[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[2,0,0],[0,0,0]],[[1,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0]]]
flushing
end condition
colocaPC failedenter colocaPC
formatting
Wrote: [[[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0]],[[1,0,0],[0,0,2],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0]]]
flushing
end condition
colocaPC failedenter colocaPC
formatting
Wrote: [[[0,0,0],[0,2,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0]],[[1,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0]]]
flushing
end condition
colocaPC failedenter colocaPC
formatting
Wrote: [[[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0]],[[1,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,2,0]]]
flushing
end condition
colocaPC failedenter colocaPC
formatting
Wrote: [[[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,2,0],[0,0,0]],[[1,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0]]]
flushing
end condition
colocaPC failedenter colocaPC
formatting
Wrote: [[[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,2],[0,0,0]],[[1,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0]]]
flushing
end condition
colocaPC failedenter colocaPC
formatting
Wrote: [[[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,2,0],[0,0,0]],[[1,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0]]]
flushing
end condition
colocaPC failedenter colocaPC
formatting
Wrote: [[[0,2,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0]],[[1,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0]]]
flushing
end condition
colocaPC failedenter colocaPC
formatting
Wrote: [[[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0]],[[1,2,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,0]]]
flushing
end condition
colocaPC failedenter colocaPC
formatting
Wrote: [[[0,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,2]],[[1,0,0],[0,0,0],[0,0,0]],[[0,0,0],[0,0,0],[0,0,
Prolog interruption (h for help)?

我还必须注意,如果我在 sicstus 的直接调用中调用 putpiecePC,它就可以工作,所以问题不应该来自它。
为什么会这样?

最佳答案

问题与您实现主循环的方式有关(使用重复)。这种编写方式只有在所有代码都是确定性的情况下才有效,因此,只有在 ClientMsg 时才有效。是 quitend_of_file程序将结束,否则它将返回到最初的重复。

但这在您的代码中并非如此。您的代码中内置了一个 super 明显的无限循环

putpiecePC(BOARD, PIECE, NEXTBOARD, 0):- 
write('putpiecePC failed'),
putpiecePC(BOARD, PIECE, NEXTBOARD, 0).

如果有理由在代码后面的任何地方回溯,这可以无限期地重复。一旦您的代码命中 ClientMsg 的最终检查,它将回溯到这个循环并永远停留在那里(它不会重新考虑证明 putpiecePC 的第一种方法,因为它认为证明它的方法已经失败——它不考虑随机性)。

就我个人而言,我真的不喜欢使用额外的逻辑结构,但如果你已经这样做了,我相信引入另一个重复可能会成功:
putpiecePC(BOARD, PIECE, NEXTBOARD, 0):-
write('enter putpiecePC'), nl,
repeat,
random(0, 6, LINE),
random(0, 6, COLUMN),
putPiece(BOARD, PIECE, LINE, COLUMN, NEXTBOARD).

不过,解决这个问题的更好方法是避免主循环中的重复逻辑,并使其成为适当的递归。

编辑:

如果你遵循这个模式,事情应该会奏效。你可以试试这个代码。只需尝试目标“循环”并在 [0, 6] 之间输入数字。 test将猜测它然后返回到主循环。 test就像你的 putpiecePC 谓词。 loop当然是主循环。
loop :- loop(ignore).                                                           
loop(q) :- !.
loop(_) :-
writeln('guess!'),
read(X),
test(X),
loop(X).

test(q).

test(X) :-
writeln('test'),
repeat,
random(0, 6, LINE),
writeln(LINE),
LINE == X.

关于debugging - 为什么prolog进入无限循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20777091/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com