Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Объектно-ориентированное программирование.PDF
Скачиваний:
208
Добавлен:
01.05.2014
Размер:
3.64 Mб
Скачать

converted to PDF by BoJIoc

<applet code="QueenSolver.class" width=500 height=500>

Если Вы увидите этот текст, ваш броузер не обеспечивает выполнение апплетов Java.

</applet>

<hr>

<p>

Броузер первоначально изображает только одно решение. После каждого щелчка мышью будет появляться новое решение. <p>

<a href="QueenSolver.java">Исходный текст программы.</a> </body>

</html>

A.4. «Задача о восьми ферзях» на языке Objective-C

В данном примере классы Queen и SentinelQueen начинают прямо с раздела implementation без предшествующей части interface. Это вызовет предупреждающее сообщение со стороны компилятора, но не сообщение об ошибке.

/*

Задача «Восемь ферзей», язык Objective-C

Автор: Тимоти Бадд, университет штата Орегон, 1996

*/

#include

#include

/*

«Сторожевой» ферзь находится левее самого левого ферзя

*/

@implementation SentinelQueen : Object - (int) advance

{

/* ничего не делать */ return 1;

}

- (int) findSolution

{

/* ничего не делать */ return 1;

}

-(void) print

{

/* ничего не делать */

}

-(int) canAttack: (int) testRow column: (int) testColumn;

{

/* нельзя атаковать */ return 0;

}

@end

@interface Queen : Object { /* поля данных */

int row; int column; id neighbor;

}

/* методы */

converted to PDF by BoJIoc

-(void) initialize: (int) c neighbor: ngh;

-(int) advance;

-(void) print;

-(int) canAttack: (int) testRow column: (int) testColumn;

-(int) findSolution;

@end

@implementation Queen : Object

- (void) initialize: (int) c neighbor: ngh;

{

/* задать постоянные значения */ column = c;

neighbor = ngh; row = 1;

}

- (int) advance

{

/* сначала попробовать следующую горизонталь */ if (row < 8)

{

row = row + 1;

return [ self findSolution ];

}

/* дальше двигаться нельзя, подвинем соседа */ if ( ! [ neighbor advance ] )

return 0;

/* начать снова с первой горизонтали */ row = 1;

return [ self findSolution ];

}

-(void) print

{

if (neighbor)

[ neighbor print ];

print("column %d row %d\n", column, row);

}

-(int) canAttack: (int) testRow column: (int) testColumn { int columnDifference;

/* если та же горизонталь, то можно аттаковать */ if (row == testRow)

return 1;

columnDifference = testColumn — column; if ((row + columnDifference == testRow) ||

(row — columnDifference == testRow)) return 1;

return [ neighbor canAttack:testRow column: testColumn ];

}

-(int) findSolution

{

/* если сосед может атаковать, то продвинуться */ while ( [ neighbor canAttack:row column: column ] )

if ( ! [ self advance ] ) return 0;

/* в противном случае мы в безопасности */ return 1;

}

@end

main()

converted to PDF by BoJIoc

{

id lastQueen, neighbor; int i;

//создать и инициализировать ферзей neighbor = [ SentinelQueen new ]; for (i = 1; i <= 8; i++)

{

lastQueen = [ Queen new ];

[ lastQueen initialize: i neighbor: neighbor ]; [ lastQueen findSolution ];

neighbor = lastQueen;

}

//теперь напечатать решение

[ lastQueen print ];

}

A.5. «Задача о восьми ферзях» на языке Smalltalk

Класс SentinelQueen не имеет переменных экземпляра. Класс использует следующие методы:

advance

false

canAttack: row column: column false

result

List new

Класс Queen имеет три переменные экземпляра: row, column, neighbor. Определены следующие методы класса:

setColumn: aNumber neighbor: aQueen

"инициализировать поля данных " column := aNumber.

neighbor := aQueen.

"найти первое решение "

row := 1.

canAttack: testRow column: testColumn Ѕ columnDifference Ѕ columnDifference := testColumn — column.

(((row = testRow) or:

[ row + columnDifference = testRow]) or: [ row — columnDifference = testRow])

ifTrue: [ true ].

neighbor canAttack: testRow column: testColumn advance

"сначала испытать следующую строку " (row < 8)

ifTrue: [ row := row + 1. self findSolution ].

"нельзя двигаться дальше, подвинем соседа " (neighbor advance )

ifFalse: [ false ]. row := 1.

self findSolution

findSolution

[ neighbor canAttack: row column: column ] whileTrue: [ self advance

ifFalse: [ false ] ]. true

converted to PDF by BoJIoc

result

neighbor result; addLast: row

Чтобы найти решение, выполняется следующий метод: run | lastQueen |

lastQueen <- SentinelQueen new.

1 to: 8 do: [:i Ѕ lastQueen <- (Queen new) setColumn: i neighbor: lastQueen. lastQueen findSolution ].

