prolog - Prolog 棋子动作
问题描述
我正在使用 prolog 制作一个人工智能国际象棋游戏。我有这个板:
Board = [piece(white, rook, 1, 1), piece(white, knight, 2, 1), piece(white, bishop, 3, 1), piece(white, queen, 4, 1), piece(white, king, 5, 1), piece(white, bishop, 6, 1), piece(white, knight, 7, 1), piece(white, rook, 8, 1), piece(white, pawn, 1, 2), piece(white, pawn, 2, 2), piece(white, pawn, 3, 2), piece(white, pawn, 4, 2), piece(white, pawn, 5, 2), piece(white, pawn, 6, 2), piece(white, pawn, 7, 2), piece(white, pawn, 8, 2), piece(black, rook, 1, 8), piece(black, knight, 2, 8), piece(black, bishop, 3, 8), piece(black, queen, 4, 8), piece(black, king, 5, 8), piece(black, bishop, 6, 8), piece(black, knight, 7, 8), piece(black, rook, 8, 8), piece(black, pawn, 1, 7), piece(black, pawn, 2, 7), piece(black, pawn, 3, 7), piece(black, pawn, 4, 7), piece(black, pawn, 5, 7), piece(black, pawn, 6, 7), piece(black, pawn, 7, 7), piece(black, pawn, 8, 7)]
如您所见,板由列表表示。我正在尝试创建一个谓词来返回棋盘上给定棋子的可能动作。这些移动应该作为可能移动的列表返回。我很容易地做出了棋子的移动,但是我陷入了车和象可能的移动(水平,垂直,对角线)中,我很困惑。
编辑:这是典当动作:
in_boundaries(Col,Row):-
between(1,8,Col),
between(1,8,Row).
create_board(Board) :-
findall(Piece, initial(Piece), Board).
nonmember(X,[Y|Ys]):-
X\=Y,
nonmember(X,Ys).
nonmember(_,[]).
%% Pawn possible moves
movement(Board,piece(white,pawn,Col,Row),piece(white,pawn,Col,NewRow)):-
NewRow is Row+1,
in_boundaries(Col,NewRow),
nonmember(piece(_,_,Col,NewRow),Board). %%Check if (Col,Row+1) is empty.
movement(Board,piece(black,pawn,Col,Row),piece(black,pawn,Col,NewRow)):-
NewRow is Row-1,
in_boundaries(Col,NewRow),
nonmember(piece(_,_,Col,NewRow),Board). %%Check if (Col,Row+1) is empty.
movement(Board,piece(white,pawn,Col,Row),piece(white,pawn,NewCol,NewRow)):-
NewCol is Col-1,
NewRow is Row+1,
in_boundaries(Col,NewRow),
member(piece(black,_,NewCol,NewRow),Board). %%Check if the pawn could eat in (Col-1,Row+1).
movement(Board,piece(white,pawn,Col,Row),piece(white,pawn,NewCol,NewRow)):-
NewCol is Col+1,
NewRow is Row+1,
in_boundaries(Col,NewRow),
member(piece(black,_,NewCol,NewRow),Board). %%Check if the pawn could eat in (Col+1,Row+1).
movement(Board,piece(black,pawn,Col,Row),piece(black,pawn,NewCol,NewRow)):-
NewCol is Col-1,
NewRow is Row-1,
in_boundaries(Col,NewRow),
member(piece(black,_,NewCol,NewRow),Board). %%Check if the pawn could eat in (Col-1,Row-1).
movement(Board,piece(black,pawn,Col,Row),piece(black,pawn,NewCol,NewRow)):-
NewCol is Col-1,
NewRow is Row-1,
in_boundaries(Col,NewRow),
member(piece(black,_,NewCol,NewRow),Board). %%Check if the pawn could eat in (Col+1,Row-1).
解决方案
不幸的是,“这些动作应该作为一个可能的动作列表返回”不是在 Prolog 中处理事情的有用方法。最好的方法是写一个位置和另一个位置之间的关系来表达一个合法的举动。这种关系应该列举可能的回溯移动,而不是作为一个列表。
我们将编写一个行为如下的关系:
?- piece_moved(piece(white, rook, 2, 7), Moved).
Moved = piece(white, rook, 1, 7) ;
Moved = piece(white, rook, 3, 7) ;
Moved = piece(white, rook, 4, 7) ;
Moved = piece(white, rook, 5, 7) ;
Moved = piece(white, rook, 6, 7) ;
Moved = piece(white, rook, 7, 7) ;
Moved = piece(white, rook, 8, 7) ;
Moved = piece(white, rook, 2, 1) ;
Moved = piece(white, rook, 2, 2) ;
Moved = piece(white, rook, 2, 3) ;
Moved = piece(white, rook, 2, 4) ;
Moved = piece(white, rook, 2, 5) ;
Moved = piece(white, rook, 2, 6) ;
Moved = piece(white, rook, 2, 8) ;
false.
之后,如果你真的需要一个列表,你可以使用findall/3
:
?- findall(Moved, piece_moved(piece(white, rook, 2, 7), Moved), Moves).
Moves = [piece(white, rook, 1, 7), piece(white, rook, 3, 7), piece(white, rook, 4, 7), piece(white, rook, 5, 7), piece(white, rook, 6, 7), piece(white, rook, 7, 7), piece(white, rook, 8, 7), piece(white, rook, 2, 1), piece(..., ..., ..., ...)|...].
(顺便说一句,看看你是如何实现你的棋子移动的,这不会有什么坏处。)
我将使用以下谓词来帮助检查移动是否有效:
valid(Coordinate) :-
between(1, 8, Coordinate).
车沿一维的移动是:
piece_moved(piece(Color, rook, X, Y), piece(Color, rook, X1, Y)) :-
between(-7, 7, DeltaX),
dif(DeltaX, 0),
X1 is X + DeltaX,
valid(X1).
只要结果位置有效,这将保持Y
坐标常数并移动任意非零数,最多向左或向右移动 7 个方格。X
另一个维度的移动基本相同:
piece_moved(piece(Color, rook, X, Y), piece(Color, rook, X, Y1)) :-
between(-7, 7, DeltaY),
dif(DeltaY, 0),
Y1 is Y + DeltaY,
valid(Y1).
推荐阅读
- swift - Firebase 上传图片 | 使用 NSProgress
- python - 主机 0.0.0.0 (flask) 上的 Docker 连接被拒绝
- sql - Snowflake 是否等同于 SQL WITH(NOLOCK)
- r - R dplyr 使用条件有效地创建多个列
- javascript - 制表符和上下文菜单双击右键问题
- maven - 如何在发布中配置唯一版本
- javascript - 显示警报后隐藏模型弹出窗口
- sql - 更新 SQL Server 中的特定行和列
- linux - 为什么当我回显时,我的变量会被 BASH 中 for 循环中的下一个字符覆盖?
- python - Python从tweepy返回流数据