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

converted to PDF by BoJIoc

begin

done := false while not done do begin

systemTask;

ignore := GetNextEvent(everyEvent, event); case event.what of

(* выйти и прекратить работу *) keyDown : done := true; mouseDown : begin

localPoint := event.where; GlobalToLocal(localPoint); mouseButtonDown(localPoint.h, localPoint.v);

end;

updateEvt: drawBoard; end; (* case *)

end;

end; begin

MaxApplZone;

InitGraf(@qd.thePort);

InitWindows;

InitCursor;

createGlobals;

createWindow;

eventLoop;

end.

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

(*

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

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

Program billiards; USES

Windows; type

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

link : GraphicalObject; region : rect;

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

procedure setRegion(left, top, right, bottom : integer); (* операции с графическими объектами *)

procedure draw; procedure erase; procedure update;

function intersect(anObj : GraphicalObject) : boolean; procedure hitBy(aBall : GraphicalObject);

end;

Ball = object (GraphicalObject)

(* данные, которые содержатся в объектах-шарах *) direction : real;

energy : real;

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

converted to PDF by BoJIoc

procedure initialize(x, y : integer); (* методы общего характера *)

procedure draw; override; procedure erase; override; procedure update; override;

procedure hitBy(aBall : GraphicalObject); override; procedure setCenter(newx, newy : integer); procedure setDirection(newDirection : real);

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

function y : integer; end;

CueBall = object (Ball)

(* изменяется только подпрограмма рисования *) procedure draw; override;

end;

Wall = object (GraphicalObject)

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

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

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

procedure draw; override;

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

end;

Hole = object (GraphicalObject)

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

procedure draw; override;

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

end; var

cueBall : Ball; saveRack : integer; ballMoved : boolean;

listOfObjects : GraphicalObject; theWindow : windowPtr;

procedure GraphicalObject.setRegion (left, top, right, bottom : integer);

begin

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

procedure GraphicalObject.draw; begin

end;

procedure GraphicalObject.erase; begin

EraseRect(region);

end;

procedure GraphicalObject.update; begin

end;

procedure GraphicalObject.hitBy(aBall : GraphicalObject);

converted to PDF by BoJIoc

begin end;

procedure GraphicalObject.intersect (anObj : GraphicalObject) : boolean;

var

theIntersection : Rect; begin

intersect := SetRect(region, anObj.region, theIntersection); end;

procedure Wall.hitBy(anObj : GraphicalObject); var

aBall : Ball; begin

if Member(anObj, Ball) then begin

aBall := Ball(anObj);

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

end;

end;

procedure Hole.hitBy(anObj : GraphicalObject); var

aBall : Ball; begin

if Member(anObj, Ball) then begin

aBall := Ball(anObj);

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

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

aBall.setCenter(50, 100) else begin

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

end;

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

end;

end;

procedure Ball.update; var

gptr : GraphicalObject; dx, dy : integer;

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));

converted to PDF by BoJIoc

offsetRect(region, dx, dy); (* перерисовать шар *)

for i := 1 to 25 do draw;

(* проверить, не стукнули ли мы чего-нибудь *) gptr := listOfHoles;

while (gptr <> nil) do begin

if gptr <> self then begin

if self.intersect(gptr) then begin

gptr.hitBy(self);

end;

end;

gptr :=gptr.link; end;

end;

end;

procedure Ball.hitBy(anObj : GraphicalObject); var

aBall : Ball; da : real;

begin

if Member(anObj, Ball) then begin

aBall := Ball(anObj);

(* уменьшить энергию ударяющегося шара вдвое *) 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;

end;

procedure Ball.draw; begin

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

end;

procedure CueBall.draw; begin

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

end;

procedure mouseButtonDown(x, y : integer); var

gptr : GraphicalObject; begin

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

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

cueBall.setDirection( hitAngle(cueBall.x — x, cueBall.y — y));

converted to PDF by BoJIoc

(* цикл до тех пор, пока что-либо движется *) ballMoved := true;

while ballMoved do begin

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

gptr.update;

gptr := gptr.link; end;

end;

end;

procedure CreateGlobals; var

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

begin

saveRack := 0; listOfObjects := nil;

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

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

new (newWall);

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

new (newWall);

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

listOfObjects := newWall; new (newWall);

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

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

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

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

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

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

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

converted to PDF by BoJIoc

new (cueBall); cueBall.initialize(50, 96); cueBall.link := listOfObjects; listOfObjects := cueBall;

for i := 1 to 5 do begin

for j := 1 to i do begin

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

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

end;

end;

end;

procedure drawBoard; var

