(100分)策划俄罗斯方块的完整游戏流程(有可能加50分,谢谢)

从网上下载的CSDN代码。

分享...........

我用TC调试成功。

因为有

# include & ltstdio.h & gt

# include & ltstdlib.h & gt

# include & ltbios.h & gt/*在这里,你需要读取系统运行时间作为计时器*/

# include & ltgraphics.h & gt/*可惜TC2简单的图形让我放弃使用*/

# include & ltconio.h & gt/*win32+openGL来解释。*/

#define MAX_X 14 /*最大可见X*/

#define MAX_Y 21 /*可见最大Y*/

/*我们已经定义了最大可见X和Y,那么还有没有?

可见的部分,其实就是地图中的左右(大方框)

两边和最下面两行都填1,大大简化了。

界外判断,其实本案不是这样的。

码,因为1旁边有个圈,防止小盒子变大。

箱子的冲压范围

*/

#定义MAX_C 7 /*最大类别,这个不用解释*/

#define KEY_UP 'w' /*定义上下左右按钮*/

#定义向下键

#define KEY_LEFT 'a '

#定义KEY_RIGHT 'd '

#define KEY_ESC 27 /* Exit */

typedef int BOOL

#定义假0

#定义TRUE 1 /*没有这些TC...自己定义吧:)*/

/*时钟结构*/

Typedef结构{/*时钟结构*/

BOOL已启用;/*时钟是否开启*/

无符号整数区间;/*时间间隔*/

无符号整数lasttime/*这是内部变量*/

}定时器;

/*

*现在已经进入编程初级阶段。

*一开始,我会写所有的函数原型和它们的功能。

*主功能在程序的最后,你可以在这里看到整个游戏的组织结构。

*很好,只有几十行,而且很好理解。当然,我们先来看看函数的原型。

*和解释

*/

/******************************************************\

*功能原型和描述*

\******************************************************/

/*下面三个函数可以参考定时器结构。在函数声明*/之后

int GetTickCount();/*返回计算机或操作系统运行所用的时间*/

/*已包含在win32环境下的windows.h中,4字节*/

/*在DOS(代码)环境下,要自己写,用BIOS.h内容*/

int setTimer(Timer *t,unsigned int intv,BOOL en);

/*设置时钟t,参数为时钟指针、时间间隔和活动*/

/*时间间隔,win32下毫秒,DOS下1/18秒(有点低)*/

BOOL test Timer(Timer * t);/*测试时钟t是否到达预定时间*/

/*比如下面的代码:*/

/*

setTimer(& amp;t,1,1);设置1单位的间隔

while(1) {

if(testTimer(& amp;t)) printf("Active!\ n ");

}

活跃会定期印在屏幕上(1台)!

一般来说,testTimer必须循环重复执行,激活时返回1。

*/

void渲染(void);/*独特的绘图功能*/

/*注意,这个函数根据贴图中的点阵和

在地图中间坐标的右边位置画一个小方框*/

/*DOS图形当然很低,但是这里全屏画图还是可以的。

是的,我使用双缓冲来交换图纸,这让我感觉更好*/

void init map(void);/*初始化地图(大框)*/

/*之前提到过这个二维数组中有一个1的圆来阻止它。

小方框越界了,这是函数*/

void new game();/*创建新游戏*/

/*此函数初始化一个或多个时钟,并构建第一个下降框*/

/*当然,在构造之后,预览应该是一个一个生成的*/

void rotateBox(int box 1[5][5],int box 2[5][5]);

/*核心函数成员,逆时针旋转box1 90度,保存在box2 */

void rebidnext();

/*核心函数成员,生成下一个框*/

int drop();

/*核心函数成员,向下移动下降框(实际上是增加下降框)

子的y值,当然要判断是否与贴图格子重叠*/

/*与地图重叠,无法完成下落操作。返回0*/

void putBox();

/*在此之上,落盒和地图是两个独立的维度*/

/*当下落失败时,小盒子必须返回顶部重新进行下落,这*/

/*当原框内容当然会变成map、putBox的内容。

就是根据XY */

void clear();

/*此功能在坠落失败和putBox后执行,扫描整个地图*/

/*清除格子的全行,细节在函数里*/

int move(int dir);

/*左右移动下拉框,dir表示向左或向右,和drop一样。

是一样的*/

int test(int mx,int my,int box[5][5]);

/*这个更重要。判断盒子在MX和My的坐标上,和地图上是一样的。

非空格子是否重叠。一个很常见的函数*/

int rotate();

/*旋转下降盒。当然,如果旋转后与地图冲突,就会

取消旋转,返回0,但是返回值好像没用~ */

int new fall();

/*创建一个拖放元素,并将“下一个”预览的内容复制到下拉框*/