'результат получен' print.

lastQueen result do: [:x | x print. ' ' print ]. Char newline print.

Приложение Б

Исходный код игры «Бильярд»

В этом приложении приведен полный код игры «Бильярд», описанной в главе 6. Код дается для версии языка Apple Object Pascal.

Б.1. Версия без использования наследования

*

Программа, моделирующая игру «Бильярд» Демонстрирует объектные свойства языка Object Pascal

Автор: Тимоти Бадд, университет штата Орегон, сентябрь 1995 *)

Program billiards; USES

Windows; type

Ball = object

(* данные, которые поддерживают объекты-шары *) link : Ball;

region : Rect; filler : integer; direction : real; energy : real;

(* процедура инициализации *) procedure initialization (x, y : integer);

(* методы общего характера *)

procedure draw; procedure erase; procedure update;

procedure hitBy(aBall : Ball);

procedure setCenter(newx, newy : integer); procedure setDirection(newDirection : real);

(* вернуть координаты x и y центра шара *) function x : integer;

function y : integer; end;

Wall = object

(* поля данных *)

link : Wall; region : Rect;

converted to PDF by BoJIoc

(* нечто вроде коэффициента отражения шаров при ударе *) convertFactor : real;

(* процедура инициализации *) procedure initialize

(left, top, right, bottom : integer; cf : real); (* рисуем стенку *)

procedure draw;

(* известить стенку, что в нее попал шар *) procedure hitBy(aBall : Ball);

end;

Hole = object

(* поля данных *) link : Hole;

region : Rect;

(* инициализировать положение лузы *) procedure initialize(x,y : integer);

(* нарисовать лузу *) procedure draw;

(* известить лузу, что в нее попал шар *) procedure hitBy(aBall : Ball);

end; var

cueBall : Ball; saveRack : integer; ballMoved : boolean; listOfHoles : Hole; listOfWalls : Wall; listOfBalls : Ball; theWindow : windowPtr;

procedure Wall.initialize

(left, top, right, bottom : integer; cf : real); begin

(* инициализировать коэффициент отражения *) convertFactor := cf;

(* задать прямоугольник для стенки *) SetRect(region, left, top, right, bottom);

end;

procedure Wall.draw; begin

PaintRect(region);

end;

procedure Wall.hitBy(aBall : Ball); begin

(* отразить шар от стенки *) aBall.setDirection(convertFactor — aBall.direction); end;

procedure Hole.initialize(x, y : integer); var left, top, bottom, right : integer; begin

(* идентифицировать область вокруг точки x, y *)

left

:=

y

:= x — 5;

top

— 5;

right

:=

y

:= x + 5;

bottom

+ 5;

SetRect(region, left, top, right, bottom); end;

procedure Hole.draw;

converted to PDF by BoJIoc

begin PaintOval(region);

end;

procedure Hole.hitBy(aBall : Ball); begin

(* забрать у шара энергию *) aBall.energy := 0.0; aBall.erase;

(* передвинуть шар *) if aBall = cueBall then

aBall.setCenter(50,100) else begin

saveRack := saveRack + 1; aBall.setCenter(10 + saveRack*15, 250);

end;

(* обновить изображение шара *) aBall.draw;

end;

procedure Ball.setCenter(newx, newy : integer); var left, top, bottom, right : integer;

begin

(* идентифицировать область вокруг точки x, y *)

left

:=

newy

:= newx — 5;

top

— 5;

right

:=

newy

:= newx + 5;

bottom

+ 5;

SetRect(region, left, top, right, bottom); end;

procedure Ball.initialize(x, y : integer); begin

setCenter(x,y);

setDirection(0,0); energy := 0.0;

end;

procedure Ball.setDirection(newDirection : real); begin

direction := newDirection; end;

procedure Ball.erase; begin

EraseRect(region);

end;

procedure Ball.draw; begin

if self = cueBall then

(* нарисовать окружность *) FrameOval(region)

else

(* нарисовать закрашенный круг *) PaintOval(region);

end;

procedure Ball.update; var

hptr : Hole; wptr : Wall; bptr : Ball;

dx, dy : integer;

converted to PDF by BoJIoc

theIntersection : Rect; i : integer;

begin

if energy > 0.5 then begin

ballMoved := true;

(* удалить шар с экрана *) erase;

(* уменьшить энергию *) energy := energy — 0.05;

(* передвинуть шар *)

dx := trunc(5.0*cos(direction)); dy := trunc(5.0*sin(direction)); offsetRect(region, dx, dy);

(* перерисовать шар *) for i := 1 to 25 do

draw;

(* проверить, не попали ли мы в лузу *) hptr := listOfHoles;

while (hptr <> nil) do begin

if SetRect(region, hptr.region, theIntersection) then begin

hptr.hitBy(self); hptr := nil;

end else

hptr :=hptr.link;

end;

