我正在开发一个项目,它基本上是一个带有游戏逻辑的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)
这是其中i从发送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,这是完全随机的)
这些是解析器调用的perdicates:
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一个电脑的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
is 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.