2010-11-03 104 views
6

如何簡化if語句?它會產生一個加號: http://i.stack.imgur.com/PtHO1.png如何簡化這個很長的if語句?

如果聲明已完成,則在x和y座標處設置一個塊。

for y in range(MAP_HEIGHT): 
    for x in range(MAP_WIDTH): 
     if (x%5 == 2 or x%5 == 3 or x%5 == 4) and \ 
      (y%5 == 2 or y%5 == 3 or y%5 == 4) and \ 
      not(x%5 == 2 and y%5 == 2) and \ 
      not(x%5 == 4 and y%5 == 2) and \ 
      not(x%5 == 2 and y%5 == 4) and \ 
      not(x%5 == 4 and y%5 == 4): 
      ... 
+0

也許我沒有解釋得很好。在if語句完成的x和y座標處設置一個塊。 – 2010-11-03 15:01:42

+2

請不要添加評論。請**更新**的問題是完整的。請**修復**問題並刪除評論。 – 2010-11-03 15:24:22

+0

我敢肯定,你可以通過使用一些智能切片來壓縮這一點,但我有點懶得解決它。 – Daenyth 2010-11-03 18:21:07

回答

15

這是相同的:

if (x % 5 == 3 and y % 5 > 1) or (y % 5 == 3 and x % 5 > 1): 
+1

該死的,你贏了。 ;-)但是請刪除多餘的括號。 – 2010-11-03 14:45:48

+1

除非我錯了,否則OP的陳述*不會*畫出例如x = 1; y = 3. – 2010-11-03 14:50:51

+0

@Iain Galloway - 好點 - 現在已經修好了。 – 2010-11-03 14:51:50

7

有兩種瑣碎修正:

  • 緩存的x % 5結果和y % 5
  • 使用in或鏈狀<測試值:

此外,測試對<= 4(或< 5)實際上是多餘的,因爲lxly值將是< 5.

for y in range(MAP_HEIGHT): 
    for x in range(MAP_WIDTH): 
     lx = x % 5 # for local-x 
     ly = y % 5 # for local-y 
     if lx > 1 and y > 1 and \ 
      not (lx == 2 and ly == 2) and \ 
      not (lx == 4 and ly == 2) and \ 
      not (lx == 2 and ly == 4) and \ 
      not (lx == 4 and ly == 4): 

或者你只是保持實際允許的元組的列表:

cross_fields = [(2, 3), (3, 2), (3, 3), (3, 4), (4, 3)] 

for y in range(MAP_HEIGHT): 
    for x in range(MAP_WIDTH): 
     if (x % 5, y % 5) in cross_fields: 
+1

哇。你做到了這一點......可讀,我根本沒有想到使用列表/元組。他們都工作,除了第一段代碼有一些錯誤。最後一個耦合的條件語句應該不是(lX == 4和lY == 4),並且應該有一個lX!= 0和lY!= 0. – 2010-11-03 15:04:46

+0

@Azrathud:我實際上發現Dave的答案稍好些。無論如何,感謝您的更正。 – 2010-11-03 15:06:31

+0

我認爲使用元組是我們要走的路。它不僅更清潔,而且更靈活。 – 2010-11-04 10:16:49

2

大廈康拉德的回答,您可以進一步簡化它:

for y in range(MAP_HEIGHT): 
    for x in range(MAP_WIDTH): 
     lx = x % 5 # for local-x 
     ly = y % 5 # for local-y 
     if (1 < lx < 5 and 1 < y < 5 and 
      (lx, ly) not in ((2, 2), (4, 2), (2, 4), (4, 2))): 
+0

我不認爲元組列表是正確的。如果不是(2,3),(3,3),(4,3),(3,2)和(3,4)? (或者等一等,你錯過了不是嗎?) – 2010-11-03 14:55:33

+0

是的,錯過了一個沒有,加了回來。 – 2010-11-03 15:07:41

1

康拉德的第二個答案: -

cross_fields = [(2, 3), (3, 2), (3, 3), (3, 4), (4, 3)] 

for y in range(MAP_HEIGHT): 
    for x in range(MAP_WIDTH): 
    if (x % 5, y % 5) in cross_fields: 

可能是最好的一個。

不過,我會貢獻: -

for y in range(MAP_HEIGHT): 
    for x in range(MAP_WIDTH): 
    lx = x % 5 
    ly = y % 5 
    if (lx > 1 and ly == 3) or (ly > 1 and lx == 3): 
12

基本上你平鋪一個5x5的二進制模式。這是一個明確的表達:

pattern = [[0, 0, 0, 0, 0], 
      [0, 0, 0, 0, 0], 
      [0, 0, 0, 1, 0], 
      [0, 0, 1, 1, 1], 
      [0, 0, 0, 1, 0]] 

for y in range(MAP_HEIGHT): 
    for x in range(MAP_WIDTH): 
     if pattern[x%5][y%5]: 
      ... 

這是一個非常簡單和一般的方法,可以很容易地修改模式。

0

像這樣優化邏輯功能的一般解決方案是Karnaugh map。你的真值表應該是你想要的字面加形狀,行和列是你的模塊化測試。

+0

啊。與馬蒂諾的答案類似嗎? – 2010-11-04 06:06:08

+0

第一步將是類似的,但卡諾圖是一種技術,用於提取覆蓋案例所需的最小邏輯表達式。 – 2010-11-04 06:44:45

+0

(&@Iain Galloway):在我的回答中使用的位圖基本上是兩個輸入變量('x%5'和'y%5')的K-映射 - 所以,結果是一樣的我的答案,但是以一種完全不同的(而且更簡單的恕我直言)的方式來到。 – martineau 2010-11-19 20:15:13