注:私はこれをテストしていません。おそらくバギー。
私はあなたの問題は、ボードを2つの視点から考えて、「白」と「黒」と呼ぶ必要があると思います。
data Player = White | Black
otherPlayer :: Player -> Player
otherPlayer White = Black
otherPlayer Black = White
Mancalaボードは、モジュラーアースメントを示唆する円形構造です。
import Data.Vector -- More efficient version of Array
type PotNum = Int -- Use Int for simple index of pot position.
type Pot = Int -- Just record number of marbles in the pot.
Intの代わりにData.Word8を使用すると、よりコンパクトなデータ構造が得られるかもしれませんが、わかりません。今はそれを簡単に保つ。
type Board = Vector Pot
はその後isStoreはPotNumの簡単な関数とプレイヤー
isStore :: Player -> PotNum -> Bool
isStore White 0 = True
isStore Black 7 = True
isStore _ _ = False
もしているあなたは、他のプレイヤーの店舗をスキップして、ボードの周りに前方に移動したいです。..
nextPot :: Player -> PotNum -> PotNum
nextPot White 6 = 8 -- Skip Black's store
nextPot White 13 = 0
nextPot Black 12 = 0 -- Skip White's store
nextPot _ n = n + 1
各プレイヤー
playerPots :: Player -> [PotNum] -- Implementation omitted.
ための制御されたポットのリスト与えられたポット
marblesIn :: PotNum -> Board -> Int -- Implementation omitted.
でビー玉の数を今、あなたは移動機能を書くことができます。違法行為のために何も返さないようにします。
move :: Player -> PotNum -> Board -> Maybe Board -- Implementation omitted.
あなたは、これはだから今、あなたがData.Tree.unfoldを使用して、任意の開始位置からの完全なゲーム木を得ることができるすべての潜在的な動き、そして得られたボードの状態
allMoves :: Player -> Board -> [(PotNum, Board)]
allMoves p b1 = do
n <- playerPots p
case move p n b1 of
Nothing -> fail "" -- List monad has this as []
Just b2 -> return (n, b2)
を生成することができますリストモナドを使いますこれはmove関数の変形をとる。これはやや控えめです。我々はポジションをもたらした移動を知りたいが、最初のポジションはそれにつながる動きがない。したがって、おそらく。
unfoldTree関数は、現在の状態を取り、子ノードの値のリストを返す関数(以下のコードではf)を受け取ります。現在の状態と現在のノードは、単に移動したプレイヤーのトリプル、作成した移動、および結果のボードの両方です。従って "f"の最初のビット。 "f"の2番目のビットは、 "allMoves"によって返された値を変換して正しいデータを追加する "opponentMoves"関数を呼び出します。
unfoldGame :: Player -> Board -> Tree (Player, Maybe PotNum, Board)
unfoldGame p b = unfoldTree f (p, Nothing, b)
where
f (p1, n1, b1) = ((p1, n1, b1), opponentMoves (otherPlayer p1), b1
opponentMoves p2 b2 = map (\(n3, b3) -> (p2, Just n3, b3)) $ allMoves p2 b2
これでツリーを散歩するだけです。法的な動きが残っていないので、各リーフはゲームの終わりです。 unfoldGame関数は怠惰なので、現在検討中のゲーム状態を保持するメモリだけが必要です。