河内的塔 - 移动列表,检查是否有效

时间:2015-05-04 12:00:40

标签: haskell functional-programming towers-of-hanoi

我在Haskell的编程任务中挣扎。 我必须写一个函数:

move ::([Move],Towers) -> ([Move],Towers)

获取移动列表和游戏配置。该函数必须检查第一次移动是否有效,然后执行此移动。您可以在下面看到该功能的可能输出。我对Haskell很陌生,这个编程任务对我来说很重要。我不知道如何以及从哪里开始。解决这个问题的基本策略是什么?我真的很想学习它,如果你能给我一些建议,我会很高兴。

由于

 type Position = Int
 type Move     = (Position,Position)
 type Towers   = ([Int],[Int],[Int])

 hanoi :: Int -> Position -> Position -> [Move]
 hanoi 1 i j = [(i, j)]
 hanoi n i j = (hanoi (n-1) i other) ++ [(i, j)] ++ (hanoi (n-1) other j)
     where
        other = 1+2+3-i-j

输出:move ::([Move],Towers) -> ([Move],Towers)

> hanoi 3 1 3 [(1,3),(1,2),(3,2),(1,3),(2,1),(2,3),(1,3)]
> move (it, ([1,2,3],[],[])) ([(1,2),(3,2),(1,3),(2,1),(2,3),(1,3)],([2,3],[],[1])) 
> move it ([(3,2),(1,3),(2,1),(2,3),(1,3)],([3],[2],[1]))
> move it ([(1,3),(2,1),(2,3),(1,3)],([3],[1,2],[]))
> move ([(1,4)],([3],[1,2],[])) ([],*** Exception: Move not valid!
> move ([(1,2),(1,3)],([3,4],[1,2],[])) ([(2,3)],([4],*** Exception: Disc is to big!

1 个答案:

答案 0 :(得分:2)

move ::([Move],Towers) -> ([Move],Towers)
move ([],t) = ([],t)
move (x:xs,t) = move (xs,move1 x t)

move1::Move->Towers->Towers
move1 (i,j) (a,b,c)
    | i==1 && j==2 && not (null a) = if inf a b then (tail a,head a:b,c) else error "Disk too large"
    | i==1 && j==3 && not (null a) = if inf a c then (tail a,b,head a:c) else error "Disk too large"
    | i==2 && j==1 && not (null b) = if inf b a then (head b:a,tail b,c) else error "Disk too large"
    | i==2 && j==3 && not (null b) = if inf b c then (a,tail b,head b:c) else error "Disk too large"
    | i==3 && j==1 && not (null c) = if inf c a then (head c:a,b,tail c) else error "Disk too large"
    | i==3 && j==2 && not (null c) = if inf c b then (a,head c:b,tail c) else error "Disk too large"
    | otherwise = error "Move not valid"

inf :: [Int]->[Int]->Bool
inf a b = null b || head a < minimum b