【问题标题】:Multidimensional array not letting me assign values through loop?多维数组不允许我通过循环赋值?
【发布时间】:2015-12-11 20:27:46
【问题描述】:

我有一小段代码如下所示:

func initAllLabels() {

    var scoreLabels:[[[SKLabelNode]]] = []

    for (var x = 0; x < modesInGame; x++) {
        for (var y = 0; y < levelsInMode; y++) {
            for (z = 0; z < labelsInLevel; z++) {
                scoreLabels[x][y][z] = SKLabelNode(fontNamed: "Font")
            }
        }
    }
}

所以我要做的是为每个游戏模式存储我的所有标签。我尝试使用多维数组的原因是因为每个级别 (3-5) 我将有多个标签,我想像这样访问它们:

updateText(scoreLabels[currentMode][currentLevel][thisLabel])

并像这样访问当前标签的所有标签:

for label in labelsInLevel:
    label.hidden = false

问题是,当我尝试在游戏开始时在 initAllLabels 中创建所有标签时,在循环的第一次运行时出现“索引超出范围”错误(索引:0)。我认为问题是因为我需要在设置其内容之前“附加”到数组,对吗?我如何在像我这样的数组结构中实现这一点?

【问题讨论】:

标签: arrays swift multidimensional-array


【解决方案1】:

在更新数组中位置的项目之前,您需要将数组初始化为给定大小。从一维案例开始可能会有所帮助:

var labels: [SKLabelNode] = [] // creates an empty array
// since the array is empty, this will generate an index out of range error:
labels[0] = SKLabelNode(fontNamed: "Font")

相反,您需要使用要添加的元素来扩展数组。例如,

for _ in 0..<labelsInLevel {
    labels.append(SKLabelNode(fontNamed: "Font"))
}

_ 的意思是“我不关心每次迭代的实际次数 - 通常如果你想知道这是 ith 围绕你写的循环for i in 0..&lt;n

虽然有更好的方法可以做到这一点。但是小心其中之一,Array 的初始化程序,它采用 countrepeatedValue

let labels = Array(count: labelsInLevel, repeatedValue: SKLabelNode(fontNamed: "Font”))

SKLabelNode 是一个引用类型。这意味着一个变量只引用一个实例,而将一个变量分配给另一个变量只会复制引用。比如:

let variableOne = SKLabelNode(fontNamed: "Foo")
let variableTwo = variableOne  
// variableTwo now refers to the same instance of SKLabelNode
variableTwo.fontName = "Bar"
print(variableOne) 
// fontName will now be “Bar” even though this was
// done via variableTwo

使用上面的repeatedValue 代码可以获得相同的效果。标签被创建一次,对它的相同引用被插入多次。更改数组中一个标签的属性,然后将它们全部更改。注意for 循环版本没有 有这个问题。每次循环时,都会创建一个新的SKLabelNode 实例。它们不会被共享。

在不使用for 循环的情况下创建repeatedValue 初始化器的替代方法是使用map

(0..<labelsInLevel).map { _ in SKLabelNode(fontNamed: "Font") }

在这里,就像在for 循环版本中一样,每次都会创建一个新的SKLabelNode 实例。

(同样,我们使用_ 表示我们不关心迭代次数)

最后,要创建包含循环的嵌套多维数组,您可以多次运行map

var scoreLabels =
  (0..<modesInGame).map { _ in
    (0..<levelsInMode).map { _ in
      (0..<labelsInLevel).map { _ in
        SKLabelNode(fontNamed: "Font")
      }
    }
  }

【讨论】:

  • 非常感谢详细的回复,这个解决方案完全没有问题!
【解决方案2】:

如果您希望所有 SKLabelNode 指向不同的 SKLabelNode,则需要像这样初始化 3D 数组:

func initAllLabels() {

    var scoreLabels = [[[SKLabelNode]]](count: modesInGame, repeatedValue:
        [[SKLabelNode]](count: levelsInMode, repeatedValue:
        (0..< labelsInLevel).map { _ in SKLabelNode(fontNamed: "Font") }))
}

repeatedValue 是您在单元格中存储的内容(类型或值),计数表示您希望将其存储在数组中的次数。

PS:这个答案是用 Xcode Playground 测试过的,效果很好。


我根据 Airspeed Velocity 的评论编辑了我的答案。

【讨论】:

  • 注意,这会创建一个内部数组,其中每个元素都引用 same 标签实例,因为SKLabelNode 是一个引用类型。更改它将在每个条目中更改它。要创建不同标签的数组,请使用 map: var scoreLabels = Array(count: modesInGame, repeatedValue: Array(count: levelsInMode, repeatedValue: (0..&lt;labelsInLevel).map { _ in SKLabelNode(fontNamed: "Foo") }))
猜你喜欢
  • 2019-06-27
  • 1970-01-01
  • 2018-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多