2017-10-16 61 views
0

下面的代码会产生一个错误,并且无法运行,因为表达式太“复杂”。如何分解表达式涉及按位移操作符? Swift

for row in 0...NumRows { 
     for column in 0...NumColumns { 
      let topLeft = (column > 0) && (row < NumRows) 
       && level.tileAt(column: column - 1, row: row) != nil 
      let bottomLeft = (column > 0) && (row > 0) 
       && level.tileAt(column: column - 1, row: row - 1) != nil 
      let topRight = (column < NumColumns) && (row < NumRows) 
       && level.tileAt(column: column, row: row) != nil 
      let bottomRight = (column < NumColumns) && (row > 0) 
       && level.tileAt(column: column, row: row - 1) != nil 

      let value = Int(topLeft.hashValue) | Int(topRight.hashValue) << 1 | Int(bottomLeft.hashValue) << 2 | Int(bottomRight.hashValue) << 3 

      if value != 0 && value != 6 && value != 9 { 

       let name = String(format: "Tile_%ld", value) 
       let tileNode = SKSpriteNode(imageNamed: name) 
       tileNode.size = CGSize(width: TileWidth, height: TileHeight) 
       var point = pointFor(column: column, row: row) 
       point.x -= TileWidth/2 
       point.y -= TileHeight/2 
       tileNode.position = point 
       tilesLayer.addChild(tileNode) 

      } 
     } 
    } 

具体来说这一行:

let value = Int(topLeft.hashValue) | Int(topRight.hashValue) << 1 | Int(bottomLeft.hashValue) << 2 | Int(bottomRight.hashValue) << 3 

的误差如下:

表达过于复杂在合理时间内解决;考虑将表达式分解成不同的子表达式

如何分解值的表达式,使得它后面的代码保持相同的答案?

回答

2

hashValue已经是Int,所以Int(...)构造函数不是 需要。这将编译在Xcode 9:

let value = topLeft.hashValue | (topRight.hashValue << 1) | (bottomLeft.hashValue << 2) | (bottomRight.hashValue << 3) 

但是,这是一个坏主意!它依赖于具有特定值布尔值的哈希值:

false.hashValue == 0 
true.hashValue == 1 

其无处保证。 (只有保证是相同的元素具有相同的散列值。我们甚至不能假定散列 值在您的程序的不同执行中相等, 请参阅Hashable)。

一个更好的解决办法是

let value = (topLeft ? 1 : 0) + (topRight ? 2 : 0) + (bottomLeft ? 4 : 0) + (bottomRight ? 8 : 0) 

另外,使用switch语句。例如:

switch (topLeft, topRight, bottomLeft, bottomRight) { 
case (false, false, false, false): 
    // ... all false ... 
case (false, true, true, false): 
    // ... topRight and bottomLeft are true ... 
case (true, false, false, true): 
    // ... topLeft and bottomRight are true ... 
default: 
    // ... all other cases ... 
} 
+0

不错的答案,特别是关于不依赖boolean的hashValue的部分 –