List.filterに複数の引数を含めるにはどうすればよいですか?List.filterに複数の引数を含めるにはどうすればよいですか?
リストをフィルタリングするための述語として機能するいくつかのパラメータを関数に追加する必要があります。
F#では、List.filterは引数を1つだけ受け入れます。しかし、私は述語が機能するために複数の引数を追加する必要があります。私の場合は
、私はパラメータとしてsourceXとsourceYを追加する必要があります。結論として
let jumpOptions space =
match space with
| Allocated p -> match p with
| Red (ch,xy) -> xy = (sourceX + 1, sourceY - 1) ||
xy = (sourceX - 1, sourceY - 1)
| Black (ch,xy) -> xy = (sourceX + 1, sourceY + 1) ||
xy = (sourceX - 1, sourceY + 1)
| _ -> false
let jumpsForSoldier piece positions =
match piece with
| Black (ch,pos) -> positions |> List.filter jumpOptions
| Red (ch,pos) -> positions |> List.filter jumpOptions
、私は純粋に私のリスト内の要素を維持したいです。したがって、フィルタ関数を満たすために、リスト内の各要素を他の値とバンドルする必要はありません。
ガイダンスはありますか?
付録:
open NUnit.Framework
open FsUnit
(* Types *)
type Black = BlackKing | BlackSoldier
type Red = RedKing | RedSoldier
type Coordinate = int * int
type Piece =
| Black of Black * Coordinate
| Red of Red * Coordinate
type Space =
| Allocated of Piece
| Available of Coordinate
type Status =
| BlacksTurn | RedsTurn
| BlackWins | RedWins
(* Private *)
let private black coordinate = Allocated (Black (BlackSoldier , coordinate))
let private red coordinate = Allocated (Red (RedSoldier , coordinate))
let private yDirection = function
| Black _ -> -1
| Red _ -> 1
let private toAvailable = function
| Available pos -> true
| _ -> false
let available positions = positions |> List.filter toAvailable
let private availableSelection = function
| Available pos -> Some pos
| Allocated _ -> None
let private availablePositions positions =
positions |> List.filter toAvailable
|> List.choose availableSelection
let private allocatedSelection = function
| Allocated p -> match p with
| Red (ch,xy) -> Some xy
| Black (ch,xy) -> Some xy
| _ -> None
let private allocatedPositions positions =
positions |> List.filter toAvailable
|> List.choose allocatedSelection
let private getCoordinate = function
| Available xy -> Some xy
| _ -> None
let coordinateOf = function
| Black (checker , pos) -> pos
| Red (checker , pos) -> pos
let jumpOptions space =
match space with
| Allocated p -> match p with
| Red (ch,xy) -> let sourceX, sourceY = coordinateOf source
xy = (sourceX + 1, sourceY - 1) ||
xy = (sourceX - 1, sourceY - 1)
| Black (ch,xy) -> let sourceX, sourceY = coordinateOf p
xy = (sourceX + 1, sourceY + 1) ||
xy = (sourceX - 1, sourceY + 1)
| _ -> false
let jumpsForSoldier piece positions =
match piece with
| Black (ch,pos) -> positions |> List.filter jumpOptions
| Red (ch,pos) -> positions |> List.filter jumpOptions
let private isKing piece =
match piece with
| Black (checker , _) -> match checker with
| BlackSoldier -> false
| BlackKing -> true
| Red (checker , _) -> match checker with
| RedSoldier -> false
| RedKing -> true
(* Public *)
let startGame() =
[ red (0,0); red (2,0); red (4,0); red (6,0)
red (1,1); red (3,1); red (5,1); red (7,1)
red (0,2); red (2,2); red (4,2); red (6,2)
Available (1,3); Available (3,3); Available (5,3); Available (7,3)
Available (0,4); Available (2,4); Available (4,4); Available (6,4)
black (1,5); black (3,5); black (5,5); black (7,5)
black (0,6); black (2,6); black (4,6); black (6,6)
black (1,7); black (3,7); black (5,7); black (7,7) ] , BlacksTurn
let optionsFor piece positions =
let sourceX , sourceY = coordinateOf piece
let optionsForSoldier =
(fun pos -> pos = ((sourceX - 1) , (sourceY + (piece |> yDirection))) ||
pos = ((sourceX + 1) , (sourceY + (piece |> yDirection))))
let optionsForKing =
(fun pos -> pos = ((sourceX - 1) , (sourceY + 1)) ||
pos = ((sourceX + 1) , (sourceY + 1)) ||
pos = ((sourceX - 1) , (sourceY - 1)) ||
pos = ((sourceX + 1) , (sourceY - 1)))
match piece |> isKing with
| false -> positions |> availablePositions
|> List.filter optionsForSoldier
| true -> positions |> availablePositions
|> List.filter optionsForKing
let move piece destination positions =
let rec movePiece positions destinationXY =
let foundPiece = positions |> List.filter (fun space -> space = Allocated piece)
|> List.head
match foundPiece with
| Allocated (Black (ch, xy)) -> (positions |> List.filter (fun space -> space <> Allocated (Black (ch, xy)))
|> List.filter (fun space -> space <> destination))
@ [Available (xy) ; (Allocated (Black (ch, destinationXY)))]
| Allocated (Red (ch, xy)) -> (positions |> List.filter (fun space -> space <> Allocated (Red (ch, xy)))
|> List.filter (fun space -> space <> destination))
@ [Available (xy) ; (Allocated (Red (ch, destinationXY)))]
| _ -> positions
let options = optionsFor piece positions
let canMoveTo = (fun target -> options |> List.exists (fun xy -> xy = target))
match getCoordinate destination with
| Some target -> match canMoveTo target with
| true -> movePiece positions target
| false -> positions
| None -> positions
(* Tests *)
[<Test>]
let ``get jump options for red soldier``() =
// Setup
let redPiece = Red (RedSoldier , (0,2))
let blackPiece = Black (BlackSoldier , (1,3))
let positions = [Allocated redPiece; Available (2,2); Available (4,2); Available (6,2)
Allocated blackPiece; Available (3,3); Available (5,3); Available (7,3)
Available (0,4); Available (2,4); Available (4,4); Available (6,4)]
// Test
positions |> jumpsForSoldier redPiece
|> should equal [Allocated blackPiece]
このコードは、理由は比類のない括弧と中 'when'句でコンパイルされません。許可されていない場所。私は 'いつ'がその論理を破るだろうと考えています。 – TheQuickBrownFox
@TheQuickBrownFoxはそれを逃してしまいました。 'when'部分を理解していない。もしそれが欠落している括弧に関連していたり、何かを意味しているのであれば、 – Sehnsucht
パターンごとに 'when'を1つだけ持つことができ、2つの' Allocated'行は '| | '(OR)。 – TheQuickBrownFox