Партнерка на США и Канаду по недвижимости, выплаты в крипто

  • 30% recurring commission
  • Выплаты в USDT
  • Вывод каждую неделю
  • Комиссия до 5 лет за каждого referral

unit Mouse;

{Примеры использования –

см. mousetst. pas в графике,

mousetxt. pas в текстовом режиме 80*25}

interface

var MousePresent:boolean;

function MouseInit(var nb:integer):boolean;

{ Инициализация мыши - вызывать первой.

Вернет true, если мышь обнаружена }

procedure Mouseshow; {Показать курсор мыши}

procedure MouseHide; {Скрыть курсор мыши}

procedure Mouseread(var x, y,bMask:integer);

{Прочитать позицию мыши.

Вернет через x, y координаты курсора

(для текстового режима см. пример),

через bmask - состояние кнопок

(0-отпущены,1-нажата левая,2-нажата правая,

3-нажаты обе) }

procedure MousesetPos(x, y:word);

{Поставить курсор в указанную позицию}

procedure Mouseminxmaxx(minx, maxx:integer);

{Установить границы перемещения по x}

procedure Mouseminymaxy(miny, maxy:integer);

{Установить границы перемещения по y}

procedure setVideoPage(Page:integer);

{Установить нужную видеостраницу}

procedure GetVideoPage(var Page:integer);

{Получить номер видеостраницы}

function MouseGetb(bMask:word; var count,

Lastx, Lasty:word):word;

procedure MousekeyPreset

(var key, sost, x,y:integer);

implementation

uses Dos;

var r: registers;

Mi:pointer;

function MouseInit(var nb:integer):boolean;

begin

if MousePresent then begin

r. Ax:=0; Intr($33,r);

if r. Ax=0 then begin

nb:=0; MouseInit:=false

end

else begin

nb:=r. Ax; MouseInit:=true

end

end

else begin

nb:=0; MouseInit:=false

end

end;

procedure Mouseshow;

begin

r. Ax:=1; Intr($33,r)

end;

procedure MouseHide;

НЕ нашли? Не то? Что вы ищете?

begin

r. Ax:=2; Intr($33,r)

end;

procedure Mouseread(var x, y,bMask:integer);

begin

r. Ax:=3; Intr($33,r);

x:=r. cx; y:=r. dx; bMask:=r. Bx

end;

procedure MousesetPos(x, y:word);

begin

r. Ax:=4; r. cx:=x; r. dx:=y;

Intr($33,r)

end;

function MouseGetb(bMask:word;

var count, Lastx, Lasty:word):word;

begin

r. Ax:=5; r. Bx:=bMask;Intr($33,r);

count:=r. Bx; Lastx:=r. cx;

Lasty:=r. dx; MouseGetb:=r. Ax

end;

procedure Mouseminxmaxx(minx, maxx:integer);

begin

r. Ax:=7; r. cx:=minx;

r. dx:=maxx; Intr($33,r)

end;

procedure Mouseminymaxy(miny, maxy:integer);

begin

r. Ax:=8; r. cx:=miny;

r. dx:=maxy; Intr($33,r)

end;

procedure setVideoPage(Page:integer);

begin

r. Ax:=$1D; r. Bx:=Page; Intr($33,r)

end;

procedure GetVideoPage(var Page:integer);

begin

r. Ax:=$1E; Intr($33,r); Page:=r. Bx;

end;

procedure MousekeyPreset

(var key, sost, x,y:integer);

begin

r. Ax:=$6; r. Bx:=key; Intr($33,r);

key:=r. Ax; sost:=r. Bx;

x:=r. cx; y:=r. dx;

end;

begin

GetIntVec($33,Mi);

if Mi=nil then

MousePresent:=false

else if byte(Mi^)=$cE then

MousePresent:=false

else MousePresent:=true

end.

11.2. Тест модуля mouse. pas в графическом режиме (mousetst. pas).

program MouseTst;

uses graph, Mouse, crt;

var grDriver : integer; grMode : integer;

Errcode : integer;

procedure init;

begin

grDriver:=VGA;grMode:=VGAHi;

initgraph(grDriver, grMode, '');

Errcode:=graphresult;

if Errcode <> grOk then begin

writeln('Ошибка инициализации графики:',

grapherrormsg(Errcode)); halt;

end;

end;

var n, x,y, x0,y0,b:integer; s1,s2:string;

begin

init;

mouseinit(n);

mouseshow;

setfillstyle (solidfill, BLACK);

setcolor (WHITE);

settextJustify(centertext, centertext);

x0:=-1; y0:=-1;

repeat

mouseread (x, y,b);

if (x<>x0) or (y<>y0) then begin

str (x, s1); str (y, s2);

bar (getmaxx div 2-50,

getmaxy-15,getmaxx div 2+50,getmaxy-5);

outtextxy (getmaxx div 2,

getmaxy-10,s1+' '+s2);

x0:=x; y0:=y;

end;

until keypressed;

mousehide;

closegraph;

end.

11.3. Тест модуля mouse. pas в текстовом режиме (mousetxt. pas).

program MouseTxt;

uses crt, mouse;

var n, x,y, b:integer;

n1,k, lastx, lasty:word;

begin