/*并将下拉框移动到地图顶部。当然,这个过程,如果顶

如果部门有冲突,则返回0,描述完整...gameOver*/

/******************************************************\

*可变面积*

\******************************************************/

/*在上面的解释中,可能会有一些无知,因为可能对实际使用的变量没有了解。

*是的。

*/

int map[MAX _ Y+4][MAX _ X+4];/*地图\大框...MAX_X,Y是可视面积*/

/*我说过我们需要在外面安排两个“警卫*/

int curbox[5][5];/*当前下落的盒子*/

int curx,cury/*保存当前活动框在地图上的位置*/

int next box[5][5];/*容纳下一个形状的盒子*/

/*这只是几个方框和坐标*/

/*这里有七个标准的俄罗斯方块图形格子,会复制到Phase */

/*应该是的框...:) */

Int box[MAX_C][5][5] = {/*MAX_C(7)预定义框*/

{

{0,0,0,0,0},

{0,0,0,0,0},

{1,1,1,1,0},

{0,0,0,0,0},

{0,0,0,0,0}

},

{

{0,0,0,0,0},

{0,0,1,0,0},

{0,1,1,1,0},

{0,0,0,0,0},

{0,0,0,0,0}

},

{

{0,0,0,0,0},

{0,1,1,0,0},

{0,0,1,1,0},

{0,0,0,0,0},

{0,0,0,0,0}

},

{

{0,0,0,0,0},

{0,0,1,1,0},

{0,1,1,0,0},

{0,0,0,0,0},

{0,0,0,0,0}

},

{

{0,0,0,0,0},

{0,1,1,0,0},

{0,0,1,0,0},

{0,0,1,0,0},

{0,0,0,0,0}

},

{

{0,0,0,0,0},

{0,0,1,1,0},

{0,0,1,0,0},

{0,0,1,0,0},

{0,0,0,0,0}

},

{

{0,0,0,0,0},

{0,0,1,1,0},

{0,0,1,1,0},

{0,0,0,0,0},

{0,0,0,0,0}

}

};

/******************************************************\

*时钟*

\******************************************************/

/*时钟部分也很好理解,一个用来设置时钟,一个用来测试时钟激活状态*/

定时器tDown/*正常的下降定时时钟间隔将会更大*/

定时器tFast/*按下KEY_DOWN时使用快速下降*/

int speed = 13;/*控制下降时间间隔*/

#定义快速_INTV 1 /*快速时钟的间隔*/

/******************************************************\

*时钟*

\******************************************************/

/*时钟部分也很好理解,一个用来设置时钟,一个用来测试时钟激活状态*/

定时器tDown/*正常的下降定时时钟间隔将会更大*/

定时器tFast/*按下KEY_DOWN时使用快速下降*/

#定义快速_INTV 1 /*快速时钟的间隔*/

Int GetTickCount() {/*读取BIOS时钟*/

int ret

ret = peek(0x0,0x46e);/*实际在0:046e读取内存内容*/

ret & lt& lt= 8;/*这个地方是$ % # $ $ % &;^*/

ret += peek(0x0,0x 46c);/*新东西那么多,找几本书看看*/

返回(ret);

}

int setTimer(Timer *t,unsigned int intv,BOOL en) {

t->;enabled = en/*设置时钟*/

t->;intervel = intv

t->;last time = GetTickCount();/*lasttime记录最后的*/

/* What /*tickcount返回*/

/*以便再次测试时间时,生成新的tickcount。

它减去最后一次tickcount得到一个时间。

间隔,这个可以和intervel比较一下,看是不是

激活的

*/

返回0;

}

Boolstesttimer (timer * t) {/*以上六行解释:)*/

无符号int tmp,dt;

如果(!(t->;enabled))返回FALSE

tmp = GetTickCount();

dt = tmp-(t-& gt;last time);

if(dt & gt;= t->;intervel) {

t->;lasttime = tmp

返回TRUE

}

返回FALSE

}

/******************************************************\

*渲染部分*

\******************************************************/

/*提供渲染以更新整个屏幕*/

/*这个功能还有很多话要说,为了追求美观和编译*/

灵活性当/*时,这个函数写得相当长...*/

/*现在写一些关于这个游戏的图形...我也不用TC2图形。

我很乐意。毕竟已经过时了,但是鉴于它的简单性和实用性,还是用来教学的。

太完美了,这也是教学中一直用TC的原因。老师不喜欢让学生学习。

学生问一些他们难以掌握的问题...

/*这里我用VGAMED模式代替VGAHI,因为有两个VGAMED。

Page(可以想象成一个缓冲区),可以用来画图,不用闪烁。也就是在后台。

在页面上画一个图形,完成后显示。

这里使用了两个函数:

Setactivepage(1 | 0)参数只能是1或0。选择一个绘图页,例如,选择。

选择1后,以后所有的绘图动作都将在1页上绘制。

Setvisualpage(1 | 0)这叫选择可见页面,也就是在屏幕上选择。

显示页面1或0

*/

