如何将两个案例值表达式重构为一个?

时间:2016-07-29 16:03:24

标签: f#

如何将两个案例值表达式重构为一个?

我担心我还不清楚如何从这个逻辑中删除重复:

match redPiece with
| Checker checker -> checker |> set (checker |> attemptJump blackChecker yIncrementValue)
| King    king    -> king    |> set (king    |> attemptJump blackChecker yIncrementValue)

这个问题可能是 duplicate 。但是,我仍然在努力重构这种类型的代码味道。

我如何实际实现其中一张海报在我提供的link上建议的包装函数?

以下是完整的功能:

let jumpBlack ((blackChecker:BlackChecker),(blackCheckers:BlackChecker list))  (redPiece:RedPiece) =

    let yIncrementValue = -1
    let minY = 0

    let set position piece =
       match position with
       | pos when pos = piece   -> position , blackCheckers
       | _                      -> position , blackCheckers |> remove blackChecker

    match redPiece with
    | Checker checker -> checker |> set (checker |> attemptJump blackChecker yIncrementValue)
    | King    king    -> king    |> set (king    |> attemptJump blackChecker yIncrementValue)

可以在此处找到整个域名:

(* Types *)
type BlackOption = NorthEast | NorthWest
type RedOption =   SouthEast | SouthWest

type KingOption = 
    | NorthEast 
    | NorthWest
    | SouthEast 
    | SouthWest

type Position =     { X:int; Y:int }

type BlackChecker = Position
type RedChecker =   Position
type BlackKing =    Position
type RedKing =      Position

type King = 
    | BlackKing of BlackKing
    | RedKing of RedKing

type RedPiece = 
    | Checker of RedChecker 
    | King of RedKing

type BlackPiece = 
    | BlackChecker of BlackChecker 
    | BlackKing of BlackKing

(* Private *)
let private remove item list = list |> List.filter (fun x -> x <> item)

let private setRowPosition y1 y2 y3 index =
    match index with 
    | x when x < 4 -> { X=x; Y=y1 }
    | x when x < 8 -> { X=x-4; Y=y2 }
    | _            -> { X=index-8; Y=y3 }

let private set (x, y) positions (position:Position) =
    match not (positions |> List.exists (fun pos -> pos = { X=x; Y=y })) with
    | true -> { X=x; Y=y }
    | false -> position

let private attemptJump target yDirection source =
    let updateX value = { X=target.X + value
                          Y=target.Y + yDirection }
    match source with
    | position when position.Y + yDirection = target.Y &&
                    position.X + 1 = target.X -> updateX 1

    | position when position.Y + yDirection = target.Y &&
                    position.X - 1 = target.X -> updateX -1
    | _ -> source

let private initializeBlack () =
    let setPosition index =
        index |> setRowPosition 7 6 5

    let blackCheckers = List.init 12 setPosition |> List.map (fun pos -> { X=pos.X; Y=pos.Y })
    blackCheckers

let private initializeRed () =
    let setPosition index =
        index |> setRowPosition 0 1 2

    let redCheckers =   List.init 12 setPosition |> List.map (fun pos -> { X=pos.X; Y=pos.Y })
    redCheckers

(* Exposed *)
let moveBlack direction positions (checker:BlackChecker) =
    let position = checker

    match direction with
    | BlackOption.NorthEast -> (positions, position) ||> set ((position.X + 1), (position.Y + 1 ))
    | BlackOption.NorthWest -> (positions, position) ||> set ((position.X - 1), (position.Y + 1 ))

let moveRed direction positions (checker:RedChecker) =
    let position = checker

    match direction with
    | RedOption.SouthEast -> (positions, position) ||> set ((position.X + 1), (position.Y - 1 ))
    | RedOption.SouthWest -> (positions, position) ||> set ((position.X - 1), (position.Y - 1 ))

let moveKing direction positions (king:King) =

    let position = match king with
                   | King.BlackKing bk -> bk
                   | King.RedKing   rk -> rk

    let result = match direction with
                 | NorthEast -> (positions, position) ||> set ((position.X + 1), (position.Y + 1 ))
                 | NorthWest -> (positions, position) ||> set ((position.X - 1), (position.Y + 1 ))
                 | SouthEast -> (positions, position) ||> set ((position.X + 1), (position.Y - 1 ))
                 | SouthWest -> (positions, position) ||> set ((position.X - 1), (position.Y - 1 ))

    match king with
    | King.BlackKing _ -> King.BlackKing result
    | King.RedKing   _ -> King.RedKing   result

let jumpRed ((redChecker:RedChecker), (redCheckers:RedChecker list)) (blackChecker:BlackChecker) =

    let yIncrementValue = 1
    let maxY = 7
    let position = blackChecker |> attemptJump redChecker yIncrementValue

    match position with
    | pos when pos = blackChecker -> BlackChecker position , redCheckers
    | pos when pos.Y = maxY       -> BlackKing    position , redCheckers |> remove redChecker
    | _                           -> BlackChecker position , redCheckers |> remove redChecker

let jumpBlack ((blackChecker:BlackChecker),(blackCheckers:BlackChecker list))  (redPiece:RedPiece) =

    let yIncrementValue = -1
    let minY = 0

    let set position piece =
       match position with
       | pos when pos = piece   -> position , blackCheckers
       | _                      -> position , blackCheckers |> remove blackChecker

    match redPiece with
    | Checker checker -> checker |> set (checker |> attemptJump blackChecker yIncrementValue)
    | King    king    -> king    |> set (king    |> attemptJump blackChecker yIncrementValue)

1 个答案:

答案 0 :(得分:4)

我会删除那样的重复:

match redPiece with
    | Checker piece
    | King    piece    -> piece    |> set (piece    |> attemptJump blackChecker yIncrementValue)