2.2.2 Концептуальный анализ
3 Переход от концептуальной модели к объектной
Элемент концептуальной модели |
Элемент объектной модели |
Объект: пользователь |
Пользователь системы, объектной модели явно не представлен. |
Объект: игра |
Исполнитель системы, в объектной модели явно не представлен |
Объект: Количество игроков |
Поле onetwo класса SuperCounter |
Объект: Клетка |
Класс Pixel |
Объект: Номер клетки |
Поле pos класса Pixel |
Объект: Конь |
Класс Horse |
Объект: Цветок |
Элемент класса Pixel |
Объект: Конь1 |
Элемент класса Horse |
Объект: Конь2 |
Элемент класса Horse |
Отношение: вывести |
Часть метода onePlLogic |
Отношение: победил |
Определяется в части методов onePlLogic и twoPlLogic |
4 Программная реализация
Руководствуясь объектной моделью, полученной ранее, была произведена программная реализация. Для этого в среде VisualAge Smalltalk были заведены классы, показанные на рис. 1 Всего потребовалось создать два обычных Smalltalk-класса и один класс с визуальым компонентом. Кроме того, один класс был создан средой программирования автоматически и служит обычным SmallTalk-классом. Далее последовательно опишем содержание пользовательских классов.
Класс Green
Визуальная часть
Описание использованных связей:
1) Связь event-to-action между событием aboutToOpenWidget окна Horse the game и пользовательским методом init.
2) Связь event-to-action между событием aboutToOpenWidget окна Horse the game и пользовательским методом addNewEvents.
3) Связь event-to-action между событием clicked подменю 1 player c пользовательским методом onepl.
4) Связь event-to-action между свойством normalResult связи №3 и пользовательским методом initOne.
5) Связь event-to-action между событием clicked подменю 2 player c пользовательским методом twopl.
6) Связь event-to-action между свойством normalResult связи №5 и пользовательским методом initTwo.
7) Связь event-to-action между событием clicked подменю Restart c пользовательским методом exit.
8) Связь event-to-action между свойством normalResult связи №7 и пользовательским методом init.
9) Связь event-to-action между событием clicked подменю Exit c пользовательским методом exit.
10) Связь event-to-action между свойством normalResult связи №9 и методом закрытия окна Horse the game.
Невизуальная часть
Содержит 29 методов.
1,2)Методы bHorse и wHorse возвращают позицию черного/белого коня:
bHorse
^bHorse
wHorse
^wHorse
3) Метод breed:
breed
"Возвращает номер породы лошади"
^breed
4) Метод newHorse:
newHorse
"Возвращает позицию нажатой клетки"
^newHorse
5-12) Методы p1-p4 и p1:-p4::
p1:CgPCXFileFormat
p1:=CgPCXFileFormat
p1
^p1
"Возвращает адрес файла формата PCX"
13,14)Методы pixmaps и pixmaps::
pixmaps:CgPixmap
pixmaps:=CgPixmap
pixmaps
^pixmaps
15)Метод pl12:
pl12
^pl12
"Возвращает количество игрооков"
16)Метод playerSCounter:
playerSCounter
^playerSCounter
"Возвращает количество собранных цветов"
17)Метод addNewEvents:
addNewEvents
"Вызывает обработчик событий и направляет события методу buttonEvent:clientData:callData: "
(self subpartNamed: 'Drawing Area1') widget
addEventHandler: ButtonPressMask
receiver: self
selector: #buttonEvent:clientData:callData:
clientData: nil
18)Метод aDrawingArea clientData: clientData callData: event:
buttonEvent: aDrawingArea clientData: clientData callData: event
"Проверяет, что состоялся клик по игровому полю"
event button = 1
ifTrue: [
event type = ButtonPress
ifTrue: [ ^ self button1PressAt: event ].
].
19) Метод button1PressAt: event :
button1PressAt: event
"Переводит координаты клика сначала в координаты клетки, а затем в номер клетки"
|xh yh|
xh:=(event x/50) truncated + 1.
yh:=(event y/50) truncated.
newHorse pos:yh*10+ xh.
self drawing.
pl12 onetwo=1 ifTrue:
[
self onePlLogic
].
pl12 onetwo=2 ifTrue:
[
self twoPlLogic
]
20) Метод drawing:
drawing
"Выполняет перерисовку игрового поля в соответствии с содержанием pixmaps"
1 to: 100 do: [:i|
(pixels at:i) vis =1
ifTrue: [pixmaps:=p1] .
(pixels at:i) vis =2
ifTrue: [pixmaps:=p2] .
(pixels at:i) vis =3
ifTrue: [pixmaps:=p3] .
(pixels at:i) vis =4
ifTrue: [pixmaps:=p4] .
pixmaps copyArea: winCg
gc: gc
srcX:0
srcY: 0
width: 50
height: 50
destX: ((i-1)\\10)*50
destY: ((i-1)//10)*50.
].
21) Метод onePlLogic:
onePlLogic
"Осуществляет логику игры одного игрока. Если игрок кликнул на доступную клетку, то счетчик переключается, происходит перерисовка игрового поля, а также осуществляется проверка на выигрыш"
|a b c d|
a:=(newHorse pos)\\10.
b:=(newHorse pos)//10.
c:=(wHorse pos)\\10.
d:=(wHorse pos)//10.
a=0
ifTrue:[a:=10. b:=b-1].
c=0
ifTrue:[c:=10. d:=d-1].
(((a=(c+1))&(b=(d+2))) |
((a=(c+1))&(b=(d-2))) |
((a=(c-1))&(b=(d+2))) |
((a=(c-1))&(b=(d-2))) |
((a=(c+2))&(b=(d+1))) |
((a=(c+2))&(b=(d-1))) |
((a=(c-2))&(b=(d+1))) |
((a=(c-2))&(b=(d-1))))&
((pixels at: newHorse pos) vis=2)
ifTrue: [playerSCounter sCount: (playerSCounter sCount)+1.
self redraw.
playerSCounter sCount=100
ifTrue:
[
OSMessageBox new
message:'Congratulations!';
style:0;
label:'WOW!';
open
].
]
22) Метод twoPlLogic:
twoPlLogic
"Осуществляет логику игры двух игроков. В соответствии с породой лошади осуществяется очередность хода. Если игрок кликнул на доступную для его лошади клетку, то осуществляется перерисовка игрового поля, меняется порода лошади для хода следующего игрока, а также выполняется проверка на выигрыш одного из игроков."
|a b c d|
breed wb=3
ifTrue:
[
a:=(newHorse pos)\\10.
b:=(newHorse pos)//10.
c:=(wHorse pos)\\10.
d:=(wHorse pos)//10.
a=0
ifTrue:[a:=10. b:=b-1].
c=0
ifTrue:[c:=10. d:=d-1].
(((a=(c+1))&(b=(d+2))) |
((a=(c+1))&(b=(d-2))) |
((a=(c-1))&(b=(d+2))) |
((a=(c-1))&(b=(d-2))) |
((a=(c+2))&(b=(d+1))) |
((a=(c+2))&(b=(d-1))) |
((a=(c-2))&(b=(d+1))) |
((a=(c-2))&(b=(d-1))))&
((pixels at: newHorse pos) vis=2)
ifTrue:
[
self redraw.
breed wb:4.
]
].
breed wb=4
ifTrue:
[
a:=(newHorse pos)\\10.
b:=(newHorse pos)//10.
c:=(bHorse pos)\\10.
d:=(bHorse pos)//10.
a=0
ifTrue:[a:=10. b:=b-1].
c=0
ifTrue:[c:=10. d:=d-1].
(((a=(c+1))&(b=(d+2))) |
((a=(c+1))&(b=(d-2))) |
((a=(c-1))&(b=(d+2))) |
((a=(c-1))&(b=(d-2))) |
((a=(c+2))&(b=(d+1))) |
((a=(c+2))&(b=(d-1))) |
((a=(c-2))&(b=(d+1))) |
((a=(c-2))&(b=(d-1))))&
(((pixels at: newHorse pos) vis=2)|((pixels at: newHorse pos) vis=3))
ifTrue:
[
self redraw.
breed wb:3.
(pixels at: newHorse pos) vis=3
ifTrue:
[
OSMessageBox new
message:'Black horse won' ;
style:0;
label:'WOW!';
open
].
]
].
23) Метод redraw:
Redraw
"Осуществляет визуальный прыжок лошади на другую позицию в соответствии с ее породой, затем вызывается метод перерисовки игрового поля."
breed wb=3
ifTrue:
[
pixels at:(wHorse pos) put: (Pixel new pos: (wHorse pos); vis: 1).
wHorse pos:newHorse pos.
pixels at:(newHorse pos) put: (Pixel new pos: (newHorse pos); vis: 3).
].
breed wb=4
ifTrue:
[
pixels at:(bHorse pos) put: (Pixel new pos: (bHorse pos); vis: 2).
bHorse pos:newHorse pos.
pixels at:(newHorse pos) put: (Pixel new pos: (newHorse pos); vis: 4).
].
self drawing.
24) Метод init:
init
"Подключает необходимые для начал игры класса, загружает изображения, заполняет игровое поле цветами и вызывает метод перерисовки"
pl12:=SuperCounter new.
pl12 onetwo: 0.
breed:=SuperCounter new.
breed wb:3.
winCg:=(self subpartNamed: 'Drawing Area1') widget window.
gc := winCg createGC: None values: nil.
newHorse:=Horse new.
p1:= CgPCXFileFormat new.
p1:= p1 loadFromFile:'C:\Images\green.pcx'.
p1:= p1 asPixmap.
p2:= CgPCXFileFormat new.
p2:= p2 loadFromFile:'C:\Images\flower.pcx'.
p2:= p2 asPixmap.
p3:= CgPCXFileFormat new.
p3:= p3 loadFromFile:'C:\Images\whorse.pcx'.
p3:= p3 asPixmap.
p4:= CgPCXFileFormat new.
p4:= p4 loadFromFile:'C:\Images\bhorse.pcx'.
p4:= p4 asPixmap.
pixels:= Dictionary new.
1 to: 100 do: [:i|
pixels at:(i) put: (Pixel new pos: i; vis: 2 ).
].
self drawing.
25,26) Методы onepl и twopl объявляют количество игроков:
onepl
pl12 onetwo:1.
twopl
pl12 onetwo:2
27) Метод initOne:
initOne
"Объявляет необходимые переменные, а также перерисовывает игровое поля для начала игры"
wHorse:=Horse new.
newHorse:=Horse new.
playerSCounter:=SuperCounter new.
playerSCounter sCount: 1.
wHorse pos:1.
pixels at:1 put: (Pixel new pos: 1; vis:3).
self drawing.
28) Метод initTwo:
initTwo
"Объявляет необходимые переменные, а также перерисовывает игровое поля для начала игры"
wHorse:=Horse new.
bHorse:=Horse new.
newHorse:=Horse new.
wHorse pos:1.
bHorse pos:100.
pixels at:1 put: (Pixel new pos: 1; vis:3).
pixels at:100 put: (Pixel new pos:100; vis:4).
self drawing.
29) Метод exit:
exit
"Чистит pixmap, p1-p4 и gc для завершения игры"
p1 isNil ifFalse: [p1 freePixmap].
p2 isNil ifFalse: [p2 freePixmap].
p3 isNil ifFalse: [p3 freePixmap].
p4 isNil ifFalse: [p4 freePixmap].
pixmaps isNil ifFalse: [pixmaps freePixmap].
gc isNil ifFalse:[gc freeGC].
Класс Horse
Класс Horse содержит 2 метода:
1,2) Методы pos и pos: служат для хранения позиций коней:
pos
^pos
pos:integer
pos:=integer.
Класс Pixel
Класс Pixel содержит 4 метода.
1,2) Методы pos и pos: служат для хранения позиций клеток:
pos
^pos
pos:integer
pos:=integer.
3,4) Методы vis и vis: служат для хранения номеров видов клеток:
vis
^vis
vis:integer
vis:=integer
Класс SuperCounter
Класс SuperCounter содержит 6 методов:
1,2) Методы onetwo и onetwo: служат для хранения количества игроков
onetwo
^onetwo
onetwo:integer
onetwo:=integer
3,4) Методы sCount и sCount: служат для хранения количества собранных цветов:
sCount
^sCount
sCount:integer
sCount:=integer
5,6) Методы wb и wb: служат для хранения пород лошадей:
wb
^wb
wb:integer
wb:=integer