【问题标题】:Why are x values vertical and y values horizontal in my 2d array为什么我的二维数组中的 x 值是垂直的而 y 值是水平的
【发布时间】:2018-04-25 00:26:48
【问题描述】:

我有一个二维数组,我试图用它来表示我的游戏中的某种网格。它是 5x3,看起来像:

[0,0][0,1][0,2][0,3][0,4]
[1,0][1,1][1,2][1,3][1,4]
[2,0][2,1][2,2][2,3][2,4]

问题是,我想将某个点转换为屏幕上的某个位置,但在我的二维数组中,x 似乎是垂直值而 y 是水平值。如果我想在 x = 1、y = 2 处添加一个节点,那么我实际上是在 -right- 2 和 -down- 1 处。但是当我想到 x 时,我会想到一个水平值(左/右) .我在这里设计错了吗?如何设计我的二维数组,使 x 值对应于左/右移动和 y 上/下。

我正在创建如下数组:

    init(width: Int, height: Int) {
        self.width = width
        self.height = height


        for y in 0..<height {
            map.append([Tile]())

            for _ in 0..<width {
                map[y].append(Tile(blocked: false))
            }
        }
    }

瓷砖只是一个保持其位置的对象和一些其他不相关的东西。谢谢!

【问题讨论】:

  • 只需使用arr[y][x]访问您的阵列
  • @vacawama 这对我来说有点违反直觉,因为我已经习惯了 x,y
  • xy 在图形/几何上不是任何东西——它们只是数组中的值。您将这些值转换为视图的部分在哪里?您可以从构建数组的方式向后声明或访问rowcolumn,但我们看不到那部分。如果您说[1][2],那么您将“向下 1 和向右 2”,因为这就是数组访问以您在此处构建它的方式的工作方式 - 行,然后是列。您将 (1,2) 视为笛卡尔 (x,y),但事实并非如此。你真正在做的是访问[row][column]
  • Swift 并没有真正的多维数组。您只是在构建一个数组数组。将它们构建为行的集合是很自然的,因此arr[row][col] 是自然顺序,row 是垂直维度。
  • 将数组更改为 [0,0],[1,0],[2,0]... 如果它对您很重要。

标签: arrays swift multidimensional-array


【解决方案1】:

这是将矩阵存储在row major order, vs column major order 中的问题。

主要行是当迭代外部数组产生行时,迭代内部数组产生行内的元素。由于文本输出(到文件或终端)是逐行完成的,这对于打印目的来说是更可取的。但是,这意味着当以a[b][c] 形式索引时,第一个索引(b)是您的垂直坐标(通常称为y),第二个索引(c)是您的水平坐标(通常称为x),它不遵循您习惯的通常的“x 然后y”约定。但是,您可以通过编写自定义下标运算符来轻松解决此问题,该运算符会翻转两个索引:

struct Tile {
    let blocked: Bool

    init(blocked: Bool = false) { self.blocked = blocked }
}

extension Tile: CustomDebugStringConvertible {
    var debugDescription: String {
        return self.blocked ? "X" : "-"
    }
}

struct Gameboard {
    var tiles: [[Tile]]

    init(tiles: [[Tile]]) {
        let width = tiles.first?.count
        assert(!tiles.contains(where:) { $0.count != width }, "The tiles must be a square matrix (having all rows of equal length)!")
        self.tiles = tiles
    }

    init(width: Int, height: Int) {
        self.init(tiles: (0..<height).map { row in
            (0..<width).map { column in Tile() }
        })
    }

    subscript(x x: Int, y y: Int) -> Tile {
        return self.tiles[y][x]
    }
}

extension Gameboard: CustomDebugStringConvertible {
    var debugDescription: String {
        let header = (self.tiles.first ?? []).indices.map(String.init).joined(separator: "\t")
        let body = self.tiles.enumerated().map { rowNumber, row in
            let rowText = row.map { $0.debugDescription }.joined(separator: "\t")
            return "\(rowNumber)\t\(rowText)"
        }.joined(separator: "\n")

        return "\t\(header)\n\(body)"
    }
}

let g = Gameboard(width: 5, height: 3)
print(g)
// Example indexing:
let (x, y) = (2, 3)
g[x: x, y; y]

行主要顺序也是可取的,因为它是使用嵌套数组表示矩阵的自然结果

let matrix = [ // Outer array hold rows
   [1, 2, 3] // The inner arrays hold elements within rows
   [4, 5, 6]
   [7, 8, 9]
] // Thus, this matrix is in row-major order.

您可以使用列主顺序来解决交换索引的问题,但这意味着如果您希望逐行打印或使用嵌套数组字面量定义它,则需要transpose the matrix

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-14
    • 1970-01-01
    • 2020-11-16
    • 1970-01-01
    • 2020-04-04
    • 2010-11-05
    • 2020-08-05
    相关资源
    最近更新 更多