void渲染(void) {

int x,y;

静态int c page = 0;/*当前页面,使用*/

#define STARTX 50 /*定义几个常量*/

#定义STARTY 0

#定义镜头18

setactivepage(cPage=(cPage == 0?1:0));/*选择页面*/

clear device();/*清空屏幕*/

set color(15);

矩形(STARTX + LEN * 2 - 2,

STARTY + LEN * 3 - 2

STARTX + LEN * (MAX_X - 2) + 2,

STARTY+LEN *(MAX _ Y-2)+2);

/*用白色画出轮廓*/

setfillstyle(SOLID_FILL,5);

for(y = 3;y & ltMAX _ Y-2;Y++) {/*画地图*/

for(x = 2;x & ltMAX _ X-2;x++) {

if(map[y][x]) {

矩形(x * LEN + STARTX,

y * LEN + STARTY,

x * LEN + STARTX + LEN,

y * LEN+STARTY+LEN);

bar( x * LEN + STARTX + 1,

y * LEN + STARTY + 1,

x * LEN + STARTX + LEN - 2,

y * LEN+STARTY+LEN-2);

}

}

}

/*不要把画图操作介绍的太复杂,只是为了写作*/

/*在上面的段落中,根据局部地图上的点阵将地图反映到屏幕上*/

for(y = 0;y & lt5;Y++) {/*画落体*/

for(x = 0;x & lt5;x++) {

if(curbox[y][x]) {

if(y+cury & gt;2) {

矩形((x + curx) * LEN + STARTX,

(y + cury) * LEN + STARTY,

(x + curx) * LEN + STARTX + LEN,

(y+cury)* LEN+STARTY+LEN);

bar((x+curx)* LEN+STARTX+1,

(y + cury) * LEN + STARTY + 1,

(x + curx) * LEN + STARTX + LEN - 2,

(y+cury)* LEN+STARTY+LEN-2);

}

}

}

}

/*根据下落框在地图上的坐标,将下落框绘制到相应的区域*/

for(y = 0;y & lt5;Y++) {/*画下一个*/

for(x = 0;x & lt5;x++) {

if(nextbox[y][x]) {

矩形(x * LEN + 320,

y * LEN + 10,

x * LEN + 338,

y * LEN+28);

bar( x * LEN + 321,

y * LEN + 11,

x * LEN + 336,

y * LEN+26);

}

}

}

/*这将绘制下一个框的预览*/

setvisual page(c page);/*确保在页面中绘制*/

/*展示它*/

}

/******************************************************\

*初始化部分*

\******************************************************/

/*提供newGame()来初始化新游戏*/

Void initMap(void) {/*初始化映射*/

int x,y;/*我们需要一圈警卫...*/

for(y = 0;y & ltMAX _ Y;y++) {

for(x = 0;x & ltMAX _ X;x++) {

if(x & lt;2 | | x & gtMAX _ X-3 | | y & gt;MAX_Y - 3)

map[y][x]= 1;

else map[y][x]= 0;

}

}/*此形状在此处初始化*/

}/*当然没有封面...*/

Void newGame() {/*创建新游戏*/

int x,y;

init map();/*初始化映射*/

srand(GetTickCount());/*初始化随机生成器*/

rebidnext();/*创建下一个*/

setTimer(& amp;tDown,速度,1);/*开始时钟(快速和慢速)*/

setTimer(& amp;tFast,FAST_INTV,1);

new fall();/*操作跌落箱*/

/*这是第一个下落的方块。

它位于地图的顶部*/

}

/******************************************************\

*核心功能*

\******************************************************/

void rotate box(int box 1[5][5],int box2[5][5]) {

/*旋转box1并输出到box2*/

int x,y;

for(x = 0;x & lt5;X++) /*这个函数可能需要实际的*/

for(y = 4;y & gt= 0;Y-)/*写出来打动*/

box 2[y][x]= box 1[x][4-y];

}

Void rebuild next () {/*创建下一个形状并将其放入nextbox */

int i,x,y;

I = random(MAX _ C);/*选择几个方块中的一个*/

for(y = 0;y & lt5;Y++) /*并复制它*/

for(x = 0;x & lt5;x++)

next box[y][x]= box[I][y][x];/*复制*/

}

Int drop() {/*行踪,返回成功或失败*/

int newy/*盒子将放置的新位置*/

newy = cury+1;/*是当前的Y位置+1*/

if(test(curx,newy,curbox)) {

cury = newy/*测试箱在这个位置*/

返回1;/*有冲突吗?如果没有,*/

}/*直接设置cury */*/

返回0;

}

