2010-11-03 37 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