这更像是TicTacToe的一个‘模型’,因为您将看到它不是“游戏化”,因为它将允许输入和输出,也不会记录游戏中的任何“活动”状态,但这些都是微不足道的实现。
我在我的函数的函数范型上欺骗了一点来旋转网格,但这是有意的,通过突变来旋转网格比采用纯函数的方式更容易,最后,状态只在局部函数中被操纵,所以我认为它是否定的。
还有很多时候,我忽略了对简洁性的优化。人们可能会认为,这并不是最优性能是关键的领域,所以我已经将获取尽可能简洁和可读的代码列为优先事项。
module TicTacToe
type Mark = None | Cross | Nought
type Outcome = None | NoughtWon | CrossWon | Draw
let emptyGrid = (None, Array2D.init 3 3 (fun _ _ -> Mark.None))
let flatten (x: 'a [,]) = x |> Seq.cast<'a>
let rotateCw (grid: 'a [,]) =
let out = Array2D.zeroCreate 3 3
for y in 0..2 do
for x in 0..2 do
out.[x,y] <- grid.[0 + y, 2 - x]
out
let checkOutcome grid =
let checkSeg seg =
seq { for i in 0..2 do
let count =
seg i |> Array.sumBy
(function Cross -> 1 | Nought -> 2 | _ -> 0)
if count = 6 || count = 3 then
yield (if count = 6 then NoughtWon else CrossWon) }
|> Seq.tryFind ((<>)None)
let vertical =
let rot = grid |> rotateCw
(fun x -> rot.[x, 0..2])
let horizontal = (fun y -> grid.[0..2, y])
let diagonal (m:_[,]) = (fun _ -> [| for i in 0..2 -> m.[i,i] |])
let diagonal2 = grid |> rotateCw |> diagonal
let checks =
[checkSeg vertical; checkSeg horizontal;
checkSeg (diagonal grid); checkSeg diagonal2]
if checks |> List.exists (Option.isSome) then
checks |> List.find (Option.isSome) |> Option.get
elif grid |> flatten |> Seq.forall ((<>)Mark.None) then Draw
else None
let placeMark pos mark (_, grid: Mark [,]) =
let res =
Array2D.init 3 3 (fun x y ->
if (x,y) = pos then mark else grid.[x,y])
(checkOutcome res, res)发布于 2015-02-03 03:32:48
设emptyGrid =(无,Array2D.init 3 3 (fun __ -> Mark.None))
这可以使用Array2D.create进行简化:
let emptyGrid = None, Array2D.create 3 3 Mark.None在rotateCw和placeMark中,x作为第一个索引,y作为第二个索引。这是令人困惑的,因为通常的顺序是行然后列。例如,
let test = Array2D.create 3 3 Mark.None
test.[2, 1] <- Cross
printfn "%A" test
[[None; None; None]
[None; None; None]
[None; Cross; None]]rotateCw可以简化(假设上一段中的索引更改)
let rotateCw (grid : 'a[,]) = Array2D.init 3 3 (fun y x -> grid.[2 - x, y])我觉得这个版本的placeMark更易读
let placeMark (x, y) mark (_, grid : Mark[,]) =
let res = Array2D.copy grid
res.[y, x] <- mark
(checkOutcome res, res)https://codereview.stackexchange.com/questions/79326
复制相似问题