F#打印2D字符串数组

时间:2018-06-25 00:27:21

标签: multidimensional-array f# printf

我目前正在开发名为Neutron的棋盘游戏。

let boardArray = array2D [ ["*"; "*"; "*"; "*"; "*"; "*"; "*"; "*"; "*"; "*"; "*"];
                           ["*"; "1"; "*"; "2"; "*"; "3"; "*"; "4"; "*"; "5"; "*"];
                           ["*"; "*"; "*"; "*"; "*"; "*"; "*"; "*"; "*"; "*"; "*"];
                           ["*"; "0"; "*"; "0"; "*"; "0"; "*"; "0"; "*"; "0"; "*"];
                           ["*"; "*"; "*"; "*"; "*"; "*"; "*"; "*"; "*"; "*"; "*"];
                           ["*"; "0"; "*"; "0"; "*"; "N"; "*"; "0"; "*"; "0"; "*"];
                           ["*"; "*"; "*"; "*"; "*"; "*"; "*"; "*"; "*"; "*"; "*"];
                           ["*"; "0"; "*"; "0"; "*"; "0"; "*"; "0"; "*"; "0"; "*"];
                           ["*"; "*"; "*"; "*"; "*"; "*"; "*"; "*"; "*"; "*"; "*"];
                           ["*"; "A"; "*"; "B"; "*"; "C"; "*"; "D"; "*"; "E"; "*"];
                           ["*"; "*"; "*"; "*"; "*"; "*"; "*"; "*"; "*"; "*"; "*"] ]

我有这个字符串数组。我的问题是,我该如何打印这样的数组?

我最初的想法是使用嵌套的for循环打印出一些boardArray.[row, column],但是据我了解,

中的row

for row in boardArray do是obj类型;而且我不能完全通过需要int的obj。我可以进行转换吗?我应该使用另一种方法?我是否严重误解了每个循环中F#的用法?

2 个答案:

答案 0 :(得分:4)

使用for..to循环解决:

let initiateBoard = 
 for r = 0 to Array2D.length1 boardArray - 1 do
  for c = 0 to Array2D.length2 boardArray - 1 do
   printfn "%A " boardArray.[r, c]

这将在新行上打印出每个元素,因此除此以外,还需要一个单独的间距处理功能。

答案 1 :(得分:4)

板上的每个项目是否总是一个字符?如果是这样,那么我建议您稍微更改一下数据类型。

首先,如果木板中的每个项目始终都是单个字符,那么使用char(而不是字符串)作为每个木板位置的数据类型更有意义,就像这样:

let boardArray = array2D [ ['*'; '*'; '*'; '*'; '*'; '*'; '*'; '*'; '*'; '*'; '*'];
                           ['*'; '1'; '*'; '2'; '*'; '3'; '*'; '4'; '*'; '5'; '*'];
                           // Etc.
                         ]

但是有一种更好的方式来表示这样的2D字符数组,这就是 strings 的一维数组,其中每个字符串都是一行:

let boardArray = [| "***********";
                    "*1*2*3*4*5*"
                    // Etc.
                 |]

现在访问第r行和第c列的字符,而不是写board.[r, c],而是写board.[r].[c]。如果您感到困扰,则可以编写如下的帮助函数:

let getChar (row, col) board = board.[row].[col]

然后像这样使用它:

board |> getChar (1, 3)

这等同于以您当前使用的board.[1, 3]表示形式进行array2d

然后印刷电路板变得非常容易:

for row in board do
    printfn "%s" row

由于字符串是不可变的,因此更改板中的项目会有些困难,但是您可以为“使用旧字符串的内容制作新字符串,但该索引处的替换字符除外”定义辅助函数:

let replaceAt idx (ch : char) (s : string) =
    let len = s.Length
    let before = s.Substring(0, idx)
    let after = if idx >= len then "" else s.Substring(idx+1, len-idx-1)
    sprintf "%s%c%s" before ch after

用法:

"*1*2*3*4*5*" |> replaceAt 1 'X'  // Returns "*X*2*3*4*5*"

因此要将第1行第3行的项目替换为“ X”,您可以这样做:

board.[1] <- board.[1] |> replaceAt 3 'X'

或者,如果您选择 not 来对您的阵列进行突变,而不是为每个板状态创建一个新的阵列,那么您可以使用以下辅助函数来实现:

let replaceItemInArray idx (newItem : 'T) (arr : 'T []) =
    arr |> Array.mapi (fun i oldItem -> if i = idx then newItem else oldItem)

let updateBoard newItem (row, col) oldBoard =
    let oldRowContents = oldBoard.[row]
    let newRowContents = oldRowContents |> replaceAt col newItem
    oldBoard |> replaceItemInArray row newRowContents

如果您对我使用的Array.mapi函数感到好奇,请its documentation is here