textmode(3);

mouseinit (n);

mouseshow;

repeat

mouseread (x, y,b);

gotoxy (1,25);

write ('x=',(x div 8 + 1):2,

' y=',(y div 8 + 1):2,' b=',b:2);

until keypressed;

mousehide;

end.

12.1. Учебная игра, использующая собственный файл ресурсов. Первый листинг содержит утилиту для создания файла ресурсов resfile из файлов *.bmp текущей директории, список которых находится в файле filelist. txt. Файлы *.bmp должны быть сохранены в режиме 16 цветов. При необходимости следует изменить в программе константу пути к Паскалю.

uses graph, crt;

const VGAPath='c:\TP7\egavga. bgi';

FileList='filelist. txt';

resfile='attack. res';

const width=32; height=20;

const color: array [0..15] of byte=

(0,4,2,6,1,5,3,7,8,12,10,14,9,13,11,15);

const maxx=639; maxy=479;

cx=MAxx div 2; cy=maxy div 2;

type bmpinfo=record

h1,h2:char;

size, reserved, offset, b,width,

height: longint;

plans, bpp:word;

end;

var Driver, Mode: integer;

DriverF: file; List, res:text;

DriverP: pointer; s:string;

procedure Wait;

var ch:char;

begin

reset (Input); repeat until keyPressed;

ch:=readkey; if ch=#0 then readkey;

end;

procedure closeMe;

begin

if DriverP <> nil then begin

FreeMem(DriverP, Filesize(DriverF));

close (DriverF);

end;

closegraph;

end;

procedure graphError;

begin

closeMe;

writeln('graphics error:',

grapherrormsg(graphresult));

writeln('Press any key to halt ');

Wait;

halt (graphresult);

end;

procedure InitMe;

begin

assign(DriverF, VGAPath);

reset(DriverF, 1);

getmem(DriverP, Filesize(DriverF));

Blockread(DriverF, DriverP^,

Filesize(DriverF));

if registerBGIdriver(DriverP)<0 then

graphError;

Driver:=VGA; Mode:=VGAHi;

initgraph(Driver, Mode,'');

if graphresult < 0 then graphError;

end;

procedure clearscreen;

begin

setfillstyle (solidfill, White);

bar (0,0,maxx, maxy);

end;

procedure Window

(x1,y1,x2,y2,color, Fillcolor:integer);

begin

setcolor (color);

setfillstyle (1,Fillcolor);

bar (x1,y1,x2,y2);

rectangle (x1+2,y1+2,x2-2,y2-2);

rectangle (x1+4,y1+4,x2-4,y2-4);

setfillstyle (1,DArKGrAy);

bar (x1+8,y2+1,x2+8,y2+8);

bar (x2+1,y1+8,x2+8,y2);

end;

procedure Error (code:integer; str:string);

begin

Window (cx-140,cy-100,cx+140,

cy-70,Black, YELLOW);

case code of

1: s:='Файл '+str+' не найден!';

2: s:='Файл '+str+' не формата BMP-16';

3: s:='Файл '+str+' испорчен!';

end;

settextjustify (Lefttext, toptext);

settextstyle(DefaultFont, HorizDir, 1);

outtextxy (cx-136,cy-92,s);

Wait;

halt(code);

end;

function Draw (x0,y0:integer; fname:string;

transparent:boolean):integer;

var f:file of bmpinfo;

bmpf:file of byte;

res:integer; info:bmpinfo;

x, y:integer; b, bh, bl:byte;

nb, np:integer; tpcolor:byte;

i, j:integer;

begin

assign(f, fname);

{$I-} reset (f); {$I+}

res:=IoResult;

if res <> 0 then Error (1,fname);

read (f, info);

close (f);

if info. bpp<>4 then Error(2,fname);

x:=x0;

y:=y0+info. height;

nb:=(info. width div 8)*4;

if (info. width mod 8) <> 0 then nb:=nb+4;

assign (bmpf, fname);

reset (bmpf);

seek (bmpf, info. offset);

if transparent then begin

read (bmpf, b);

tpcolor:=b shr 4;

seek (bmpf, info. offset);

end

else tpcolor:=17;

for i:=1 to info. height do begin

np:=0;

for j:=1 to nb do begin

read (bmpf, b);

if np<info. width then begin

bh:=b shr 4;

if bh <> tpcolor then

putpixel (x, y,color[bh]);

inc (x);

inc(np);

end;

if np<info. width then begin

bl:=b and 15;

if bl <> tpcolor then

putpixel (x, y,color[bl]);

inc(x);

inc(np);

end;

end;

x:=x0;

dec(y);

end;

close (bmpf);

Draw:=info. height;

end;

var i, j:word;

b:char;

r:integer;

begin

InitMe;

clearscreen;

assign (List, FileList);

{$I-}

reset (List);

{$I+}

if IoResult <> 0 then Error (1,FileList);

assign (res, resfile);

{$I-}

rewrite (res);

{$I+}

if IoResult <> 0 then Error (1,resfile);

settextjustify (centertext, toptext);

while not eof(List) do begin

readLn (List, s);

clearscreen;

Draw (0,0,s, true);

for j:=1 to height do

for i:=1 to width do begin

