遍历F#2D阵列

Dav*_*001 5 f#

我在F#中创建了一个棋盘(类型)游戏,并且在以"功能"方式遍历阵列时遇到了一些麻烦.

我有一个数组,看起来像,例如:

val myArray : int [,] = [[1; 1; 0; 0; 0]
                         [0; 0; 1; 0; 0]
                         [2; 0; 0; 0; 3]
                         [0; 0; 0; 0; 0]
                         [0; 1; 0; 0; 1]]
Run Code Online (Sandbox Code Playgroud)

我想根据上面的内容创建一个新数组,其中:

  1. 如果项目> 0,则在新数组中应为数字1
  2. 如果项目为= 0,则:
    1. 如果左侧或右侧或上方或下方的项目> 1,则在新阵列中该数字应为2
    2. 否则,如果右侧或上方或下方左侧的项目= 1,则在新阵列中该数字应为3
    3. 否则,数字应为4

这应该创建一个新的数组,如下所示:

val myArray : int [,] = [[1; 1; 3; 4; 4]
                         [2; 3; 1; 3; 2]
                         [1; 2; 3; 2; 1]
                         [2; 3; 4; 4; 2]
                         [3; 1; 3; 3; 1]]
Run Code Online (Sandbox Code Playgroud)

我无法在F#中看到实现这一目标的任何简单方法.在C#中,我只是创建了一个for循环来实现这一点,但我认为在F#中可能有一种偷偷摸摸的方式,使用像map函数这样的东西- mapi看起来很有希望,但它似乎只能访问正在考虑的当前部分它的指数,而不是整个阵列......

我的问题似乎是游戏规则依赖于周围区域,而标准的遍历方法似乎无法访问周围区域 - 实现我正在做的事情的最佳方式是什么?

cfe*_*ern 5

我不认为我在这个解决方案中做了任何偷偷摸摸的表演。我使用 Array2D.init 构建了一个新数组。init 所需的函数确定每个位置的数组值。

此外,我将收集邻居放在一个单独的函数中。在邻居函数中,我使用了列表理解并仅生成有效的邻居,避免了角落和边缘周围的麻烦。

这就是我想到的(警告:当 2D 数组为 1x1 或为空时,它将失败,我将其留给读者来防范这种情况):

let neighbors r c (A:'a[,]) =
    [if r > 0 then yield A.[r-1,c]
     if r < Array2D.length1 A - 1 then yield A.[r+1,c]
     if c > 0 then yield A.[r,c-1]
     if c < Array2D.length2 A - 1 then yield A.[r,c+1]]

let newArray A =
    Array2D.init (Array2D.length1 A) (Array2D.length2 A) 
        (fun r c ->
            if A.[r,c] > 0 then 1 
            else
                match neighbors r c A |> List.max with
                | 1 -> 3
                | 0 -> 4
                | _ -> 2
        )
Run Code Online (Sandbox Code Playgroud)

在 F# 交互式中测试:

let myArray = array2D [[1; 1; 0; 0; 0]
                       [0; 0; 1; 0; 0]
                       [2; 0; 0; 0; 3]
                       [0; 0; 0; 0; 0]
                       [0; 1; 0; 0; 1]]

let result = newArray myArray
Run Code Online (Sandbox Code Playgroud)

结果:

val result : int [,] = [[1; 1; 3; 4; 4]
                        [2; 3; 1; 3; 2]
                        [1; 2; 3; 2; 1]
                        [2; 3; 4; 4; 2]
                        [3; 1; 3; 3; 1]]
Run Code Online (Sandbox Code Playgroud)