我正在开发一个项目,该项目基本上是一个带有游戏逻辑的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).
我确实认识到,人体有点多余,但这是为了保持模式。因此,putPiece是在使用新游戏修改后返回棋盘的终结者,如果已经有一个位置可以玩,则会失败。
当一个人放置一个片段时,c ++程序会过滤坏的输入,因此putPiece失败是不可能的,因此它可以直接使用,正如你所看到的。另一方面,putpiecePC是由randoms完成的,因为它可能会失败我添加了一个基本重复第一个,如果它失败的perdicate。
问题是:当我使用putpieceHuman玩时,它的效果很奇妙,但是当我尝试使用putpiecePC时它会无限循环。
这是Sicstus日志之后的人类putpiece,人类旋转(忽略这一点),并且finnaly是一个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可以工作,所以问题不应该来自它。 为什么会这样?
答案 0 :(得分:6)
问题与实现主循环的方式有关(使用repeat)。这种编写方式只有在所有代码都是确定性的情况下才有效,因此,只有当ClientMsg
为quit
或end_of_file
时,程序才会结束,否则它将回溯到初始状态重复。
但是在你的代码中并非如此。你的代码中内置了一个非常明显的无限循环
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.