哈斯克尔 - 国际象棋 - 下一步可能吗?

时间:2014-06-05 17:04:35

标签: haskell chess

我想写一个带有一个位置的国际象棋人物的函数,并告诉我这个数字可以通过他的下一个动作做出哪些动作。

对于国王,我能够做到这一点。

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]

1 个答案:

答案 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以及inRangefst功能轻松完成,例如:

snd

元组filter (inRange (1,8) . fst) . filter (inRange (1,8) . snd) . filter (/= (8,8)) $ [(7,9), 9,7), (7,7), (8, 8)] 的{​​{1}}实例会检查这两个组件是否为Ix,因此这相当于

(,)