(* проверить, не попали ли мы в стенку *) wptr := listOfWalls;

while (wptr <> nil) do begin

if SetRect(region, wptr.region, theIntersection) then begin

wptr.hitBy(self); wptr := nil;

end else

wptr :=wptr.link;

end;

(* проверить, не попали ли мы в другой шар *) bptr := listOfBalls;

while (bptr <> nil) do begin

if (bptr <> self) and

SetRect(region, bptr.region, theIntersection) then begin

bptr.hitBy(self); bptr := nil;

end else

bptr :=bptr.link;

end;

end;

end;

converted to PDF by BoJIoc

function Ball.x : integer; begin

x := (region.left + region.right) div 2; end;

function Ball.y : integer; begin

y := (region.top + region.bottom) div 2; end;

function hitAngle (dx, dy : real) : real; const

PI = 3.14159265359; var na : real;

begin

if (abs(dx) < 0.05) then na := PI/2

else

na := arctan (abs)dy/dx)); if (dx < 0) then

na := PI — na; if (dy < 0) then

na := -na; hitAngle := na;

end;

procedure Ball.hitBy(aBall : Ball); var

da : real; begin

(* уменьшить энергию ударяющегося шара вдвое *) aBall.energy := aBall.energy / 2.0;

(* и прибавить ее к собственной *) energy := energy + aBall.energy;

(* задать новое направление *)

direction := hitAngle(self.x — aBall.x, self.y — aBall.y); (* направить ударившийся шар *)

da := aBall.direction — direction; aBall.setDirection(aBall.direction + da);

(* продолжить обновление состояния *) update;

end;

procedure mouseButtonDown(x, y : integer); var

bptr : Ball; begin

(* придать белому шару некоторую начальную энергию *) cueBall.energy := 20.0;

(* и направление *)

cueBall.setDirection( hitAngle(cueBall.x — x, cueBall.y — y)); (* цикл до тех пор, пока есть что-то движущееся *)

ballMoved := true; while ballMoved do begin

ballMoved := false; bptr := listOfBalls; while bptr <> nil do begin

bptr.update;

bptr := bptr.link;

converted to PDF by BoJIoc

end;

end;

end;

procedure CreateGlobals; var

i, j : integer; newBall : Ball; newWall : Wall; newHole : Hole;

begin

saveRack := 0; listOfWalls := nil; listOfHoles := nil; listOfBalls := nil;

(* создать стенки *) new (newWall);

newWall.initialize(10, 10, 300, 15, 0.0); newWall.link := listOfWalls;

listOfWalls := newWall; new (newWall);

newWall.initialize(10, 200, 300, 205, 0.0); newWall.link := listOfWalls;

listOfWalls := newWall; new (newWall);

newWall.initialize(10, 10, 15, 200, 3.14159265359); newWall.link := listOfWalls;

listOfWalls := newWall; new (newWall);

newWall.initialize(300, 10, 305, 205, 3.14159265359); newWall.link := listOfWalls;

listOfWalls := newWall; (* создать лузы *)

new (newHole); newHole.initialize(15, 15); newHole.link := listOfHoles; listOfHoles := newHole;

new (newHole); newHole.initialize(15, 200); newHole.link := listOfHoles; listOfHoles := newHole;

new (newHole); newHole.initialize(300, 15); newHole.link := listOfHoles; listOfHoles := newHole;

new (newHole); newHole.initialize(300, 200); newHole.link := listOfHoles; listOfHoles := newHole;

(* создать шары *) new (cueBall);

cueBall.initialize(50, 96); cueBall.link := nil; listOfBalls := cueBall; for i := 1 to 5 do

begin

for j := 1 to i do begin

converted to PDF by BoJIoc

new (newBall); newBall.initialize(190 + i*8,

100 + 16*j — 8*i); newBall.link := listOfBalls; listOfBalls := newBall;

end;

end;

end;

procedure drawBoard; var

aWall : Wall;

aBall : Ball;

aHole : Hole; begin

SetPort(theWindow); aWall := listOfWalls; while (aWall <> nil) do begin

aWall.draw;

aWall := aWall.link; end;

aHole := listOfHoles; while (aHole <> nil) do begin

aHole.draw;

aHole := aHole.link; end;

aBall := listOfBalls; while (aBall <> nil) do begin

aBall.draw;

aBall := aBall.link; end;

cueBall.draw;

end;

procedure createWindow; var

name : STR255; winType : integer; windowRect : Rect;

begin

name := 'billiard game'; SetRect(windowRect, 50, 70, 500, 400);

winType := DocumentProc; theWindow :=

NewWindow(nil, windowRect, name, TRUE, winType, WindowPtr(-1), True, LongInt(09));

SelectWindow(theWindow);

showWindow(theWindow);

end;

procedure EVentLoop; var

ignore : boolean; event : eventRecord; localPoint : Point; done : boolean;