我想写一个带有一个位置的国际象棋人物的函数,并告诉我这个数字可以通过他的下一个动作做出哪些动作。
对于国王,我能够做到这一点。
type Position = (Int,Int)
data Piece = Piece {
_position :: Position,
_color :: String}
nextMoves :: Piece -> [Position]
nextMoves king = filter (onTheBoard) (filter (/= (xOld,yOld))
[(x,y) | x <- [(xOld-1)..(xOld+1)], y <- [(yOld-1)..(yOld+1)]])
where
xOld = fst(_position king)
yOld = snd(_position king)
他站在(1,3)上,我的功能给了我[(1,2),(1,4),(2,2),(2,3),(2,4)]。
现在我想为主教或骑士做同样的事情。但是如何在此问题上使用过滤器? 谢谢tipp。
//编辑:我已将支票更改为帮助功能:
onTheBoard :: Position -> Bool
onTheBoard (x,y) = elem x [1..8] && elem y [1..8]
答案 0 :(得分:4)
你无法分辨Piece
是哪一块(国王,主教,骑士等)。 nextMoves king
匹配所有部分,无论它是哪种类型。要弄清楚其他部分的动作,您需要能够区分它们。你需要像
data PieceType = Pawn | Knight | Bishop | Rook | Queen | King
data Piece = Piece {
_position :: Position,
_color :: String,
_pieceType :: PieceType}
然后你可以为nextMoves
nextMoves :: Piece -> [Position]
nextMoves piece =
case _pieceType piece of
King -> filter (<= (1,1)) (filter (>= (8,8)) (filter (/= (xOld,yOld))
[(x,y) | x <- [(xOld-1)..(xOld+1)], y <- [(yOld-1)..yOld+1)]]))(yOld+1)]]))
Queen -> ...
Rook -> ...
Bishop -> ...
Knight -> ...
Pawn -> ...
where
xOld = fst(_position piece)
yOld = snd(_position piece)
您可以从其他规则中提取移动必须在棋盘上的过滤。
如果您的目标是实际的国际象棋游戏,那么移动是否有效还有其他规则取决于棋盘的其他状态。
正如Priyatham所指出的那样,你也有过滤问题。 typles Ord
的{{1}}实例首先比较元组的第一个元素,然后比较第二个元素。这意味着,例如,(,)
。这被称为词法排序,就像条目按字母顺序排列:首先是第一个字母,然后是第二个字母,等等......
您需要检查每个组件是否在范围内,这可以通过(1, 9) < (2, 0)
Data.Ix
以及inRange
和fst
功能轻松完成,例如:
snd
元组filter (inRange (1,8) . fst) . filter (inRange (1,8) . snd) . filter (/= (8,8)) $ [(7,9), 9,7), (7,7), (8, 8)]
的{{1}}实例会检查这两个组件是否为Ix
,因此这相当于
(,)