gptr : GraphicalObject; begin

SetPort(theWindow); gptr := listOfObjects; while (gptr <> nil) do begin

gptr.draw;

gptr := gptr.link; end;

end;

Приложение С

Исходный код программ для карточного пасьянса

Программа карточного пасьянса из главы 8 написана на языке Java со стандартной библиотекой API.

В.1. HTML-файл для апплета

<html>

<title>Solitare Game</title>

<applet code="Solitare.class" width=400 height=500> </applet>

</html>

В.2. Файл Solitare.java

/*

Карточный пасьянс на языке Java

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

*/

import java.awt.*; import java.applet.*;

converted to PDF by BoJIoc

class Card

{

// конструктор

Card (int sv, int rv)

{

s = sv; r = rv;

faceup = false;

} // доступ к атрибутам карты public int rank ()

{

return r;

}

public int suit()

{

return s;

}

public boolean faceUp()

{

return faceup;

}

public void flip()

{

faceup = ! faceup;

}

public int color()

{

if (suit() == heart || suit() == diamond) return red;

return black;

}

public void draw (Graphics g, int x, int y)

{

String names[] = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"};

//очистить прямоугольник, нарисовать границу g.clearRect(x, y, width, height); g.setColor(Color.black);

g.drawRect(x, y, width, height);

//нарисовать карту

if (faceUp())

{

if (color() == red) g.setColor(Color.red);

else g.setColor(Color.blue);

g.drawString(names[rank()], x+3, y+15); if (suit() == heart)

{

g.drawLine(x+25, y+30, x+35, y+20); g.drawLine(x+35, y+20, x+45, y+30); g.drawLine(x+45, y+30, x+25, y+60); g.drawLine(x+25, y+60, x+5, y+30); g.drawLine(x+5, y+30, x+15, y+20); g.drawLine(x+15, y+20, x+25, y+30);

}

else if (suit() == spade)

converted to PDF by BoJIoc

{

g.drawLine(x+25, y+20, x+40, y+50); g.drawLine(x+40, y+50, x+10, y+50); g.drawLine(x+10, y+50, x+25, y+20); g.drawLine(x+23, y+45, x+20, y+60); g.drawLine(x+20, y+60, x+30, y+60); g.drawLine(x+30, y+60, x+27, y+45);

}

else if (suit() == diamond)

{

g.drawLine(x+25, y+20, x+40, y+40); g.drawLine(x+40, y+40, x+25, y+60); g.drawLine(x+25, y+60, x+10, y+40); g.drawLine(x+10, y+40, x+25, y+20);

}

else if (suit() == club)

{

g.drawOval(x+20, y+25, 10, 10); g.drawOval(x+25, y+35, 10, 10); g.drawOval(x+15, y+35, 10, 10); g.drawLine(x+23, y+45, x+20, y+55); g.drawLine(x+20, y+55, x+30, y+55); g.drawLine(x+30, y+55, x+27, y+45);

}

}

else // картинка вниз

{

g.setColor(Color.yellow); g.drawLine(x+15, y+5, x+15, y+65); g.drawLine(x+35, y+5, x+35, y+65); g.drawLine(x+5, y+20, x+45, y+20); g.drawLine(x+5, y+35, x+45, y+35); g.drawLine(x+5, y+50, x+45, y+50);

}

}

// поля данных

для цветов и мастей

final static int

width

= 50;

final static int

height = 70;

final static int

red

= 0;

final static int

black

= 1;

final static int

heart

= 0;

final static int

spade

= 1;

final static int

diamond = 2;

final static int

club

= 3;

// поля данных private boolean faceup; private int r;

private int s; public Card link;

}

class CardPile

{

CardPile (int x1, int y1)

{

x = x1; y = y1;

firstCard = null;

converted to PDF by BoJIoc

}

// функции доступа к картам не переопределяются public Card top()

{

return firstCard;

}

public boolean empty()

{

return firstCard == null;

}

public Card pop()

{

Card result = null; if (firstCard != null)

{

result = firstCard; firstCard = firstCard.link;

}

return result;

}

// следующие методы иногда переопределяются public boolean includes (int tx, int ty)

{

return x <= tx && tx <= x + Card.width && y <= ty && ty <= y + Card.height;

}

public void select (int tx, int ty)

{

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

}

public void addCard (Card aCard)

{

aCard.link = firstCard; firstCard = aCard;

}

public void display (Graphics g)

{

g.setColor(Color.black); if (firstCard == null)

g.drawRect(x, y, Card.width, Card.height); else

firstCard.draw(g, x, y);

}

public boolean canTake (Card aCard)

{

return false;

}

// координаты стопки protected int x; protected int y; private Card firstCard;

}

