[c语言编程]俄罗斯方块游戏…

Tc2.0 编写俄罗斯方块游戏 

很多编程爱好者都编写过俄罗斯方块的游戏程序。很久以前,我用Tc2.0也做过一个;最近有好些朋友看见我以前的俄罗斯方块的程序后, 
问我是怎么做的。我一直想把这个程序的整个过程写一份详细的东西,与各位编程爱好者分享,一直没空。正好现在放假了,而且离回家还有几天。于是我就把这个程序重新写了一遍,尽量使程序的结构比较清晰好懂一些。同时写了下面的这份东西。 

  俄罗斯方块游戏的程序中用到了一些方法。为了比较容易理解这些方法,我在讲述的同时写了些专门针对这些方法的示例程序。这些示例程序力求短小,目的是用最小的代码能够清楚的示例所用的方法。这些示例程序都经过tc2.0测试。最后还附了完整的俄罗斯方块游戏的源代码,和最终的可执行程序。如果你看了这份东东,有什么意见和想法,请发电子邮件告诉我。我将会继续更新这分东东,最新的版本可以在我的个人主页上下载。 

  下面的问题是有关俄罗斯方块程序的,其中有些是朋友问我的,有些是我认为可能会被问到的。我尽量按问题从易到难排列这些问题。 关于俄罗斯方块程序的一些问题: 
****************************************************** 

Tc2.0中怎么样设置图形显示? 
Tc2.0中常用图形函数的用法? 
怎样获取键盘输入? 
怎样控制方块的移动? 
怎样控制时间间隔(用于游戏中控制形状的下落)? 
游戏中的各种形状及整个游戏空间怎么用数据表示? 
游戏中怎么判断左右及向下移动的可能性? 
游戏中怎么判断某一形状旋转的可能性? 
按向下方向键时加速某一形状下落速度的处理? 
怎么判断某一形状已经到底? 
怎么判断某一已经被填满? 
怎么消去已经被填满的一行? 
怎么消去某一形状落到底后能够消去的所有的行?(如长条最多可以消去四行) 
怎样修改游戏板的状态? 
怎样统计分数? 
怎样处理升级后的加速问题? 
怎样判断游戏结束? 
关于计分板设计的问题。 
关于“下一个”形状取法的问题。 
剩下的问题。 

****************************************************** 
新的问题: 
 我想有一个最高记录的显示,应该怎么做呀? 
 我想实现一个进度存储功能,应该怎么做呀? 

 

Tc2.0中怎么样设置图形显示? 

  Tc2.0中有两种显示模式,一种是我们所熟知的字符模式,另一种是图形模式。在字符模式下只能显式字符,如ASCII字符。一般是显示25 
行,每行80个字符。程序缺省的是字符模式。在字符模式下不能显式图形和进行绘图操作。要想进行图形显示和绘图操作,必须切换到图形模 
式下。 

  Tc2.0中用initgraph()函数可以切换到图形模式,用closegraph()可以从图形模式切换回字符模式。initgraph()和closegraph()都是图形 
函数,使用图形函数必须包括头文件"graphics.h"。 

  void far initgraph(int far *graphdriver,int far *graphmode,char far *pathtodriver);graphdriver是上涨指向图形驱动序号变量的指针;graphmode是在graphdriver选定后,指向图形显示模式序号变量的指针。pathtodriver表示存放图形驱动文件的路径。 

  Tc2.0中有多种图形驱动,每种图形驱动下又有几种图形显示模式。在我的程序中图形驱动序号为VGA,图形显示模式序号为VGAHI。这是一种分辨率为640*480(从左到右坐标依次为0-639,从上到下坐标依次为0-479),能够显示16种颜色的图形模式。别的图形驱动序号和图形显示模式序号,可以从手册或联机帮助中找到。 

  pathtodriver指示存放图形驱动文件的路径。图形驱动序号不同,图形驱动文件也不同。序号为VGA图形驱动对应"egavga.bgi"这个图形驱动文件。"egavga.bgi"一般在Tc目录下。 

void far closegraph(void); 
  没有参数,从图形模式直接返回字符模式。 