b:=chr(getpixel (i, j));

write (res, b);

end;

setcolor (BLACK);

outtextxy (cx, maxy-20,'Файл '+s+' ОК');

Wait;

end;

closeMe;

close (res);

close (List);

end.

12.2. Листинг содержит исходный текст игры в стиле Invaders. Компилировать в Паскаль 7. При необходимости изменить константу пути к Паскалю. Требует файла ресурсов, созданного утилитой из листинга 12.1. Требует установленного графического шрифта trip. chr.

uses graph, crt, Dos;

const width=32; height=20;

type Picture=array [0..width-1,0..height-1]

of char;

type sprite=record

state, x,y, Pnum, PREDir: word;

end;

const VGAPath='c:\TP7\egavga. bgi';

FontPath='c:\TP7\Trip. chr';

sprName='attack. res';

const ESC=#27; F1=#59; SPACE=#32;

UP=#72; DOWN=#80; LEFT=#75; RIGHT=#77;

const maxx=639; maxy=479;

cx=maxx div 2; cy=maxy div 2;

maxsprites=11; maxPictures=11;

maxshoots=100;

const LeftDir=0; RightDir=1;

UpDir=2; DownDir=3;

Delta=2; shootradius=5;

var ch:char; s:string;

Hour, min, sec, sec1,secN, secN1,

sec100,secI, secI1:word;

var Driver, Mode, Font1,

currentsprites, currentBottom,

currentshoots, shootx, Lives,

Enemyshooter, Enemies,

shootsProbability: integer;

score, Level:longint;

DriverF, FontF: file;

DriverP, FontP: pointer;

spr: array [1..maxsprites] of sprite;

Pict: array [1..maxPictures] of Picture;

shoots: array [1..maxshoots] of sprite;

shooter, DieMe, InGame, Initshoot:boolean;

procedure Wait;

var ch:char;

begin

reset (Input); repeat until keyPressed;

ch:=readkey; if ch=#0 then readkey;

end;

procedure closeAll;

begin

if FontP <> nil then begin

FreeMem(FontP, Filesize(FontF));

close (FontF);

end;

if DriverP <> nil then begin

FreeMem(DriverP, Filesize(DriverF));

close (DriverF);

end;

closegraph;

end;

procedure graphError;

begin

closeAll;

writeln('graphics error:',

grapherrormsg(graphresult));

writeln('Press any key to halt');

Wait; halt (graphresult);

end;

procedure InitAll;

begin

assign(DriverF, VGAPath);

reset(DriverF, 1);

getmem(DriverP, Filesize(DriverF));

Blockread(DriverF, DriverP^,

Filesize(DriverF));

if registerBGIdriver(DriverP)<0 then

graphError;

Driver:=VGA; Mode:=VGAHi;

initgraph(Driver, Mode,'');

if graphresult < 0 then graphError;

assign(FontF, FontPath);

reset(FontF, 1);

getmem(FontP, Filesize(FontF));

Blockread(FontF, FontP^, Filesize(FontF));

Font1:=registerBGifont(FontP);

if Font1 < 0 then graphError;

end;

procedure clearscreen;

begin

setfillstyle (solidfill, White);

bar (0,0,maxx, maxy);

end;

procedure Window

(x1,y1,x2,y2,color, Fillcolor:integer);

begin

setcolor (color);

setfillstyle (1,Fillcolor);

bar (x1,y1,x2,y2);

rectangle (x1+2,y1+2,x2-2,y2-2);

rectangle (x1+4,y1+4,x2-4,y2-4);

setfillstyle (1,DArKGrAy);

bar (x1+8,y2+1,x2+8,y2+8);

bar (x2+1,y1+8,x2+8,y2);

end;

procedure outtextcxy (y:integer; s:string);

begin

settextjustify (centertext, centertext);

outtextxy (cx, y,s);

end;

procedure start;

begin

clearscreen;

Window (10,10,maxx-10,maxy-10,Blue, White);

settextstyle(Font1, HorizDir, 4);

outtextcxy (25,'Атака из космоса');

settextstyle(Font1, HorizDir, 1);

outtextcxy (maxy-25,

'Нажмите клавишу для начала');

Wait;

end;

procedure restorescreen

(sNum, Dir, Delta:word);

var x, y:word;

begin

x:=spr[sNum].x; y:=spr[sNum].y;

setfillstyle (solidfill, White);

case Dir of

LeftDir: begin

bar(x+width-Delta, y,x+width-1,

y+height-1);

end;

RightDir: begin

bar (x, y,x+Delta, y+height-1);

end;

UpDir: begin

bar (x, y+height-Delta,

x+width-1,y+height-1);

end;

DownDir: begin

bar (x, y,x+width-1,y+Delta);

end;

end;

end;

procedure Drawsprite (sNum:word);

var i, j,x, y,n, b:integer;

begin

N:=spr[sNum].PNum;

x:=spr[sNum].x; y:=spr[sNum].y;

for j:=y to y+height-1 do

for i:=x to x+width-1 do begin

b:=ord(Pict[n, i-x, j-y]);

putpixel(i, j,b);

end;

end;

procedure GoLeft;

var x, d2:word;

begin

x:=spr[1].x; d2:=delta*4;

