PASCAL单元常见过程调用及小游戏编程方法设计

                      

 

写本文的目的是教大家如何使用PASCAL单元来设计更好的程序界面和人机控制,本文默认的是TURBO PASCAL,本文不涉及算法,谢谢。

 

 

在文本VGA模式下,屏幕的位置分成25行,每行80个字符。

 

1:光标定位过程:(CRT单元)

Procedure Gotoxy(X,Y:byte)  

把光标移到第X列,Y行的位置。 注意X,Y的顺序是先列后行,与我们常说的第几行第几列的习惯相反。

屏幕左上角第一个位置是gotoxy(1,1);

屏幕右下角最后一个位置是gotoxy(80,25);

当光标移动后,后面write(),writeln()代码都是从当前位置输出。

例:

Var

  I:integer;

begin

   For i:=1 to 25 do

     begin

   Gotoxy(1,i);

   Write(‘AAAAA’);

     End;

End.

上面的程序,就是把光标移到每行的第一个位置,然后输出’AAAAA’字符串。

 

2:得到当前光标位置:(CRT单元)

Function whereX: byte ;  得到当前光标位置的列;

Function whereY: byte ;  得到当前光标位置的行;

 

例:

  gotoxy(1,1);              //光标移到屏幕第1列第1行

  write('AAAAA');          //输出字符串

  write(wherex,' ',wherey);    //当前光标的位置,输出了6,1,代表是第6列第1行

 

  gotoxy(1,10);              //光标移到屏幕第1列第10行

  writeln('AAAAA');          //输出字符串

  write(wherex,' ',wherey);     //当前光标的位置,输出了1,11,代表是第1列第11行

 

明显可以看出,writeln输出后,屏幕的光标位置自动移到下一行的起点,这就是换行。


 

 

再看一个屏幕滚屏的特殊例子

  gotoxy(80,25);

  writeln('AAAAA');

  write(wherex,' ',wherey);


在第25行80列输出一个’AAAAA’的串,当前光标是多少?

屏幕最后一个位置,输出一个A后,屏幕没有位置了,怎么办?

屏幕会往上滚屏,也就是整个屏幕上移一行,多出一个空行。

所以第24行80列显示一个’A’

所以第25行会出现‘AAAA’

此时再来一个writeln换行,屏幕再滚一行。

此时的屏幕上显示,

所以第23行80列显示一个’A’

所以第24行1列会出现‘AAAA’

最后的光标移动仍然是停在第25行第1列。

 

综合上述,在文本模式下,在第25行80列输出一个字符后,会导致屏幕往上滚一行,这会引起设计好的程序界面出现上滚一行的现象。至于怎么解决,大家自己想。

 

 

3:改变文字背景颜色, 文字颜色:(CRT单元)

Procedure textbackground(colorbyte);  设置将要输出的文字背景颜色

Procedure textcolor(colorbyte) 设置将要输出的文字字体颜色

 

在crt单元中,已经设置了很多颜色常量,但是我们可以直接用0-15的数字,比打那些英文更方便。

 

Const

   Black =0;   黑色

   Blue  =1;  蓝色

   Green =2;   绿色

   Cyan =3;  青绿色

   Red  =4;  红色

   Magenta =5; 洋红色

   Brown =6;   褐色

   Lightgray =7;  深灰

   Darkgray =8;  浅灰

   Lightblue= 9   深蓝

   Lightgreen=10;  深绿

   Lightcyan =11;   深青绿

   Lightred=12;     深红

   Lightmagenta=13;  深洋红

   Yellow=14;      黄色

   White =15;       白色

 

先发个例题:

uses crt;

var

 i,j:integer;

 

procedure color(i,j:integer);

begin

  textbackground(i);     //设置背景色

  textcolor(j);           //设置文字颜色

end;

 

begin

  for i:=0 to 15 do          //背景色从0-15

    begin

     for j:=0 to 15 do       //文字色从0-15

       begin

         color(i,j);         //设置当前文字颜色

         write('ABCD');    // 输出’ABCD’

       end;

     writeln;

    end;

 

end.


 

 

//当输出的字符是空格串时,屏幕上显示的就是一个背景色的小方块。

begin

  color(0,7);

  clrscr;

 

  for i:=0 to 15 do

    begin

      for j:=0 to 15 do

        begin

          color(j,15);  //改变背景色

          write('    ');  //输出空格串

        end;

      writeln;

    end;

end.


仔细看上面的背景色,从0-7,从8-15其实是一样的。

 

 

4:清除屏幕,清除行尾文字:(CRT单元)

Procedure clrscr;  清除整个屏幕,清除后,整个屏幕的颜色,就是文字的背景色

Procedure clreol 清除光标当前行的位置,到行的末尾,也就是第80列为止。

 

例:

uses crt;

var

 i,j,k:integer;

 ch:char;

 

procedure color(i,j:integer);

begin

  textbackground(i);

  textcolor(j);

end;

 

begin

  for i:=0 to 15 do

    begin

      color(i,i);    //设置颜色

      clrscr;       //清屏

      ch:=readkey;  //按任意键

end;

 

 

end.

 

 