initgraph()和closegraph()的常用用法如下:
 
 int gdriver = VGA, gmode=VGAHI, errorcode; 

 
initgraph(&gdriver, &gmode, "e:\tc2"); 

 
errorcode = graphresult(); 

if (errorcode != grOk)  

printf("Graphics error: %sn", grapherrormsg(errorcode)); 
printf("Press any key to halt:"); 
getch(); 
exit(1);  

 
closegraph(); 


Tc2.0中常用图形函数的用法? 

在这里讲几个游戏中用到的绘图用的图形函数: 
setcolor(); 
line(); 
rectangle(); 
settextjustify(); 
outtextxy(); 
setfillstyle(); 
bar(); 

void far setcolor(int color); 
  设置画线、画框和在图形模式下显示文字的当前颜色。这个函数将影响line()、rectangle()和outtextxy()函数绘图的颜色。 
color可以取常的颜色常量: 
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 

void far line(int x1,int y1,int x2,int y2); 
用当前颜色从(x1,y1)画一条到(x2,y2)的线段。 

void far rectangle(int left,int top,int right,int bottom); 
用当前颜色画一个左上角为(left,top)、右下角为(right,bottom)的矩形框。 

void far settextjustify(int horz,int vert); 
设置图形模式下文字输出的对齐方式。主要影响outtextxy()函数。 
horiz和vert可取如下枚举常量: 
horiz ?LEFT_TEXT ? 0 ?Left-justify text 
?CENTER_TEXT ? 1 ?Center text 
?RIGHT_TEXT ? 2 ?Right-justify text 
vert ?BOTTOM_TEXT ? 0 ?Justify from bottom 
?CENTER_TEXT ? 1 ?Center text 
?TOP_TEXT ? 2 ?Justify from top 

void far outtextxy(int x,int y,char * textsing); 
在(x,y)处用当前字体(缺省的字体是DEFAULT_FONT)显示字符串textsing,字符串的对齐方式由settextjustify()指定。 

void far setfillstyle(int pattern,int color); 
设置图形的填充模式和填充颜色,主要影响bar()等函数。 
pattern一般取枚举常量值SOLID_FILL,color的取值与setcolor(int color)中color的取值范围相同。 

  介绍完了前面两个问题,现在来写一个程序。这个程序演示前了面所介绍的几个图形函数。 
程序prog1.c 


怎样获取键盘输入? 

  在Tc2.0中有一个处理键盘输入的函数bioskey(); 
int bioskey(int cmd); 
  当cmd为1时,bioskey()检测是否有键按下。没有键按下时返回0;有键按下时返回按键码(任何按键码都不为0),但此时并不将检测到的按 
键码从键盘缓冲队列中清除。 
  当cmd为0时,bioskey()返回键盘缓冲队列中的按键码,并将此按键码从键盘缓冲队列中清除。如果键盘缓冲队列为空,则一直等到有键按 
下,才将得到的按键码返回。 

  Escape键的按键码为0x11b,下面的小程序可以获取按键的按键码。 

for (;;) 

key=bioskey(0);  
printf("0x%xn",key); 
if (key==0x11b) break;  

常用按键的按键码如下: 

#define VK_LEFT 0x4b00 
#define VK_RIGHT 0x4d00 
#define VK_DOWN 0x5000 
#define VK_UP 0x4800 
#define VK_HOME 0x4700 
#define VK_END 0x4f00 
#define VK_SPACE 0x3920 
#define VK_ESC 0x011b 
#define VK_ENTER 0x1c0d 


  完整的程序请参见prog2.c、prog3.c。 
prog2.c获取按键的按键码,按Escape键退出程序。 
prog3.c根据不同的按键进行不同的操作,按Escape键退出程序.
 

怎样控制方块的移动? 
  方块移动的实现很简单,将方块原来的位置用背景色画一个同样大小的方块,将原来的方块涂去。然后在新的位置上重新绘制方块就可以 
了。这样就实现了方块的移动。完整的程序请参见prog4.c。这个用方向键控制一个黄色的小方块在屏幕上上、下、左、右移动。这个程序用到了前面几个问题讲的内容,如果你有点忘了,还要回头看看哦。:) 