class DeckPile extends CardPile

{

DeckPile (int x, int y)

{

// вначале инициализировать как родителя

converted to PDF by BoJIoc

super(x, y);

//затем создать новую колоду карт

//сначала положим карты в локальную стопку

CardPile pileOne = new CardPile(0, 0); CardPile pileTwo = new CardPile(0, 0); int count = 0;

for (int i = 0; i < 4; i++) for (int j = 0; j <= 12; j++)

{

pileOne.addCard(new Card(i, j)); count++;

}

//затем вытаскиваем карты произвольным образом for (; count > 0; count--)

{

int limit = ((int)(Math.random() * 1000)) % count;

//передвинуть карту вниз на случайное место

for (int i = 0; i < limit; i++) pileTwo.addCard(pileOne.pop());

// затем добавить карту, найденную здесь addCard(pileOne.pop());

// теперь положить обратно while (! pileTwo.empty())

pileOne.addCard(pileTwo.pop());

}

}

public void select (int tx, int ty)

{

if (empty()) return; Solitare.discardPile.addCard(pop());

}

}

class DiscardPile extends CardPile

{

DiscardPile (int x, int y)

{

super (x, y);

}

public void addCard (Card aCard)

{

if (! aCard.faceUp()) aCard.flip(); super.addCard(aCard);

}

public void select (int tx, int ty)

{

if (empty()) return;

Card topCard = pop();

for (int i = 0; i < 4; i++)

if (Solitare.suitPile[i].canTake(topCard))

{

Solitare.suitPile[i].addCard(topCard);

return;

}

for (int i = 0; i < 7; i++)

if (Solitare.tableau[i].canTake(topCard))

{

converted to PDF by BoJIoc

Solitare.tableau[i].addCard(topCard);

return;

}

//эту карту некуда перекладывать

//положить ее обратно addCard(topCard);

}

}

class SuitPile extends CardPile

{

SuitPile (int x, int y)

{

super (x, y);

}

public boolean canTake (Card aCard)

{

if (empty())

return aCard.rank() == 0; Card topCard = top();

return (aCard.suit() == topCard.suit()) && (aCard.rank() == 1 + topCard.rank());

}

}

class TablePile extends CardPile

{

TablePile (int x, int y, int c)

{

super(x, y);

//инициализировать как родительский класс

//затем инициализировать нашу стопку for (int i = 0; i < c; i++)

{

addCard(Solitare.deckPile.pop());

}

//открыть самую верхнюю карту top().flip();

}

public boolean canTake (Card aCard)

{

if (empty())

return aCard.rank() == 12; Card topCard = top();

return (aCard.color() != topCard.color()) && (aCard.rank() == topCard.rank() — 1);

}

public boolean includes (int tx, int ty)

{

// не проверять нижнюю карту

return x <= tx && tx <= x + Card.width && y <= ty;

}

public void select (int tx, int ty)

{

if (empty()) return;

//если карта закрыта, перевернем

Card topCard = top();

converted to PDF by BoJIoc

if (! topCard.faceUp())

{

topCard.flip();

return;

}

//иначе посмотреть, можно ли переместить

//в основание

topCard = pop();

for (int i = 0; i < 4; i++)

if (Solitare.suitPile[i].canTake(topCard))

{

Solitare.suitPile[i].addCard(topCard);

return;

}

//иначе посмотреть, можно ли переместить

//в другую стопку расклада

for (int i = 0; i < 7; i++)

if (Solitare.tableau[i].canTake(topCard))

{

Solitare.tableau[i].addCard(topCard);

return;

}

// иначе положить обратно addCard(topCard);

}

private int stackDisplay(Graphics g, Card aCard)

{

int localy;

if (aCard == null) return y;

localy = stackDisplay(g, aCard.link); aCard.draw(g, x, localy);

return localy + 35;

}

public void display (Graphics g)

{

stackDisplay(g, top());

}

}

public class Solitare extends Applet

{

static DeckPile deckPile; static DiscardPile discardPile; static TablePile tableau[]; static SuitPile suitPile[]; static CardPile allPiles[]; public void init()

{

//вначале разместить массивы allPiles = new CardPile[13]; suitPile = new SuitPile[4]; tableau = new TablePile[7];

//затем заполнить их

allPiles[0] = deckPile = new DeckPile(335, 5); allPiles[1] = discardPile = new DiscardPile(268, 5);

for (int i = 0; i < 4; i++) allPiles[2+i] = suitPile[i] =