if x>d2 then begin

restorescreen (1,LeftDir, d2);

Dec(spr[1].x, d2); Drawsprite (1);

end;

end;

procedure GoRight;

var x, d2:word;

begin

x:=spr[1].x;

d2:=delta*4;

if x+width < maxx then begin

restorescreen (1,RightDir, d2);

Inc(spr[1].x, d2);

Drawsprite (1);

end;

end;

procedure showLives;

begin

str(Lives, s);

setfillstyle (solidfill, White);

setcolor (RED); bar (80,0,110,10);

outtextxy (82,2,s);

end;

procedure showscore;

begin

str(score, s);

setfillstyle (solidfill, White);

setcolor (Blue); bar (150,0,250,10);

outtextxy (152,2,s);

end;

procedure showshoots;

begin

str(currentshoots, s);

setfillstyle (solidfill, White);

setcolor (Black); bar (20,0,50,10);

outtextxy (20,2,s);

end;

procedure showLevel;

begin

str(Level, s);

setfillstyle (solidfill, White);

setcolor (Blue); bar (251,0,350,10);

outtextxy (253,2,'Level '+s);

end;

procedure shoot;

var i:integer;

begin

if currentshoots>0 then begin

for i:=1 to maxshoots do

if (sec<>sec1) and (shoots[i].state=0)

then begin

Dec(currentshoots);

showshoots;

spr[1].PNum:=6; Drawsprite (1);

GetTime(Hour, min, sec, sec100);

shootx:=spr[1].x; shooter:=true;

shoots[i].x:=spr[1].x+ (width div 2);

shoots[i].y:=spr[1].y - 5;

shoots[i].PNum:=UpDir;

shoots[i].state:=1;

break;

end;

end;

end;

procedure Help(s:string);

begin

setfillstyle (solidfill, White);

setcolor (Blue);

bar (10,maxy-10,maxx-10,maxy);

outtextxy (10,maxy-9,s);

end;

procedure Error (code:integer; str:string);

begin

Window (cx-120,cy-100,cx+120,cy-70,

Black, YELLOW);

case code of

1: s:='Файл '+str+' не найден!';

end;

settextjustify (Lefttext, toptext);

settextstyle(DefaultFont, HorizDir, 1);

outtextxy (cx-116,cy-92,s);

Wait; closeAll; halt(code);

end;

procedure DrawField;

var i, x,y:integer;

begin

clearscreen;

with spr[1] do begin

state:=1; Pnum:=1;

x:=maxx div 2;

y:=maxy - 10 - height;

Drawsprite (1);

end;

x:=100;

y:=10;

for i:=2 to currentsprites do begin

spr[i].state:=1;

spr[i].PNum:=7;

spr[i].x:=x; spr[i].y:=y;

Drawsprite (i);

inc(x,50);

if x>maxx-width then begin

x:=100;

if y<currentBottom-height then

Inc(y, height)

else y:=10;

end;

end;

for i:=1 to maxshoots do

shoots[i].state:=0;

shooter:=false;

Enemyshooter:=-1;

sec:=0; secN:=0;

secI1:=100; sec1:=100; secN1:=100;

setfillstyle (solidfill, RED);

FillEllipse (10,5,5,4);

showshoots;

setfillstyle (solidfill, Green);

bar (60,1,72,10);

setfillstyle (solidfill, LightGreen);

bar (62,3,70,8);

showLives;

setfillstyle (solidfill, YELLOW);

setcolor (Black);

for i:=1 to 3 do begin

circle (126+i*2,5,4);

FillEllipse (126+i*2,5,4,4);

end;

showscore;

showLevel;

InGame:=true;

end;

procedure Loadsprites;

var F:text;

n, i,j, r:integer;

b:char;

begin

assign (f, sprName);

{$I-}

reset (f);

{$I+}

if IoResult<>0 then Error (1,sprName);

for n:=1 to maxPictures do

for j:=0 to height-1 do

for i:=0 to width-1 do begin

read (f, b);

Pict [n, i,j]:=b;

end;

close (f);

end;

procedure Deltas (sNum, Dir:integer;

var dx, dy:integer);

var x, y:integer;

begin

x:=spr[sNum].x; y:=spr[sNum].y;

case Dir of

LeftDir: begin

Dec(x, Delta);

if x<0 then x:=0;

end;

RightDir: begin

Inc(x, Delta);

if x>maxx-width then x:=maxx-width;

end;

UpDir: begin

Dec (y, Delta);

if y<10 then y:=10;

end;

DownDir: begin

Inc(y, Delta);

if y>currentBottom then

y:=currentBottom;

end;

end;

dx:=x; dy:=y;

end;

function Between (a, x,b:integer):boolean;

begin

if (x>a) and (x<b) then Between:=true

else Between:=false;

end;

procedure shootMovies;

var i, d,n:integer;

x, y:word;

found:boolean;

begin

for i:=1 to maxshoots do

if shoots[i].state=1 then begin

x:=shoots[i].x; y:=shoots[i].y;

d:=shoots[i].PNum;

setfillstyle (solidfill, White);

setcolor (White);

fillellipse(x, y,shootradius, shootradius);

if d=updir then begin

setfillstyle (solidfill, RED);