怎样控制时间间隔(用于游戏中控制形状的下落)? 
  解决这个问题要用到时钟中断。时钟中断大约每秒钟发生18.2次。截获正常的时钟中断后,在处理完正常的时钟中断后,将一个计时变量 
加1。这样,每秒钟计时变量约增加18。需要控控制时间的时候,只需要看这个计时变量就行了。 


  截获时钟中断要用到函数getvect()和setvect()。 
两个函数的声明如下: 
?void interrupt (*getvect(int interruptno))(); 
?void setvect(int interruptno, void interrupt (*isr) ( )); 

  保留字interrupt指示函数是一个中断处理函数。在调用中断处理函数的时候,所有的寄存器将会被保存。中断处理函数的返回时的指令是iret,而不是一般函数用到的ret指令。 

getvect()根据中断号interruptno获取中断号为interruptno的中断处理函数的入口地址。 
setvect()将中断号为interruptno的中断处理函数的入口地址改为isr()函数的入口地址。即中断发生时,将调用isr()函数。 


  在程序开始的时候截获时钟中断,并设置新的中断处理。在程序结束的时候,一定要记着恢复时钟中断哦,不然系统的计时功能会出问题 
的。具体演示程序请参见prog5.c。由于中断处理大家可能用的不多,所以我把prog5.c这个程序完整地贴在下面,并加上详细的解释。 

 
This is an interrupt service routine. You can NOT compile this 
program with Test Stack Overflow turned on and get an execu 
file which will operate correctly. */ 

 

#include 
#include 
#include 

 
#define VK_ESC 0x11b 

#define TIMER 0x1c  

 

#ifdef __cplusplus 
#define __CPPARGS ... 
#else 
#define __CPPARGS 
#endif 

int TimerCounter=0;  

 
void interrupt ( *oldhandler)(__CPPARGS); 

 
void interrupt newhandler(__CPPARGS) 

 
TimerCounter ; 

 
oldhandler(); 

 
void SetTimer(void interrupt (*IntProc)(__CPPARGS)) 

oldhandler=getvect(TIMER); 
disable();  
setvect(TIMER,IntProc); 
enable();  

 
void KillTimer() 

disable(); 
setvect(TIMER,oldhandler); 
enable(); 


void main(void) 

int key,time=0; 

SetTimer(newhandler);  

for (;;) 

if (bioskey(1)) 

key=bioskey(0); 
if (key==VK_ESC)  

printf("User cancel!n"); 
break; 


if (TimerCounter>18)  

 
TimerCounter=0; 
time ; 
printf("%dn",time); 
if (time==10)  
 
 
printf("Program terminated normally!n"); 
break; 



KillTimer();  


游戏中的各种形状及整个游戏空间怎么用数据表示? 

以后我提到的形状都是指下面七种形之一及它们旋转后的变形体。 

□□□□ □□□□ □□□□ □□□□ 
□■□□ □■■□ □□□□ □□□□ 
□■□□ □■□□ □■□□ □■■□ 
□■■□ □■□□ ■■■□ ■■□□ 

□□□□ □■□□ □□□□ 
□□□□ □■□□ □□□□ 
■■□□ □■□□ □■■□ 
□■■□ □■□□ □■■□ 

我定义了一个结构来表示形状。 
suct shape 

int xy[8]; 
int color; 
int next; 

-1 0 1 2 
-3□□□□ 
-2□□□□ 
-1□□□□ 
0□■□□ 

  所有的各种形状都可以放在4x4的格子里。假定第二列,第四行的格子坐标为(0,0)(如上图中黑块所示),则每个形状的四个方块都可以用4 
个数对来表示。坐标x从左向右依次增加,y从上到下依次增加。表示的时候,组成该形状的四个方块从左到右,从上到下(不一定非要按这个顺 
序)。如上面七种形状的第一个用数对来表示就是(-2,0)、(-1,0)、(0,0)、(1,0)。结构shape中的xy就是用来表示这4个数对的。为了简化程序,用一维数组xy[8]来表示。xy[0]、xy[1]表示第一个数对,xy[2]、xy[3]表示第二个数对,依次类推。 
   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值