在Free Pascal中,用clrscr()或clrscr;都可以。

在Turbo Pascal中,用的是clrscr; 加上括号语法出错。

 

 

5:读入一个键盘按键:(CRT单元)

Function readkey: char ;  读一个字符的键盘输入

 

说明:用readkey读键盘,输入的字符并不在屏幕上显示,光标位置也不改变。

 

可以读入控制键,比如F1-F12,上下左右,退格,回车,ESC等。

当你按“上”键时,readkey第一个读到的是0,第二个才是“上”的代码72

 

常用的几个按键码:

上:72   下:80   左:75   右:77

退格:8     回车:13     ESC :27 

 

用readkey函数并不能读入键盘的状态字,比如单独的shift,大小写指示灯切换键。

 

 

 

例:

uses crt;

var

ch:char;

begin

  repeat

     ch:=readkey;          //读入一个键,

     writeln(ord(ch));       //输出键的ASCII码

  until ch:=chr(27);             //直到按ESC键

end.

 

上面的程序,可以测试各个按键的值,包括各种组合键,比如CTRL+F1。

 

 

6:判断当前键盘缓冲区是否还有未读按键字符:(CRT单元)

Function keypressed: boolean ;  判断键盘是否有数据输入

 

说明:该函数并不停下来等待键盘输入,只是判断是否有按键按下。

如果还有未读字符,结果为真,如果无字符,则结果为假。

 

Begin

  If keypressed then writeln(‘YES’)

       Else writeln(‘NO’);

End.

 

该函数一般readkey配合使用。

 

7:发音程序:(CRT单元)

Procedure  sound(HZ: WORD ) ;  发出HZ的频率声音。

Procedure  nosound ;  停止发音。

 

说明:运行sound(X)后,PC扬声器一直会发出以X频率的声音,直到你运行nosound。

 

例:

 

Uses crt;

Var

  Pp: array [1..7] of WORD;

  I:integer;

Begin

 

  pp[1]:=131;pp[2]:=147;pp[3]:=165;pp[4]:=175;pp[5]:=196;pp[6]:=220;pp[7]:=247;

 

{以上为C调1234567的发音,高一个调,只要乘2倍即可}

  for i:=1 to 7 do

     begin

 

   Sound(pp[i]);  //发出声音

   Delay(1000);  //延迟1秒(1000ms).

 End;

Nosound;        //关闭声音

End.

 

 

CRT常用的就这么几个过程函数, 主要是读按键,改变颜色,发音等。

 

 

 

 

 

 

下面的是DOS单元的常用函数过程。

 

8:取得当前计算机时间:(DOS单元)

Procedure gettime(Var hour,minute,second,swc100: WORD ) ; 取时///1/100秒)

9:重新设置计算机时间:(DOS单元)

Procedure settime(hour,minute,second,swc100: WORD ) ; 设计时///1/100秒)

10:取得当前计算机时间:(DOS单元)

Procedure getdate (Var year,month,day: WORD ) ;取得计算机日期年//

11:重新设置计算机时间:(DOS单元)

Procedure setdate(year,month,day: WORD ) ; 设置日期:年//

 

例:

Uses dos;

Var hour,minute,second,sec100,year,month,day: WORD;

Begin

   While not keypressed do

     Begin

       gettime(hour,minute,second,swc100) ;

getdate (year,month,day )

       Gotoxy(1,1);

       Writeln(year, ‘-’,month,’-’,day);      //第一行显示年-月-日

       Gotoxy(1,2);

       Writeln(hour:2,’:’,minute,’:’,second, ‘.’,sec100);  第二行显示HH:MM:SS.S100

     End;

 

End.

 

 

 

12:直接调用DOS中断:(DOS单元)

Procedure intr(intno:byte;Var regs: registers ) ; 运行中断,输入输出参数都在regs

 

例1:

function isok: boolean;

var

   reg:registers;     //寄存器类型

begin

   reg.AX:=$DB00;   //寄存器AX=0XDB00;

   intr($2F,reg);      //运行中断INT2F,返回值在reg变量

   if (reg.al)<>$FF then isok:=false else ispk:=true;   //根据寄存器返回值处理事件。

end;

//上面的程序,其实中调用中断,看UCDOS中文系统是否已运行,过时的代码。

 

例2:

Var

  Buff: array[1..512] of byte;  //用来存512个字节,刚好是一个扇区的大小。

 

procedure readdisk(drv,cy,head,sec:word;VAR result:boolean);

begin

   reg.DX:=head*256+drv;

   reg.CX:=((cy div 256)*64+sec)+(cy mod 256)*256;

   reg.BX:=ofs(buff[1]);   //BX指向buff的偏移地址。

   reg.AX:=$0201;       //AX=02,表示读,01表示读一个扇区

   reg.es:=seg(buff[1]);    //ES指向buff的段地址

   intr($13,reg);          //运行int 13H.

   if reg.ah=0            //如果ah=0读成功。读出的数据在ES:BX开始的空间

   then result:=true else result:=false;

end;

 

上面又增加了很多没见过的东西。比如段地址,偏移地址,寄存器类型变量。