if y<15 then begin

shoots[i].state:=0; continue;

end;

found:=false;

for n:=2 to currentsprites do begin

if spr[n].state=1 then begin

if (Between(spr[n].x, x,

spr[n].x+width)) and

(Between(spr[n].y, y,

spr[n].y+height)) then begin

shoots[i].state:=0;

found:=true;

spr[n].state:=2;

Inc(spr[n].PNum);

Inc(score,10+5*n);

showscore;

break;

end;

end;

end;

if not found then Dec(y, Delta);

end

else begin

setfillstyle (solidfill, Blue);

if y>maxy-10-(height div 2) then begin

shoots[i].state:=0;

continue;

end;

found:=false;

if Between(spr[1].x, x,spr[1].x+width)

and

Between(spr[1].y, y,spr[1].y+height)

then begin

shoots[i].state:=0; found:=true;

Inc(spr[1].Pnum); DieMe:=true;

Help ('you are missed one life :-(');

Drawsprite (1);

end;

if not found then Inc(y, Delta);

end;

if not found then begin

fillellipse(x, y,shootradius, shootradius);

shoots[i].x:=x; shoots[i].y:=y;

end;

end;

end;

procedure Enemiesstep;

var i, k,Dir, dx, dy, n:integer;

begin

Enemies:=0;

for i:=2 to currentsprites do begin

if spr[i].state=1 then begin

Inc(Enemies);

for k:=1 to 3 do begin

dir:=random(4);

if dir=spr[i].pREDir then break;

end;

spr[i].pREDir:=dir;

Deltas (i, dir, dx, dy);

restorescreen (i, Dir, Delta);

spr[i].x:=dx; spr[i].y:=dy;

Drawsprite (i);

Initshoot:=false;

GetTime(Hour, min, secN1,sec100);

if (secN1<>secN) and

(1+random(100)<shootsProbability) then

Initshoot:=true;

if Initshoot then begin

secN:=secN1;

for n:=1 to maxshoots do

if (shoots[n].state=0) and

(Enemyshooter<>i) then begin

Enemyshooter:=i;

shoots[n].x:=dx+ (width div 2);

shoots[n].y:=dy +height +5;

shoots[n].PNum:=DownDir;

shoots[n].state:=1;

break;

end;

end;

end

else if spr[i].state=2 then begin

GetTime (Hour, min, secI, sec100);

Drawsprite (i);

if secI<>secI1 then begin

secI1:=secI;

if (spr[i].PNum<11) then

Inc(spr[i].PNum)

else begin

spr[i].state:=0;

setfillstyle (solidfill, White);

bar (spr[i].x, spr[i].y,

spr[i].x+width-1,spr[i].y+height-1);

end;

end;

end;

end;

end;

procedure Timefunctions;

var i:integer;

begin

if not InGame then Exit;

GetTime(Hour, min, sec1,sec100);

if (shooter) and (sec<>sec1) then begin

spr[1].PNum:=1;

if shootx=spr[1].x then Drawsprite (1);

shooter:=false;

end;

if (DieMe) and (sec<>sec1) then begin

if spr[1].Pnum<5 then begin

sec:=sec1; Inc(spr[1].PNum);

Drawsprite (1); DieMe:=true;

end

else begin

DieMe:=false;

if Lives>0 then begin

Dec(Lives); showLives;

spr[1].PNum:=1;

Drawsprite (1);

end

else InGame:=false;

end;

end;

end;

function getlongintTime:longint;

{Вернет системное время как longint}

var Hour, minute, second, sec100: word;

var k, r:longint;

begin

GetTime (Hour, minute, second, sec100);

k:=Hour; r:=k*360000;

k:=minute; Inc (r, k*6000);

k:=second; Inc(r, k*100);

Inc(r, sec100); getlongintTime:=r;

end;

procedure Delay (ms word);

var endTime, curTime : longint;

cor:boolean;

begin

cor:=false;

endTime:=getlongintTime + ms div 10;

if endTime>8639994 then cor:=true;

repeat

curTime:=getlongintTime;

if cor=true then begin

if curTime<360000 then

Inc (curTime,8639994);

end;

until curTime>endTime;

end;

label 10,20;

begin

randomize; InitAll; InGame:=false;

start;

settextstyle (DefaultFont, HorizDir,1);

settextjustify (Lefttext, toptext);

Loadsprites;

currentBottom:=200; currentshoots:=50;

Lives:=3; score:=0; Level:=1;

shootsProbability:=5;

currentsprites:=5;

10:

DrawField;

if Level>1 then begin

str(Level-1,s);

Help ('cool, you''re complete level '+s);

end

else Help

('Let''s go! Kill them, invaders!');

repeat

if InGame then repeat

Enemiesstep;

if Enemies=0 then begin

Inc(score,100+Level*10);

if shootsProbability<100 then

Inc (shootsProbability);

if currentsprites<maxsprites then

Inc(currentsprites);

if currentBottom<maxy-10-4*height then

Inc(currentBottom,10);

currentshoots:=50;

Delay(1000);{Пауза перед след. уровнем}

Inc(Level);

goto 10;

end;

shootMovies;

if not InGame then begin

Help ('sorry, you''re dead');

end;

