当我被迫绘制一个不存在的工会案例时,我该怎么办?
以下过滤器可确保仅添加与特定案例匹配的元素:
let toAvailable =
(fun space -> match space with
| Available pos -> true
| _ -> false)
然后我想将过滤后的结果映射到另一种类型:
let availablePositions =
positions |> List.filter toAvailable
|> List.map (fun space -> match space with
| Available pos -> pos
| Allocated _ -> (-1,-1)) // Should never happen
但是,我仍然被迫处理我在之前的操作中处理的案件。因此,我已经过滤掉了“已分配”的案例。
在这种情况下我该怎么做?
以下是完整的功能:
let optionsFor piece (positions:Space list) =
let yDirection = match piece with
| Black _ -> -1
| Red _ -> 1
let sourceX , sourceY =
match piece with
| Black (checker , pos) -> pos
| Red (checker , pos) -> pos
let optionsForPiece =
(fun pos -> pos = ((sourceX - 1) , (sourceY + yDirection)) ||
pos = ((sourceX + 1) , (sourceY + yDirection)))
let availablePositions =
positions |> List.filter toAvailable
|> List.map (fun space -> match space with
| Available pos -> pos
| Allocated _ -> (-1,-1)) // Should never happen
availablePositions |> List.filter optionsForPiece
这是我的整个网域:
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
(* Functions *)
let black coordinate = Allocated (Black (BlackSoldier , coordinate))
let red coordinate = Allocated (Red (RedSoldier , coordinate))
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 toAvailable =
(fun space -> match space with
| Available pos -> true
| _ -> false)
let available (positions:Space list) = positions |> List.filter toAvailable
let optionsFor piece (positions:Space list) =
let yDirection = match piece with
| Black _ -> -1
| Red _ -> 1
let sourceX , sourceY =
match piece with
| Black (checker , pos) -> pos
| Red (checker , pos) -> pos
let optionsForPiece =
(fun pos -> pos = ((sourceX - 1) , (sourceY + yDirection)) ||
pos = ((sourceX + 1) , (sourceY + yDirection)))
let availablePositions =
positions |> List.filter toAvailable
|> List.map (fun space -> match space with
| Available pos -> pos
| Allocated _ -> (-1,-1)) // Should never happen
availablePositions |> List.filter optionsForPiece
以下是我的测试:
[<Test>]
let ``get avaialable positions for black soldier`` () =
// Setup
let piece = Black ( BlackSoldier , (1,5) )
// Test
let available = startGame () |> fst
|> available
|> optionsFor piece
// Verify
let northWestAvailable = available |> List.exists (fun pos -> pos = (0,4))
let northEastAvailable = available |> List.exists (fun pos -> pos = (2,4))
(northWestAvailable && northEastAvailable) |> should equal true
[<Test>]
let ``get avaialable positions for red soldier`` () =
// Setup
let piece = Red ( RedSoldier , (0,2) )
// Test
startGame () |> fst
|> available
|> optionsFor piece
|> List.exists (fun pos -> pos = (1,3))
|> should equal true
答案 0 :(得分:1)
这样的事情怎么样:
type Red = RedKing | RedSoldier
type Black = BlackKing | BlackSoldier
type Coordinate = int * int
type Piece =
| Black of Black * Coordinate
| Red of Red * Coordinate
type Space =
| Allocated of Piece
| Available of Coordinate
let x1 = Allocated (Black (BlackKing, (5,5)))
let x2 = Available (10,10)
let x3 = Available (20,10)
let xs = [x1;x2;x3]
根据TDD的评论编辑:
let xs' =
xs
|> List.choose (function | Available pos -> Some(pos)
| _ -> None)
// val xs' : Coordinate list = [(10, 10); (20, 10)]
如有必要,您还可以使用Option.map
。