Prolog 序言-检查X和O游戏中的获胜条件
我有一个简单的tic-tac-toe游戏,网上有很多使用min-maxing的例子,但是我只想用一个简单的例子来说明我自己的理解。 我已经在一个3x3框中显示了该板,该框具有用户可以通过以下方式选择的编号系统:Prolog 序言-检查X和O游戏中的获胜条件,prolog,Prolog,我有一个简单的tic-tac-toe游戏,网上有很多使用min-maxing的例子,但是我只想用一个简单的例子来说明我自己的理解。 我已经在一个3x3框中显示了该板,该框具有用户可以通过以下方式选择的编号系统: :- dynamic o/1. :- dynamic x/1. % The computer has made a turn, print O printBox(N) :- o(N), write('[o]'). % The player makes a turn, print X p
:- dynamic o/1.
:- dynamic x/1.
% The computer has made a turn, print O
printBox(N) :- o(N), write('[o]').
% The player makes a turn, print X
printBox(N) :- x(N), write('[x]').
% We just want to print the empty board
printBox(N) :- blankSpace(N), write('[_]').
buildBoard :- printBox(1),printBox(2),printBox(3),nl,
printBox(4),printBox(5),printBox(6),nl,
printBox(7),printBox(8),printBox(9),nl.
playersMove :-
read(X),
blankSpace(X),
assert(x(X)).
当用户从上述选项(1-9)中选择时,棋盘上会填充一个X表示人类玩家,一个O表示计算机。
现在我也有了获胜的事实:
winningLine(1,2,3).
winningLine(4,5,6).
winningLine(7,8,9).
%Winning rows from left to right
winningLine(1,4,7).
winningLine(2,5,8).
winningLine(3,6,9).
%Winning diagnolly
winningLine(7,5,3).
winningLine(9,5,1).
所以在每次移动之后,我想检查是否有一个赢线组合被玩过,即棋盘是否包含任何赢线组合,以及玩家是否有该组合。我一直在考虑这个问题,这里可以使用findall方法,但我愿意接受建议
我的问题:如何检查董事会的获胜条件?简单答案
由于您使用的是全局游戏位置,因此我们可以假设存在一个谓词checked(Player,Square)
,该谓词保存iff PlayerPlayer
已检查SquareSquare
然后,为了查看玩家是否赢了游戏,您只需询问是否存在一条赢线,其中所有三个方块都由同一玩家检查:
is_win(Player) :-
winning_line(P1,P2,P3),
checked(Player,P1),
checked(Player,P2),
checked(Player,P3).
您可以使用assertz
生成checked/2
:
:- dynamic checked/2.
player_move(Player, Square) :- assertz(checked(Player, Square)).
更好的方法
但是,如果您不想模拟简单的游戏,您应该在单个数据项中表示您的状态,而不是将其放入全局数据库中,例如:
initial_state(board([empty, empty, empty],
[empty, empty, empty],
[empty, empty, empty]).
并相应地调整player\u move
和选中的:
/* Should make a new board from Position0 by adding the move */
player_move(Player, Square, Position0, Position) :- ...
/* Should check if a player has checked a square inside Position */
checked(Player, Square, Position) :- ...
简单的答案
由于您使用的是全局游戏位置,因此我们可以假设存在一个谓词checked(Player,Square)
,该谓词保存iff PlayerPlayer
已检查SquareSquare
然后,为了查看玩家是否赢了游戏,您只需询问是否存在一条赢线,其中所有三个方块都由同一玩家检查:
is_win(Player) :-
winning_line(P1,P2,P3),
checked(Player,P1),
checked(Player,P2),
checked(Player,P3).
您可以使用assertz
生成checked/2
:
:- dynamic checked/2.
player_move(Player, Square) :- assertz(checked(Player, Square)).
更好的方法
但是,如果您不想模拟简单的游戏,您应该在单个数据项中表示您的状态,而不是将其放入全局数据库中,例如:
initial_state(board([empty, empty, empty],
[empty, empty, empty],
[empty, empty, empty]).
并相应地调整player\u move
和选中的:
/* Should make a new board from Position0 by adding the move */
player_move(Player, Square, Position0, Position) :- ...
/* Should check if a player has checked a square inside Position */
checked(Player, Square, Position) :- ...
使用上述全局状态表示法,您基本上必须调用赢线(I,J,K)
以获得三重索引,然后对于所有这些索引,x(x)
(其中x
替换为I
,J
和K
)应保持不变;或者对于所有指数o(X)
应为hols,如:
xwin :-
winningLine(I, J, K),
x(I),
x(J),
x(K).
nwin :-
winningLine(I, J, K),
o(I),
o(J),
o(K).
win :-
xwin.
win :-
owin.
因此这里xwin/0
是满意的,假设x
的玩家有一条赢线,owin/0
是满意的,假设o
的玩家有一条赢线,win/0
是满意的,如果任何玩家赢了
但就我个人而言,我认为使用全局状态并不是解决问题的优雅方式(实际上,在大多数编程范式中,如果不是所有编程范式的话)。在这里,您不能使用Prolog强大的回溯机制,而且如果您想搜索用户是否仍然存在获胜的方法,那么您不能简单地复制电路板,并在复制的电路板上运行解算器。使用上述全局状态表示,基本上,你必须调用赢线(I,J,K)
来获得三重索引,然后对于所有这些索引,x(x)
(用I
替换x
,J
和K
)应该保持不变;或者对于所有指数o(X)
应为hols,如:
xwin :-
winningLine(I, J, K),
x(I),
x(J),
x(K).
nwin :-
winningLine(I, J, K),
o(I),
o(J),
o(K).
win :-
xwin.
win :-
owin.
因此这里xwin/0
是满意的,假设x
的玩家有一条赢线,owin/0
是满意的,假设o
的玩家有一条赢线,win/0
是满意的,如果任何玩家赢了
但就我个人而言,我认为使用全局状态并不是解决问题的优雅方式(实际上,在大多数编程范式中,如果不是所有编程范式的话)。在这里,你不能使用Prolog强大的回溯机制,而且如果你想搜索用户是否还有获胜的方法,你就不能简单地复制电路板,并在复制的电路板上运行解算器。我认为简单的模式匹配可能会更容易。谢谢你的快速回复,你能不能帮我理解一下,这是如何在赢线规则中实现的?你到底是如何代表你的董事会的?你如何表示x
,o
和blank?我用更多的代码更新了这个问题,向你展示了这一点。基本上,我有动态X和O变量,当板被创建时,我放在一个字符串“[]”中,当用户输入1到9之间的一个数字时,将板重新构建成[X],进入空白数字的位置。我不相信这是一个好的方法,因为在这里你创建了一个全局状态,它还将导致大量的断言/1
s和收回/1
s,并且很容易出错,特别是当您想要搜索解决方案时。一个更简单的解决方案是构造一个通过调用传递并更新/统一的对象。我认为简单的模式匹配可能会更容易。感谢您的快速回复,您能否帮助我了解如何在Winning Line规则中实现这一点?您如何准确地表示您的董事会?你如何表示x
,o
和blank?我用更多的代码更新了这个问题,向你展示了这一点。基本上,我有动态的X和O变量,当板被创建时,我放在一个字符串“[]”中,当用户输入1到9之间的一个数字时,板被重建成[X],进入空白数字的位置。我不相信这是一个好的方法,因为这里是CR。