home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BURKS 2
/
BURKS_AUG97.ISO
/
BURKS
/
LANGUAGE
/
SMALTALK
/
TEXTBOOK
/
AP22.ST
(
.txt
)
< prev
next >
Wrap
Text File
|
1997-04-22
|
12KB
|
470 lines
'Smalltalk Textbook Appendix 22'!
Model subclass: #EngiPuzzleModel
instanceVariableNames: 'puzzleGrid puzzleImage puzzleBoard '
classVariableNames: ''
poolDictionaries: ''
category: 'Engi-Puzzle'!
EngiPuzzleModel comment:
'
Engi 0.06 (19 March 1994)
Copyright (C) 1994 by Atsushi Aoki
'!
!EngiPuzzleModel methodsFor: 'accessing'!
pointAt: aPoint
(self containsPoint: aPoint)
ifTrue: [^(puzzleBoard at: aPoint y)
at: aPoint x].
^nil!
pointAt: aPoint put: stoneNumber
(self containsPoint: aPoint)
ifTrue: [(puzzleBoard at: aPoint y)
at: aPoint x put: stoneNumber]!
puzzleGrid
^puzzleGrid!
puzzleGridSize
^self puzzleGridX * self puzzleGridY!
puzzleGridX
^self puzzleGrid x!
puzzleGridY
^self puzzleGrid y!
puzzleImage
^puzzleImage!
stoneHeight
^(self puzzleImage height // self puzzleGridY) rounded!
stoneWidth
^(self puzzleImage width // self puzzleGridX) rounded! !
!EngiPuzzleModel methodsFor: 'testing'!
containsPoint: aPoint
^((1 to: self puzzleGridX)
includes: aPoint x)
and: [(1 to: self puzzleGridY)
includes: aPoint y]!
isPerfect
| stoneNumber |
stoneNumber := 1.
1 to: self puzzleGridY do: [:y | 1 to: self puzzleGridX
do:
[:x |
stoneNumber = (self pointAt: x @ y) ifFalse: [^false].
stoneNumber := stoneNumber + 1]].
^true!
whereIsBlank
| stoneNumber |
1 to: self puzzleGridY do: [:y | 1 to: self puzzleGridX
do:
[:x |
stoneNumber := self pointAt: x @ y.
self puzzleGridSize = stoneNumber ifTrue: [^x @ y]]].
^self puzzleGridSize!
wherePoint: aPoint
^aPoint x // self stoneWidth + 1 @ (aPoint y // self stoneHeight + 1)! !
!EngiPuzzleModel methodsFor: 'moving'!
movePoints: aPoint
| collection point |
(self containsPoint: aPoint)
ifFalse: [^OrderedCollection new].
collection := OrderedCollection new.
aPoint x
to: self puzzleGridX
by: 1
do:
[:x |
point := x @ aPoint y.
collection add: point.
(self pointAt: point)
= self puzzleGridSize ifTrue: [^collection]].
collection := OrderedCollection new.
aPoint x
to: 1
by: -1
do:
[:x |
point := x @ aPoint y.
collection add: point.
(self pointAt: point)
= self puzzleGridSize ifTrue: [^collection]].
collection := OrderedCollection new.
aPoint y
to: self puzzleGridY
by: 1
do:
[:y |
point := aPoint x @ y.
collection add: point.
(self pointAt: point)
= self puzzleGridSize ifTrue: [^collection]].
collection := OrderedCollection new.
aPoint y
to: 1
by: -1
do:
[:y |
point := aPoint x @ y.
collection add: point.
(self pointAt: point)
= self puzzleGridSize ifTrue: [^collection]].
collection := OrderedCollection new.
^collection!
moveStone: aPoint
| movePoints srcPoints dstPoints srcPoint dstPoint |
movePoints := self movePoints: aPoint.
movePoints isEmpty ifTrue: [^self].
srcPoints := movePoints reverse.
srcPoints removeFirst.
dstPoints := movePoints reverse.
dstPoints removeLast.
1 to: srcPoints size
do:
[:index |
srcPoint := srcPoints at: index.
dstPoint := dstPoints at: index.
self moveStone: srcPoint to: dstPoint].
(srcPoints isEmpty not and: [self isPerfect])
ifTrue: [(Screen default) ringBell; ringBell; ringBell]!
moveStone: srcPoint to: dstPoint
self pointAt: dstPoint put: (self pointAt: srcPoint).
self changed: dstPoint.
self pointAt: srcPoint put: self puzzleGridSize.
self changed: srcPoint! !
!EngiPuzzleModel methodsFor: 'menu messages'!
normalize
| stoneNumber |
stoneNumber := 1.
1 to: self puzzleGridY do: [:y | 1 to: self puzzleGridX
do:
[:x |
self pointAt: x @ y put: stoneNumber.
stoneNumber := stoneNumber + 1]].
self changed!
randomize
| set collection random number index |
set := Set new.
collection := OrderedCollection new.
random := Random new.
[collection size < self puzzleGridSize]
whileTrue:
[number := (random next * self puzzleGridSize + 1) truncated.
(set includes: number) not
ifTrue:
[set add: number.
collection add: number]].
index := 1.
1 to: self puzzleGridY do: [:y | 1 to: self puzzleGridX
do:
[:x |
self pointAt: x @ y put: (collection at: index).
index := index + 1]].
self changed! !
!EngiPuzzleModel methodsFor: 'private'!
grid: gridPoint image: anImage
| aPixmap aBlock graphicsContext aPoint |
puzzleGrid := gridPoint.
puzzleBoard := Array new: self puzzleGridY.
1 to: puzzleBoard size do: [:index | puzzleBoard at: index put: (Array new: self puzzleGridX)].
aPixmap := Pixmap extent: (anImage extent truncateTo: self puzzleGrid).
aBlock :=
[graphicsContext := aPixmap graphicsContext.
aPoint := aPixmap bounds center - anImage bounds center.
anImage displayOn: graphicsContext at: aPoint.
puzzleImage := aPixmap asImage].
[aBlock value]
valueNowOrOnUnwindDo: [aPixmap close].
self randomize.
^self! !
"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
EngiPuzzleModel class
instanceVariableNames: ''!
!EngiPuzzleModel class methodsFor: 'instance creation'!
grid: gridPoint
^self grid: gridPoint image: (self defaultPuzzleImage: gridPoint)!
grid: gridPoint image: anImage
^super new grid: gridPoint image: anImage!
new
^self grid: self defaultPuzzleGrid image: (self defaultPuzzleImage: self defaultPuzzleGrid)! !
!EngiPuzzleModel class methodsFor: 'defaults'!
defaultPuzzleGrid
^4 @ 4!
defaultPuzzleImage: grid
| extent stone stones |
extent := self defaultStoneExtent.
stone :=
[:index |
| pixmap gc paragraph point rect image |
pixmap := Pixmap extent: extent.
[gc := pixmap graphicsContext.
index = (grid x * grid y)
ifTrue:
[pixmap background: (ColorValue brightness: 1).
pixmap clear]
ifFalse:
[pixmap background: (ColorValue brightness: 0.5).
pixmap clear.
paragraph := index printString asComposedText.
point := pixmap bounds center - paragraph bounds center.
gc paint: (ColorValue brightness: 1).
paragraph displayOn: gc at: point + (-1 @ -1).
paragraph displayOn: gc at: point + (-1 @ 0).
paragraph displayOn: gc at: point + (-1 @ 1).
paragraph displayOn: gc at: point + (0 @ -1).
paragraph displayOn: gc at: point + (0 @ 1).
paragraph displayOn: gc at: point + (1 @ -1).
paragraph displayOn: gc at: point + (1 @ 0).
paragraph displayOn: gc at: point + (1 @ 1).
gc paint: (ColorValue brightness: 0).
paragraph displayOn: gc at: point.
rect := 0 @ 0 extent: extent - (1 @ 1).
gc paint: (ColorValue brightness: 0.25).
gc displayLineFrom: rect bottomLeft to: rect bottomRight.
gc displayLineFrom: rect topRight to: rect bottomRight.
gc paint: (ColorValue brightness: 0.75).
gc displayLineFrom: rect topLeft to: rect topRight.
gc displayLineFrom: rect topLeft to: rect bottomLeft].
image := pixmap asImage]
valueNowOrOnUnwindDo: [pixmap close].
image].
stones :=
[| pixmap gc index image point |
pixmap := Pixmap extent: grid * extent.
[gc := pixmap graphicsContext.
index := 1.
1 to: grid y do: [:j | 1 to: grid x
do:
[:i |
image := stone value: index.
point := i - 1 * extent x @ (j - 1 * extent y).
image displayOn: gc at: point.
index := index + 1]].
image := pixmap asImage]
valueNowOrOnUnwindDo: [pixmap close].
image].
^stones value!
defaultStoneExtent
^35 @ 35! !
!EngiPuzzleModel class methodsFor: 'examples'!
example1
"EngiPuzzleModel example1."
| puzzleModel |
puzzleModel := EngiPuzzleModel new.
EngiPuzzleView openOn: puzzleModel.
^puzzleModel!
example2
"EngiPuzzleModel example2."
| puzzleModel |
puzzleModel := EngiPuzzleModel grid: 3 @ 3.
EngiPuzzleView openOn: puzzleModel.
^puzzleModel!
example3
"EngiPuzzleModel example3."
| puzzleModel |
puzzleModel := EngiPuzzleModel grid: 3 @ 3 image: Image fromUser.
EngiPuzzleView openOn: puzzleModel.
^puzzleModel!
example4
"EngiPuzzleModel example4."
| puzzleModel |
puzzleModel := EngiPuzzleModel new.
EngiPuzzleView openOn: puzzleModel.
EngiPuzzleView openOn: puzzleModel.
puzzleModel normalize.
(Delay forSeconds: 1) wait.
puzzleModel moveStone: 3 @ 4.
(Delay forSeconds: