5

我正在实现一个类似跳棋的游戏,我需要一个序列来枚举给定配置的所有合法移动。

我有以下函数,直接从 C# 翻译而来:

seq {
    for y1 = 0 to BOARDSIZE-1 do
        for x1 = 0 to BOARDSIZE-1 do
             for dy = -2 to 2 do
                 for dx = -2 to 2 do
                     let x2 = x1 + dx;
                     let y2 = y1 + dy;
                     let currentMove = new MoveStruct(x1, y1, x2, y2);
                     if (currentMove.SomeCondition = true) then
                             yield currentMove;
   }

它有效,但很尴尬,而且不完全是“F# 方式”,更不用说我偷偷怀疑我在这里所做的不是性能最佳的。

我想要的是将其“展平”为使用“迭代所有单元格”、“迭代来自该单元格的所有有效移动”的组合的东西。

以下是我希望结合的功能:

let AllCells =
    seq {
        for y=0 to BOARDSIZE-1 do
            for x=0 to BOARDSIZE-1 do
                yield (x,y);
    };

let LegalMovesAround(x1,y1) = 
    seq {
      if board.[x1, y1] = WHITE then
        for dy = -2 to 2 do
          for dx = -2 to 2 do
                let x2 = x1 + dx;
                let y2 = y1 + dy;
                let currentMove = new MoveStruct(x1, y1, x2, y2);
                if (currentMove.DetermineMoveType <> MoveType.ILLEGAL 
                    && board.[x2, y2] = NONE) then
                        yield currentMove;
     }

我将不向您详细说明我为使其发挥作用所做的各种尝试,因为它们都没有成功。但长话短说,我能想到的最好的方法是一个迭代器,它为每个产量返回一个序列,而不是我正在寻找的扁平版本,它会返回一个简单的 MoveStruct。

任何人都知道如何结合 AllCells 和 LegalMovesAround(x,y)?

问候, 阿列克斯

4

3 回答 3

3

你可以使用产量!在新的序列表达式中:

let allLegalMoves = seq {
  for cell in AllCells do
    yield! LegalMovesAround cell
}
于 2011-02-22T10:27:25.410 回答
3

你知道yield!吗?

就像是

seq {
    for x,y in Allcells do
        yield! LMA(x,y)
}
于 2011-02-22T10:31:32.443 回答
1

您应该能够将它们按原样组合然后变平,如下所示:

 let validMoves = 
    AllCells 
    |> Seq.collect LegalMovesAround
    |> Seq.distinct

虽然它可能不是性能方面的最佳解决方案。

编辑:根据 Tomas 评论修复了示例代码

于 2011-02-22T08:54:15.717 回答