Timefunctions;

until keypressed;

ch:=readkey;

case ch of

SPACE:

if not DieMe and InGame then shoot;

#0: begin

ch:=readkey;

case ch of

F1: Help

('Sorry, there''s no help here :-)');

LEFT: if not DieMe and InGame

then GoLeft;

RIGHT: if not DieMe and InGame

then GoRight;

UP: if not DieMe and InGame

then shoot;

end;

end;

end;

until ch=ESC;

closeAll;

end.

 

Приложение 5. Расширенные коды клавиатуры

Нажатие клавиши преобразуется в двухбайтовый код, называемый скан-ASCII-кодом. Этот код помещается в буфер клавиатуры, откуда ваша программа может считать его с помощью прерывания системы BIOS. Старший байт двухбайтового кода называется скан-кодом и является отображением фактически нажатой клавиши. Скан-код не отражает состояние клавиш Shift, Ctrl или Alt и не является уникальным. Помимо скан-кодов нажатия, существуют коды отпускания клавиш, отличающиеся на шестнадцатеричное значение 80 в сторону увеличения. Младший байт полного кода, называемый ASCII-кодом, также не является уникальным, но полная комбинация скан и ASCII-кода уникальна. Некоторые клавиши не имеют ASCII-кода и вместо него возвращается ноль. Такие двухбайтовые коды называются расширенными. При приеме кода нажатой клавиши через DOS последняя отделяет от общего значения скан-код. Кроме того, работающий в системе русификатор может дополнительно транслировать скан-коды буквенных клавиш в ASCII-коды русских букв.

Исходя из сказанного, при использовании стандартной функции readkey, работающей с ASCII-кодами клавиш, в общем случае является правильной следующая схема обработки на Паскале:

ch := readkey; {Чтение символа в байт ch}

if ch = #0 then begin

{Если нет ASCII-кода, прочитать

дополнительно расширенный код}

ch := readkey;

{Обработка расширенного кода}

end

else

{Обработка ASCII-кода}

На Паскале десятичный код может быть записан в виде #N, где N -- число, например, #65 ('A' латинская). ASCII-коды основных печатных символов можно узнать из Приложения 1, остальные нужные коды приводятся в табл. П5, П6.

Таблица П5. ASCII-коды некоторых клавиш

Enter

13

Пробел

32

Esc

27

BackSpace

8

Tab

9

Таблица П6. Расширенные коды некоторых клавиш

Клавиша

Код

Код с Shift

Код с Ctrl

Код с Alt

F1

59

84

94

104

F2

60

85

95

105

F3

61

86

96

106

F4

62

87

97

107

F5

63

88

98

108

F6

64

89

99

109

F7

65

90

100

110

F8

66

91

101

111

F9

67

92

102

112

F10

68

93

103

113

Стрелка вверх

72

Стрелка вниз

80

Стрелка влево

75

Стрелка вправо

77

Insert

82

Delete

83

Home

71

119

End

79

117

Page Up

73

132

Page Down

81

118


Приложение 6. Правила хорошего кода

Написание красивого и эффективного программного кода -- целое искусство, во многом, увы, подзабытое в связи со взрывным ростом мощности вычислительных устройств, вызвавшим снижение требований к качеству алгоритмов. Это небольшое приложение не может заменить изучения специализированных дисциплин вроде "Технологии программирования" или "Теории алгоритмов и формальных языков", но следование изложенным здесь принципам позволит начинающему программисту привыкать не просто "решать задачи", а делать это возможно более красивым и экономичным с точки зрения вычислительных затрат способом.

1. Структурируйте и выравнивайте код, по крайней мере, так, как сказано в гл. 5. Во всем пособии я тоже форматировал листинги в привычном для себя стиле. Лучше привыкнуть структурировать текст, сдвигая любые вложения и разветвления кода одним-двумя пробелами вправо. Программа при этом не "разъедется" далеко вправо на сложных блоках, а вид текста, открытого в любом редакторе, не будет зависеть от размера отступа табуляции.

2. Давайте переменным осмысленные имена. Переменная с именем Length, или, в крайнем случае, Dlina, сама напомнит о своем назначении, в отличие от L. С другой стороны, не возбраняется использовать стандартные сокращения -- например, S для площади, P для периметра, a, b и c -- для сторон треугольника. Любые индексы естественно выглядят с именами i, j, k и т. д. Но если индекс обозначает номер месяца в году, куда естественней назвать его month, чем i. Хотя Паскаль и не различает регистр букв в именах переменных и служебных словах -- соблюдайте его везде. Большинство профессиональных языков регистр символов различают.

3. Существует множество соглашений об именах переменных -- можно спорить об их достоинствах и недостатках, но бесспорно одно -- соблюдение единообразного стиля именования намного облегчает понимание и модификацию программы. В сложных проектах осмысленных имен переменных может оказаться недостаточно, тогда на помощь придут префиксы. Так, если все имена всех переменных, относящихся к таблице "Студенты", начинаются на st_, а все динамические указатели имеют в имени префикс ptr_ (от англ. "pointer" -- указатель), читать такую программу будет намного проще.

4. Создавая любую переменную, обратите внимание на следующие моменты:

