2017-10-16 63 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的部分 –