在 F# 中创建复合迭代器

发布于 2024-10-18 12:54:19 字数 1485 浏览 12 评论 0原文

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

我有以下函数,直接从 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;
     }

将不向您详细介绍我为使其发挥作用而进行的各种尝试,因为它们都没有成功。但长话短说,我能想到的最好的办法是一个迭代器,它在每次收益时返回一个 seq,而不是我正在寻找的扁平化版本,它会返回一个简单的 MoveStruct。

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

问候, 亚历克斯

I'm implementing a checkers-like game, and I need a sequence that enumerates all legal moves for a given configuration.

I've got the following function, directly translated from 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;
   }

It works, but it's awkward, and not quite the "F# way", let alone I have a sneaking suspicion that what I'm doing here is not performance optimal.

What I would like is to "flatten this out" into something that uses a combination of "iterate over all cells", "iterate over all valid moves from this cell".

And here are the functions I'm hoping to combine:

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

AND

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;
     }

I'm going to spare you the details of my various attempts to make it work, because none of them were successful. But to make the long story short, the best I could come up with is an iterator that returns a seq with each yield, instead of the flattened version I'm looking for, which would return a simple MoveStruct.

Anyone have a good idea how to combine AllCells, and LegalMovesAround(x,y)?

Regards,
Aleks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

悟红尘 2024-10-25 12:54:19

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

let allLegalMoves = seq {
  for cell in AllCells do
    yield! LegalMovesAround cell
}

You could use yield! in a new sequence expression:

let allLegalMoves = seq {
  for cell in AllCells do
    yield! LegalMovesAround cell
}
浮云落日 2024-10-25 12:54:19

您知道yield!吗?

类似的东西

seq {
    for x,y in Allcells do
        yield! LMA(x,y)
}

Are you aware of yield!?

something like

seq {
    for x,y in Allcells do
        yield! LMA(x,y)
}
方圜几里 2024-10-25 12:54:19

您应该能够按原样组合它们,然后进行扁平化,如下所示:

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

尽管从性能角度来看,这可能不是最好的解决方案。

编辑:根据托马斯评论修复了示例代码

You should be able to combine them the way they are and then flatten, something like this:

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

It may not be the best solution performance-wise though.

EDIT: Fixed sample code as per Tomas comment

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文