求ea出品的俄罗斯方块tetris psp破解版。
您好,PSP俄罗斯方块(EA出品)已发送至Email,请查收。下载后解压即为ISO镜像。
怎么用vb制作俄罗斯方块游戏啊,简单点的。
罗斯方块的发明者,是当时还被称为"苏联"的联邦科学员阿莱克斯?帕吉托夫,该游戏最初是作为自我消遣的电脑游戏而被制作出来的。
现在制作如下
开始
同时全盘检测键盘
全局判断
扫描每行格式是否有满的
有就清除当行显示
将上面左边下一Y>0
加分
判断分值是否到升级速度阶段
到则加速下落
随机抽取方块
随机抽取下落地点
判断下落速度下落方块(TIMER控件)
如果按下则加快下落
谁有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;
/* initialize graphics mode */
initgraph(&gdriver, &gmode, "e://tc2");
/* read result of initialization */
errorcode = graphresult();
if (errorcode != grOk) /* an error occurred */
{
printf("Graphics error: %s/n", grapherrormsg(errorcode));
printf("Press any key to halt:");
getch();
exit(1); /* return with error code */
}
/* return to text mode */
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 * textstring);
在(x,y)处用当前字体(缺省的字体是DEFAULT_FONT)显示字符串textstring,字符串的对齐方式由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); /* wait for a keystroke */
printf("0x%x/n",key);
if (key==0x11b) break; /* Escape */
}
常用按键的按键码如下:
#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这个程序完整地贴在下面,并加上具体的解释。
/* prog5.c */
This is an interrupt service routine. You can NOT compile this
program with Test Stack Overflow turned on and get an executable
file which will operate correctly. */
/* 这个程序每隔1秒钟输出一个整数,10秒钟后结束程序。
按escape键提前退出程序 。*/
#include <stdio.h>
#include <dos.h>
#include <conio.h>
/* Escape key */
#define VK_ESC 0x11b
#define TIMER 0x1c /* 时钟中断的中断号 */
/* 中断处理函数在C和C++中的表示略有不同。
假如定义了_cplusplus则表示在C++环境下,否则是在C环境下。 */
#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif
int TimerCounter=0; /* 计时变量,每秒钟增加18。 */
/* 指向原来时钟中断处理过程入口的中断处理函数指针(句柄) */
void interrupt ( *oldhandler)(__CPPARGS);
/* 新的时钟中断处理函数 */
void interrupt newhandler(__CPPARGS)
{
/* increase the global counter */
TimerCounter++;
/* call the old routine */
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) /* 按escape键提前退出程序 */
{
printf("User cancel!/n");
break;
}
}
if (TimerCounter>18) /* 1秒钟处理一次 */
{
/* 恢复计时变量 */
TimerCounter=0;
time++;
printf("%d/n",time);
if (time==10) /* 10秒钟后结束程序 */
{
printf("Program terminated normally!/n");
break;
}
}
}
KillTimer(); /* 恢复时钟中断 */
}
struct shape shapes[19]=
{
/*{x1,y1,x2,y2,x3,y3,x4,y4, color, next}*/
{ 0,-2, 0,-1, 0, 0, 1, 0, CYAN, 1}, /* */
{-1, 0, 0, 0, 1,-1, 1, 0, CYAN, 2}, /* # */
{ 0,-2, 1,-2, 1,-1, 1, 0, CYAN, 3}, /* # */
{-1,-1,-1, 0, 0,-1, 1,-1, CYAN, 0}, /* ## */
……
}
enum bool Confilict(int ShapeIndex,int x,int y)
{
int i;
/* 对组成索引号为ShapeIndex的外形的四个方块依次判定 */
for (i=0;i<=7;i++,i++) /* i分别取0,2,4,6 */
{
/* 假如四个方块中有任何一个方块的x坐标小于1或大于10,表示超出左边界或右边界。
此时,发生冲突。 */
if (shapes[ShapeIndex].xy[i]+x<1 ||
shapes[ShapeIndex].xy[i]+x>10) return True;
/* 假如四个方块中某个方块的y坐标小于1,表示整个外形还没有完全落入游戏板中。
此时,没有必要对这个方块进行判定。*/
if (shapes[ShapeIndex].xy[i+1]+y<1) continue;
/* 假如四个方块中有任何一个方块与游戏板当前状态发生冲突,则整个外形在(x,y)处
与游戏板当前状态冲突 */
if (board[shapes[ShapeIndex].xy[i]+x][shapes[ShapeIndex].xy[i+1]+y])
return True;
}
/* 四个方块中没有任何一个方块与游戏板当前状态发生冲突,则整个外形在(x,y)处
没有与游戏板当前状态冲突 */
return False;
}
cad2007下载,总是出现这种问题,求解呢?
被你公司领导锁住了。申请安装新软件,领导同意后就按正常步骤去安装。
俄罗斯方块下降的速度是通过什么技术实现的
俄罗斯方块实现下降速度使用编程技术:JAVA,C语言,C#。
俄罗斯方块
俄罗斯方块是款非常流行的小游戏,通过七个方块的旋转和位移,构成各种变幻莫测的图案。而游戏者也在不断的叠加和消除中找到乐趣。
从编程的角度来说,这个游戏混合了键盘事件,定时器,随机数,鼠标事件(如果没有菜单,这个也不是必需的),数据结构比较清晰,算法比较灵活,图形是比较简单的矩形,所以很适合刚学习完某种语言的语法又想做点什么的初学者。
本文使用的语言包括:c(Turboc2.0,VC6.0),JAVA(Applet),c#(.NET2003)
编写这个游戏的基本过程是:
首先,把这七个方块用一种数据结构存储起来
其次,在游戏中将这七个方块随机挑选出来并显示在屏幕上,根据键盘事件进行旋转
最后,判断到达底部的方块是简单叠加还是引发消除事件
另外,对这个游戏来说,还有一些记分和过关加速的规则,这些会穿插在上面的内容中讲述。
1存储和旋转七个方块
对于OOP语言(JAVA,C#)来讲,可以写一个数据结构类,处理本游戏中的全部数据。在界面中调用这个类,以实现界面操作与数据结构分离。在后面展示这两个数据结构类的时候,会发现除了语法外,这两个类是基本相同的(把C#的类改了改,再加上键盘操作就成Applet了)。
对于过程化语言(c)来说,界面显示函数与数据结构函数地位相当,所以在形式上稍微分分就行了。
1.1存储七个方块
普通俄罗斯方块游戏中,只有七个基本方块:|,Z,N,L,7,|-,O,如果加上旋转,一共是19种方块(要注意哦,最后一个正方形的方块不能旋转)。这19种方块都可以画在一个4*4的方格中。
于是就有两个方法:一个是只存储七个方块,在游戏运行的时候计算旋转后的方块形状;另一个是将19种方块全部存储起来,在游戏运行的时候计算取其中的哪个方块。
另外,考虑到4*4是16,而一个int正好是16位(TC2是16位,其他的是32位),所以可以把一个方块存储在一个int数据中,取出的时候,判断它的每个bit位,为1处有小方块,为0处是空白。
分别用二维数组和bit的方法来表示这19个方块:
int blocks_shape[19][16]={
0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,/*11*/
0,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,/*12*/
0,0,0,0,0,1,1,0,1,1,0,0,0,0,0,0,/*21*/
0,0,0,0,1,0,0,0,1,1,0,0,0,1,0,0,/*22*/
0,0,0,0,1,1,1,0,1,0,0,0,0,0,0,0,/*31*/
0,0,0,0,1,0,0,0,1,0,0,0,1,1,0,0,/*32*/
0,0,0,0,0,0,1,0,1,1,1,0,0,0,0,0,/*33*/
0,0,0,0,1,1,0,0,0,1,0,0,0,1,0,0,/*34*/
0,0,0,0,1,0,0,0,1,1,1,0,0,0,0,0,/*41*/
0,0,0,0,0,1,0,0,0,1,0,0,1,1,0,0,/*42*/
0,0,0,0,1,1,1,0,0,0,1,0,0,0,0,0,/*43*/
0,0,0,0,1,1,0,0,1,0,0,0,1,0,0,0,/*44*/
0,0,0,0,0,1,0,0,1,1,1,0,0,0,0,0,/*51*/
0,0,0,0,0,1,0,0,1,1,0,0,0,1,0,0,/*52*/
0,0,0,0,0,0,0,0,1,1,1,0,0,1,0,0,/*53*/
0,0,0,0,1,0,0,0,1,1,0,0,1,0,0,0,/*54*/
0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,/*61*/
0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,/*62*/
0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,/*71*/
};
注释里第一个数字表示方块编号,第二个数字表示该方块的第几个变形。
private int[] blocks_shape = {3168,1224,1728,2244,3712,2188,736,3140,2272,1100,3616,3208,1248,1220,228,2248,3840,17476,3264};
显然,第二种方法节约了一些内存。
1.2旋转七个方块
在游戏中计算旋转后的方块形状:
这个其实就是考考二维坐标知识。还是不贴图。先在脑袋里想像一个4*4的方格,上面有个|-。|占三个方格的长度,-占一个。以左下角为原点,从左向右画x轴;从下向上画y轴。如果在游戏中想逆时针旋转方块,就把这个坐标轴顺时针旋转一次。多想几遍得到结论:原来的x坐标与新的y坐标相同,原来的y坐标与新的x坐标方向正好相反。这里的“相反”意思是,原来是4,现在是1,原来是2,现在是3。语言不好表达啦,不过想通的话就很容易理解。
在游戏中计算调用19个方块中的哪个方块:
将19个方块存入数组后,再设一数组告诉程序哪七个下标是七个基本方块。比如:private int[] start_bricks = {0,2,4,8,12,16,18};每次随机产生的方块下标都为start_bricks里的元素。当游戏者旋转方块时,将当前方块下标加1,再判断加1后的下标是否在start_bricks里。如果在的话,说明已经是另一个形状了,舍掉,使用start_bricks里原来的下标。最后根据此下标在blocks_shape数组中取出形状,显示在屏幕上。
看看代码。
private int[] bricks = {3168,1224,1728,2244,3712,2188,736,3140,2272,1100,3616,3208,1248,1220,228,2248,3840,17476,3264};
private int[] start_bricks = {0,2,4,8,12,16,18};
/*mid是当前方块在bricks中的下标*/
for(i=0;i<7;i++)
{
if(mid+1==start_bricks[i])
/*如果mid加1后是start_bricks中的元素*/
/*则还是取start_bricks中原来的元素,即七个基本方块之一,不让它变形*/
mid=start_bricks[i-1];
}
2方块落下的处理
2.1判断方块已经到达底部或是否碰到墙壁
不论是用二维数组还是用bit的方法存储的方块,最终都需要遍历方块的16个小方块中为1的地方是否将会碰到障碍物。“将会”指的是方块如果向左,向右,向下移动后就会碰到障碍物;“障碍物”指的是左右下墙壁和底部已经落下未被消除的小方块。
比较困难的地方,就是把为1的地方转换为相应的坐标,用此坐标判断是否碰到了障碍物。用旋转的办法比较简单,根据旋转的方向转换一下坐标就可以了。如果采用存储19个方块的方法的话,直接看下程序:
用二维数组:
/*遍历16个小方块*/
for(j=0;j<16;j++)
{
/*此处有小方块,判断它是否碰到障碍物*/
if(blocks_shape[i][j]==1)
{
/*a,b是方块左上角坐标,aaa,bbb是新得到的小方块的坐标*/
aaa=a-1+j/4;
bbb=b+j%4;
if( ( aaa==h )||( aa[aaa][bbb]>0 )||( bbb<0 )||( bbb>9 ) )
/*aaa==h 表示该小块已经到达底部;aa[aaa][bbb]>0 表示底部该位置已经有了小方块*/
{
/*返回false,表示会碰到障碍物*/
return false;
}
}
}
用bit与此类似,只是多了一个移位处理:
for(int i=0;i<16;i++)
{
/*num是当前方块的int值,a,b是当前方块的左上角坐标*/
if( (num>>(15-i)&1)!=0 )/*此位为1*/
{
if( (a+i/4>22)||(b+i%4<0)||(b+i%4>11) )/*取得新坐标并加以判断*/
{
flag=false;
break;
}
if( (arr[a+i/4][b+i%4]>0) )/*底部该位置是否有已经落下的小方块*/
{
flag=false;
break;
}
}
}
2.2消除一行
判断到方块落下后,就开始检查是否有满足消除条件的行了。
规则很简单:只要某行被小方块全部填充,该行就被消除,上面的小方块全部下移一行。所以,只要把原来的小方块全部擦去,计算完新方块位置后,再全部画出就可以了,计算的时候,可以遍历整个游戏区域,看有没有可以消除的行。但是在实际编程中就会发现,这样的设计虽然简单,但是计算量大,而且会引起闪烁(因为是整个擦除和重画),效果不是很好。仔细观察这个游戏,就会发现,其实每次消除的时候,只要判断当前方块所在的四行就足够了。在编程的时候,还可以为方块设一个最高高度h,每次刷新的时候,只刷新从h到当前方块底部的行。虽然这样有点烦琐,但是节约了计算时间,减少了重绘面积,效果还是挺明显的。
另外,一些关于这个游戏算法的介绍,有人建议把随机产生下一个方块的计算放在当前方块正在下落的时候,因为那时比较空闲。总之,只要用心去想,一定会写出代码紧凑,资源利用合理,界面舒适的游戏。