·  какой тип значений может принимать переменная, нельзя ли заменить ее перечислением, множеством или иным "сокращенным" типом данных?

·  есть ли ограничения на допустимые значения, если да, где и как они будут учтены?

·  что произойдет при переполнении значения или попытке дать переменной недопустимое значение?

5. Закрывайте блоки сразу. Такой блок, как

if условие then begin

end

else begin

end;

или

while условие do begin

end;

пишется сразу, а только потом ветвь алгоритма или тело цикла наполняются содержимым. Это поможет не запутаться в сложном коде и облегчит соблюдение следующего принципа.

6. Не оставляйте неработающее приложение "на завтра". Блочно-модульная структура программы позволяет всегда избежать этого. Подпрограмма может быть пустой "заглушкой", вы можете использовать ничего не делающие условия, пустые блоки, комментарии, но текущий код должен компилироваться, если завтра вы не хотите половину рабочего дня затратить на восстановление в памяти недоделанного сегодня.

7. Доводите программу до отсутствия предупреждений компилятора, а не только ошибок. Неизвестно, как скажутся на самом деле эти "невинные" напоминания. В языке Си конструкция вида if a:=0 допустима и вызовет лишь предупреждение "Possibly incorrect assignment" -- хотя в результате переменная a всегда будет получать значение 0 и ветвь алгоритма, привязанная к этому условию, будет всегда выполняться.

8. Выбирайте более короткие типы данных там, где это уместно: часто byte может заменить word или integer, а string[20] -- просто string.

9. Применяйте возможно более эффективный алгоритм решения -- прежде всего, оценка эффективности связана с зависимостью числа выполняемых операций от размерности данных. Двойной цикл полной обработки всех элементов матрицы прост в изучении, но далеко не всегда является лучшим решением при работе с реальной задачей -- ведь трудоемкость этого алгоритма равна n2, где n -- размерность матрицы.

10. Выбирайте менее трудоемкие операции. Так, n div k лучше, чем Trunc(n/k), а Inc(i); лучше, чем i:=i+1;. Во всех случаях порядковые операторы и операнды работают быстрее, чем вещественные. Поэтому обходитесь порядковыми данными везде, где это возможно. Особенно избегайте без необходимости деления на вещественные числа.

11. Не забывайте о погрешностях при работе с вещественными числами. Хрестоматийное while x<=2.5 doплохо, если x -- вещественный. С другой стороны, while abs(x-2.5)<eps выглядит громоздко и требует лишних вычислений. Лучше всего while x<=2.5+eps, оптимизирующий компилятор все равно преобразует 2.5+eps в константу.

12. Используйте стандартные функции языка, на котором пишете. Мнимая экономия ресурсов, достигнутая написанием собственных подпрограмм нижнего уровня, обернется трудноуловимыми ошибками в больших проектах. После пяти-десяти лет практики это становится ясно каждому программисту, хотя эксперименты с собственными интерфейсами и машинно-ориентированными программами бывают интересны и даже полезны на этапе обучения.

13. Следите за условиями. Если вы проверяете одно и то же условие неоднократно -- скорей всего, у вашей программы не в порядке с логикой. Пример из п. 7.7 показывает это наглядно.

14. Не забывайте о взаимоисключающих условиях. Составной условный оператор if ... else if или же case в таких случаях намного лучше набора коротких условных операторов.

15. Зачастую при написании длинных фрагментов кода удобнее обрабатывать ошибки в виде

if ошибка then завершение;

обработка;

чем по схеме

if верно then обработка

else завершение;

Вообще, избегайте else, находящихся строк через 100 после своего if -- это затрудняет восприятие даже хорошо структурированной программы.

16. Избегайте в циклах вычислений, не зависящих от их параметров! Выражение вроде sin(Pi/n), помещенное в цикл, где n не меняется, выглядит нелепо. Ведь каждое вычисление синуса (как и других стандартных функций) -- это трудоемкое разложение в ряд Фурье, выполняемое машиной.

17. Используйте математику там, где это уместно для сокращения трудоемкости кода и числа сравнений. Проверить, что переменные x и y имеют один знак, можно так:

if (x>0) and (y>0) or (x<0) and (y<0) then...,

а можно и в виде if (x*y>0) then....

18. Прекращайте циклы, когда результат уже достигнут. Приоритет средств при этом следующий:

·  использование циклов repeat-until или while-do вместо for;

·  операторы break или exit;

·  в последнюю очередь -- goto, и только в случаях, описанных в п. 16.2.

19. Временный "рабочий" массив того же порядка, что создаваемый или прочитанный из файла -- почти всегда не лучшее решение. Его использование говорит о том, что задача решается "в лоб" и не оптимальным способом. Допустимым считается использование одномерного рабочего массива при обработке матричных данных -- если размерность его не превышает большей из размерностей матрицы.

20. Именуйте размерные константы массивов. Никому не нужны несколько циклов с верхними границами-"близнецами". А что, если размерность обрабатываемых данных придется изменить?

21. Передавайте значения подпрограммам преимущественно по адресу, а не по значению. Для матричных и векторных данных старайтесь делать это всегда. Применение векторных данных имеет приоритет перед матричными.

