为什么在我的2d数组中x值是垂直的,y值是水平的

时间:2018-04-25 00:26:49

标签: arrays swift multidimensional-array

我有一个二维数组,我试图用来表示我游戏中的网格类型。它是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]

问题是,我想将某个点转换为我的屏幕上的某个位置但是在我的2d数组中,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))
            }
        }
    }

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

1 个答案:

答案 0 :(得分: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