2016-07-29 84 views
0

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

恐怕我还没有就如何从这个逻辑消除重复清晰:

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) 
+3

也许我错了,但分开黑色和红色分类是一种错误的做法。一个棋子完成同样的事情,不管它的颜色(去**是左边还是右边)。颜色/播放器只是其状态的一个参数。重复IMO来自那里。 – Sehnsucht

+1

这是一个很奇怪的领域模型。就像@Sehnsucht说的那样,你在那里的定义中有很多重复。 – asibahi

+0

感谢您的反馈。我的意图是让编译器执行基于颜色和国王身份的检查器移动规则。因此,我试图实践使非法国家不能代表和不幸惨败的想法。 –

回答

4

我会删除这样的重复:

match redPiece with 
    | Checker piece 
    | King piece -> piece |> set (piece |> attemptJump blackChecker yIncrementValue) 
相关问题