Void putBox() {/*在地图上填充边界框*/

int x,y;

for(y = 0;y & lt5;Y++) /*这个也简单,主要是对root */

for(x = 0;x & lt5;X++) /*根据curx,cury表示位置*/

if(curbox[y][x])

map[y+cury][x+curx]= curbox[y][x];

}

Void clear() {/*清除整行*/

/*这个函数其实效率很低,简单来说。

从头到尾都经过测试*/

/*具体算法是:

从第0行到最后一行,测试地图格子是否满,如果满。

从当前行开始,上面的地图将下降一行*/

int x,y;

int dx,dy;

int完整标志;

for(y = 0;y & ltMAX _ Y-2;Y++) {/*最后两行是保留的*/

完整标志= 1;/*假设已满*/

for(x = 2;x & ltMAX _ X-2;X++) {/*保留列~ */

如果(!map[y][x]) {

完整标志= 0;

打破;

}

}

If(fullflag) {/*下移一行*/

for(dy = y;dy & gt0;dy -)

for(dx = 2;dx & ltMAX _ X-2;dx++)

map[dy][dx]= map[dy-1][dx];

for(dx = 2;dx & ltMAX _ X-2;dx++)

map[0][dx]= 0;

/*并清除第一行*/

}

}

}

Int move(int dir) {/*返回成功或失败*/

int newx

if(dir)newx = curx+1;

/*像drop一样,准备好移动的坐标*/

else newx = curx-1;

If(test(newx,cury,curbox)) {/*测试是否有冲突*/

curx = newx/*开关curx*/

返回1;

}

返回0;

}

int test(int mx,int my,int box[5][5]) {

/*测试箱子是否能降落在mx,我在地图中的位置*/

/*这是最关键的函数,它决定了是否存在非空冲突*/

/*但是算法很简单*/

int x,y;

for(y = 0;y & lt5;y++)

for(x = 0;x & lt5;x++)

if(map[y+my][x+MX]& amp;& amp方框[y][x])

返回0;

返回1;

}

int rotate() {

int x,y;

int newbox[5][5];/*我们必须将当前框旋转到新框*/

/*再次测试这个新盒子的冲突*/

rotateBox(curbox,new box);/*转到新框*/

if(test(curx,cury,newbox)) {

/*并且新框可以放在地图上不冲突*/

for(y = 0;y & lt5;y++)

for(x = 0;x & lt5;x++)

curbox[y][x]= new box[y][x];/*复制到*/

返回1;

}

否则返回0;

}

Int newfall() {/*无法创建下降元素。返回0*/

int x,y;

curx = MAX _ X/2-2;/*重新分配小方框的位置*/

cury = 0;

for(y = 0;y & lt5;y++)

for(x = 0;x & lt5;x++)

curbox[y][x]= next box[y][x];/*复制下一个框*/

rebidnext();/*重建nextBox*/

返回测试(curx、cury、curbox);

}

/************************************************************\

*主要功能-整个游戏架构*

\************************************************************/

int main() {

char键;/*记录当前按键*/

int I;

int gd = VGA,gm = VGAMED/*初始化图形模式*/

Timer * ptDown/*时钟下降(快或慢)*/

定时器趋势器;/*以免渲染给程序造成太大负担*/

/*使用时钟控制渲染速度*/

/*将其设置为interval = 1,*/

/*那就是18 FPS,当然达不到标准*/

/* 60帧/秒...毕竟这是DOS...*/

setTimer(& amp;趋势者,1,1);

init graph(& amp;gd,& ampgm,“”;/*初始化图形*/

new game();/*新游戏...*/

While(1) {/*主游戏循环*/

If(kbhit()) {/*如果按下键盘*/

key = getch();/*将键值读取到key*/

}

else key = 0;

开关(键){/*判断读取键*/

案例索引_UP:

rotate();/*,旋转下拉框*/

打破;

案例关键点_向下:

ptDown = & amptFast/*使用tFast时钟*/

打破;

案例关键字_左:

移动(0);/*向左移动*/

打破;

案例关键字_右:

移动(1);/*向右移动*/

打破;

案例键_ESC:

closegraph();/*结束游戏*/

退出(0);

默认值:

ptDown = & amptDown/*使用原始速度*/

}

If(testTimer(ptDown)) {/*已经在上面设置了行踪。

使用的时钟在ptDown */中

如果(!Drop()) {/* falls,0*/

putBox();/*写在地图上*/

clear();/*清除整行*/

如果(!Newfall()) {/*创建新的掉落,如果失败,游戏结束*/

closegraph();

退出(0);

}

}

}

if(testTimer(& amp;Trender)) /*最后...提供;给予...*/

render();

}

}