在Go中初始化一个二维动态数组



我正在尝试创建一个2d数组:

board := make([][]string, m)
for i := range board {
    board[i] = make([]string, n)
}

然而,鉴于冗长,我想知道是否有一个更好或更简洁的方法来处理这个问题(要么生成动态数组,要么一个不同的/习惯的数据结构来处理这样的棋盘游戏数据)?


背景:

  • 这是一个桌面游戏
  • 直到用户开始玩游戏(例如,MxN)时才知道棋盘的尺寸。
  • 我想在每个单元格中存储任意字符(或单个字符串)。在我的《TicTacToe》游戏中,这将是"X"或"O"(或用户选择的任何其他角色)。

您在示例代码中构建的不是2D数组,而是切片的切片:这种类型的每个子切片可以具有不同的长度,这就是为什么您为每个子切片分别分配的原因。

如果您想用单个分配来表示电路板,那么一种选择是分配单个切片,然后使用简单的算术来确定元素的位置。例如:

board := make([]string, m*n)
board[i*m + j] = "abc" // like board[i][j] = "abc"

您描述的方法创建了一个切片的切片,它看起来类似于您想要的2d数组。我建议您将类型更改为uint8,因为您只关心3个状态nothing/first/second播放器。

这将分别分配每一行(您将在基准测试中至少看到m + 1 allocs/op)。这并不是很好,因为不能保证单独的分配将被定位在彼此接近的位置。

为了保持局部性,你可以这样做:

M := make([][]uint8, row)
e := make([]uint8, row * col)
for i := range M {
    a[i] = e[i * col:(i + 1) * col]
}

这将最终只分配2次,并且片的片将保持数据局部性。请注意,您仍然可以访问2d格式的M M[2][6]

一个很好的视频,它解释了如何更快地做到这一点。

对于多维数组,我们可以使用以下两种用例中的任何一种:

  1. 在编译
  2. 时知道数组的尺寸
  3. 你只有在运行时才能知道数组的尺寸,也就是从用户那里

对于用例1

matr := [5][5]int{}

对于用例2

var m, n int
fmt.Scan(&m, &n)
var mat = make([][]int, m)
for i := range mat {
    mat[i] = make([]int, n)
    fmt.Printf("Row %d: %vn", i, mat[i])
}

简而言之,我们必须依靠make来创建动态数组

相关内容

  • 没有找到相关文章