22. Не делайте подпрограммы зависимыми от глобальных данных. Несоблюдение этого правила существенно уменьшит вероятность повторного использования кода вами или другим разработчиком.

23. Не пишите подпрограмм, возвращающих более одного объекта -- скаляра, вектора или матрицы. В крайнем случае, можно отдельным параметром передавать или возвращать размерность векторных данных. Избегайте подпрограмм, которые ничего не возвращают. Разработка сложных подпрограмм облегчается, если их "точка выхода" и возвращаемое значение указаны единственным и последним оператором. Для перехода из тела подпрограммы в точку возврата в этом случае не грешно использовать даже goto:

function Test (a, b:integer):integer;

label end_of_Test;

var error:integer;

begin

error:=0;

if (a<0) or (b<0) then begin

error:=1;

goto end_of_Test;

end;

. . .

end_of_Test:

Test:=error;

end;

24. Нужно приучить себя не только правильно называть переменные и функции, но и выделять все логические части задачи при проектировании иерархии подпрограмм. Например, если функция ищет в наборе данных элемент по какому-то признаку и создает новый в том случае, когда искомый элемент обнаружен, то лучше разделить ее на две -- функцию поиска и функцию создания нового узла, которая будет вызываться из первой. Достаточно придерживаться подобных незамысловатых приемов, чтобы повысить сопровождаемость приложения в разы. Если посмотреть на вопрос с другой стороны, не заставляйте одну подпрограмму выполнять несколько функций -- она окажется бесполезна с точки зрения повторного использования кода. Так, определение длины ломаной линии можно реализовать одной подпрограммой, но гораздо лучше, если задача разбита на подпрограммы вычисления длины и вычисления расстояния между двумя точками.

25. При работе с динамическими объектами пишите код так, чтобы открытые объекты всегда закрывались, как только они станут не нужны. В идеале порядок закрытия объектов должен быть обратным по отношению к порядку открытия (последний занявший память объект освобождает ее первым). Следует также избегать функций перераспределения ранее выделенной динамической памяти.

26. Проверить логику своей программы легче всего по принципу "Одна правка -- одно место в программе". Если при добавлении в меню нового пункта или, еще хуже, простом изменении размерности одномерного массива приходится переписывать несколько удаленных друг от друга фрагментов кода -- программа написана плохо.

27. Если написанная вами программа не работает или работает "криво", ошибка лежит на вашей совести, а компьютер с компилятором ни в чем не виноваты. "Отладка", при которой программист хаотически меняет то одно, то другое место в коде и на которую уходит до 90% времени написания, на самом деле -- свидетельство не слишком качественной работы. Хорошо написанной программе нужна не столько отладка, сколько тестирование на различных допустимых, недопустимых и "пограничных" наборах данных. Кстати, обдумывание и написание тестов до тестируемого кода способствует и улучшению, и большей устойчивости конечного продукта.

Резюмируя, можно сказать, что все большие программы на свете написаны только за счет одного -- правильного структурирования кода. И хороший программист -- не тот, кто "знает языки", а тот, кто умеет писать легко читаемый, понимаемый и модифицируемый код, максимально используя стандартные средства языка разработки.

Рекомендуемая литература

1.  Turbo Pascal 7.0 и Delphi. Учебное пособие. / . -- М.: Диасофт, 2001. – 208 с.

2.  Учимся программировать: Pascal 7.0. Задачи и методы их решения. / . М.: Диалог-МИФИ, 2005. – 256 с.

3.  Практикум программирования на Turbo Pascal. Задачи, алгоритмы и решения. / . СПб.: ДиаСофтЮП, ДМК Пресс, 2007. – 320 с.

4.  Практика программирования: Бейсик, Си, Паскаль. / , . СПб.: БХВ-Петербург, 2001. – 480 с.

5.  Pascal 7.0. Практическое программирование. Решение типовых задач. / . М.: КУДИЦ-образ, 2003. – 528 с.

6.  Turbo Pascal. / . М.: Диалектика, 2002. – 896 с.

7.  Программирование в Turbo Pascal 7.0 и Delphi. / . СПб.: БХВ-Петербург, 2007. – 400 с.

8.  Лукин Паскаль 7.0. Самоучитель для начинающих. / . М.: Диалог-МИФИ, 2002. – 400 с.

9.  Программирование в среде Turbo Pascal 7.0. Базовый курс. / , . М.: Век+, 2003. – 464 с.

10.  Turbo Pascal. Учитесь программировать./ М.: Вильямс, 2001. – 448 с.

11.  Изучаем Turbo Pascal. / , c. А. Немнюгин. СПб: Питер, 2007. – 320 с.

12.  Turbo Pascal. / . СПб.: Питер, 2006. – 268 с.

13.  Turbo Pascal 7. Начальный курс. / . М.: ОМД Групп, 2003. – 576 с.

14.  Turbo Pascal 7. Практика программирования. / . М.: ОМД Групп, 2003. – 415 с.

15.  Алгоритмы и программы на Turbo Pascal. Учебный курс. / . СПб: Питер, 2001. – 240 с.

16.  Система программирования Турбо Паскаль: учеб. пособие / , ; Новосиб. гос. архитектур.-строит. ун-т. – Новосибирск, 2006. – 136 с.

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11