Почему значения x вертикальные, а значения y горизонтальные в моем двумерном массиве - PullRequest
0 голосов
/ 25 апреля 2018

У меня есть двумерный массив, который я пытаюсь использовать для представления своего рода сетки в моей игре. Это 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]

Проблема в том, что я хочу перевести определенную точку в позицию на моем экране, но в моем 2-мерном массиве x кажется вертикальным значением, а y горизонтальным. Если я хочу добавить узел в x = 1, y = 2, то я фактически иду в -right- 2 и -down- 1. Но когда я думаю о x, я думаю о горизонтальном значении (влево / вправо) , Я что-то здесь не так делаю? Как я могу создать свой 2d массив так, чтобы значения 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))
            }
        }
    }

Где плитка - это просто объект, который удерживает свое положение и некоторые другие не относящиеся к делу вещи. Спасибо!

1 Ответ

0 голосов
/ 25 апреля 2018

Это вопрос хранения вашей матрицы в мажорном порядке строки по сравнению с мажорным порядком столбца .

Основная строка - это когда итерация внешнего массива дает строки, а итерация внутреннего массива - элементы в строке. Поскольку вывод текста (в файл или на терминал) выполняется построчно, это предпочтительно для печати. Однако это означает, что при индексации в форме 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.

Вы можете использовать основной порядок столбцов, чтобы обойти проблему замены индексов, но это означает, что вам нужно транспонировать матрицу , если вы хотите напечатать ее построчно или определить ее, используя литерал вложенного массива.

...