主题:PASCAL小游戏常用的过程函数
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(color:byte); 设置将要输出的文字背景颜色
Procedure textcolor(color:byte); 设置将要输出的文字字体颜色
在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;
上面又增加了很多没见过的东西。比如段地址,偏移地址,寄存器类型变量。