我正在研究Pharo中的简单棋盘游戏,我在我的棋盘上有一个方法可以将对象添加到单元格中。单元格只是对象上的点的字典。
作为该方法的一部分,我想强制Point应该大于零,但小于板的宽度和高度,换句话说,它应该实际上在板上。这样做的最佳方式是什么?
我目前的尝试是这样的:
at: aPoint put: aCell
((((aPoint x > self numberOfRows)
or: [aPoint x <= 0])
or: [aPoint y > self numberOfColumns ])
or: [aPoint y <= 0])
ifTrue: [ self error:'The point must be inside the grid.' ].
self cells at: aPoint put: aCell .
与所有那些parens的lisp-y!但是我不能使用短路or:
而不关闭每个表达式,因此它评估为布尔而不是块(或or:or:or:or:
消息)。我可以使用二进制运算符|
代替和for-go短路,但这似乎不对。
那么正确的Smalltalk-ish方法处理这个问题是什么?
答案 0 :(得分:6)
通常or:
嵌套如下:
(aPoint x > self numberOfRows
or: [ aPoint x <= 0
or: [ aPoint y > self numberOfColumns
or: [ aPoint y <= 0 ] ] ])
ifTrue: [ self error: 'The point must be inside the grid.' ].
由于第一个参数的重复测试(检查字节码以查看差异),您的嵌套是短路但效率较低。
备选方案,您可以使用assert:
上定义的assert:description:
或Object
:
self
assert: (aPoint x > self numberOfRows
or: [ aPoint x <= 0
or: [ aPoint y > self numberOfColumns
or: [ aPoint y <= 0 ] ] ])
description: 'The point must be inside the grid.'
答案 1 :(得分:4)
任何时候都是严重嵌套的东西,是时候调用另一种方法了。
isValidPoint: aPoint
aPoint x > self numberOfRows ifTrue: [^ false].
aPoint x <= 0 ifTrue: [^ false].
aPoint y > self numberOfColumns ifTrue: [^ false].
aPoint y <= 0 ifTrue: [^ false].
^ true.
一般来说,您的方法应该相对平坦。如果没有,那就重构一下。
答案 2 :(得分:3)
您可以简单地使用在该范围内有效的所有点预填充'cells'字典,即在初始化的某个位置:
1 to: numberOfRows do: [:y |
1 to: numberOfCols do: [:x |
cells at: x@y put: dummy "or nil " ] ]
那么在给定点添加单元格的方法看起来很简单:
at: aPoint put: aCell
self cells at: aPoint ifAbsent: [ self error: 'The point must be inside the grid.' ].
self cells at: aPoint put: aCell .
还有一个帮助方法#between:和:,您可以使用它来最小化代码混乱:
((aPoint x between: 1 and: self numCols) and: [
aPoint y between: 1 and: self numRows ]) ifFalse: [ ... bummer ... ]