/**俄罗斯方块源程序*/#includestdio.h#includestdlib.h#includedos.h#includegraphics.h/*图形函数库*//*定义按键码*/#defineVK_LEFT0x4b00#defineVK_RIGHT0x4d00#defineVK_DOWN0x5000#defineVK_UP0x4800#defineVK_ESC0x011b#defineTIMER0x1c/*设置中断号*//*定义常量*/#defineMAX_BOX19/*总共有19种各形态的方块*/#defineBSIZE20/*方块的边长是20个象素*/#defineSys_x160/*显示方块界面的左上角x座标*/#defineSys_y25/*显示方块界面的左上角y座标*/#defineHorizontal_boxs10/*水平的方向以方块为单位的长度*/#defineVertical_boxs15/*垂直的方向以方块为单位的长度,也就说长是15个方块*/#defineBegin_boxs_xHorizontal_boxs/2/*产生第一个方块时出现的起始位置*/#defineFgColor3/*前景颜色,如文字.2-green*/#defineBgColor0/*背景颜色.0-blac*/#defineLeftWin_xSys_x+Horizontal_boxs*BSIZE+46/*右边状态栏的x座标*/#definefalse0#definetrue1/*移动的方向*/#defineMoveLeft1#defineMoveRight2#defineMoveDown3#defineMoveRoll4/*以后坐标的每个方块可以看作是像素点是BSIZE*BSIZE的正方形*//*定义全局变量*/intcurrent_box_numb;/*保存当前方块编号*/intCurbox_x=Sys_x+Begin_boxs_x*BSIZE,Curbox_y=Sys_y;/*x,y是保存方块的当前坐标的*/intflag_newbox=false;/*是否要产生新方块的标记0*/intspeed=0;/*下落速度*/intscore=0;/*总分*/intspeed_step=30;/*每等级所需要分数*/voidinterrupt(*oldtimer)(void);/*指向原来时钟中断处理过程入口的中断处理函数指针*/structBOARD/*游戏底板结构,表示每个点所具有的属性*/{intvar;/*当前状态只有0和1,1表示此点已被占用*/intcolor;/*颜色,游戏底板的每个点可以拥有不同的颜色.增强美观*/}Table_board[Vertical_boxs][Horizontal_boxs];/*方块结构*/structSHAPE{charbox[2];/*一个字节等于8位,每4位来表示一个方块的一行如:box[0]=0x88,box[1]=0xc0表示的是:1000100011000000*/intcolor;/*每个方块的颜色*/intnext;/*下个方块的编号*/};/*初始化方块内容.即定义MAX_BOX个SHAPE类型的结构数组,并初始化*/structSHAPEshapes[MAX_BOX]={/**口口口口口口口*口口口口口口*口口口*/{0x88,0xc0,CYAN,1},{0xe8,0x0,CYAN,2},{0xc4,0x40,CYAN,3},{0x2e,0x0,CYAN,0},/**口口口口口口*口口口口*口口口口口口*/{0x44,0xc0,MAGENTA,5},{0x8e,0x0,MAGENTA,6},{0xc8,0x80,MAGENTA,7},{0xe2,0x0,MAGENTA,4},/**口*口口口口*口口口*/{0x8c,0x40,YELLOW,9},{0x6c,0x0,YELLOW,8},/**口口口*口口口口*口*/{0x4c,0x80,BROWN,11},{0xc6,0x0,BROWN,10},/**口口口*口口口口口口口口口口*口口口*/{0x4e,0x0,WHITE,13},{0x8c,0x80,WHITE,14},{0xe4,0x0,WHITE,15},{0x4c,0x40,WHITE,12},/*口*口*口口口口口*口*/{0x88,0x88,RED,17},{0xf0,0x0,RED,16},/**口口*口口*/{0xcc,0x0,BLUE,18}};unsignedintTimerCounter=0;/*定时计数器变量*//*新的时钟中断处理函数*/voidinterruptnewtimer(void){(*oldtimer)();/*calltheoldroutine*/TimerCounter++;/*increasetheglobalcounter*/}/*设置新的时钟中断处理过程*/voidSetTimer(voidinterrupt(*IntProc)(void)){oldtimer=getvect(TIMER);/*获取中断号为TIMER的中断处理函数的入口地址*/disable();/*设置新的时钟中断处理过程时,禁止所有中断*/setvect(TIMER,IntProc);/*将中断号为TIMER的中断处理函数的入口地址改为IntProc()函数的入口地址即中断发生时,将调用IntProc()函数。*/enable();/*开启中断*/}/*恢复原有的时钟中断处理过程*/voidKillTimer(){disable();setvect(TIMER,oldtimer);enable();}voidshow_intro(intxs,intys){charstemp[50];setcolor(15);rectangle(xs,ys,xs+239,ys+100);sprintf(stemp,-Roll-Downwards);stemp[0]=24;stemp[8]=25;setcolor(14);outtextxy(xs+40,ys+30,stemp);sprintf(stemp,-TurnLeft-TurnRight);stemp[0]=27;stemp[13]=26;outtextxy(xs+40,ys+45,stemp);outtextxy(xs+40,ys+60,Esc-Exit);setcolor(FgColor);}/*显示分数*/voidShowScore(intscore){intx,y;charscore_str[5];/*保存游戏得分*/setfillstyle(SOLID_FILL,BgColor);x=LeftWin_x;y=100;bar(x-BSIZE,y,x+BSIZE*3,y+BSIZE*3);sprintf(score_str,%3d,score);outtextxy(x,y,SCORE);outtextxy(x,y+10,score_str);}/*显示速度*/voidShowSpeed(intspeed){intx,y;charspeed_str[5];/*保存速度值*/setfillstyle(SOLID_FILL,BgColor);x=LeftWin_x;y=150;bar(x-BSIZE,y,x+BSIZE*3,y+BSIZE*3);/*确定一个以(x1,y1)为左上角,(x2,y2)为右下角的矩形窗口,再按规定图模和颜色填充。*/sprintf(speed_str,%3d,speed+1);outtextxy(x,y,Level);outtextxy(x,y+10,speed_str);/*输出字符串指针speed_str所指的文本在规定的(x,y)位置*/outtextxy(x,y+50,Nextbox);}/**********初始化界面********参数说明:*x,y为左上角坐标*m,n对应于Vertical_boxs,Horizontal_boxs*分别表示纵横方向上方块的个数(以方块为单位)*BSIZESys_xSys_y**********************************/voidinitialize(intx,inty,intm,intn){inti,j,oldx;oldx=x;for(j=0;jn;j++){for(i=0;im;i++){Table_board[j][i].var=0;Table_board[j][i].color=BgColor;line(x,y,x+BSIZE,y);line(x,y,x,y+BSIZE);line(x,y+BSIZE,x+BSIZE,y+BSIZE);line(x+BSIZE,y,x+BSIZE,y+BSIZE);x+=BSIZE;}y+=BSIZE;x=oldx;}Curbox_x=x;Curbox_y=y;/*x,y是保存方块的当前坐标的*/flag_newbox=false;/*是否要产生新方块的标记0*/speed=0;/*下落速度*/score=0;/*总分*/ShowScore(score);ShowSpeed(speed);}/*删除一行满的情况*这里的y为具体哪一行为满*/intDelFullRow(inty){/*该行游戏板往下移一行*/intn,top=0;/*top保存的是当前最高点,出现一行全空就表示为最点了,移动是到最高点结束*/registerm,totoal;for(n=y;n=0;n--)/*从当前行往上看*/{totoal=0;for(m=0;mHorizontal_boxs;m++){if(!Table_board[n][m].var)totoal++;/*没占有方格+1*/if(Table_board[n][m].var!=Table_board[n-1][m].var)/*上行不等于下行就把上行传给下行xor关系*/{Table_board[n][m].var=Table_board[n-1][m].var;Table_board[n][m].color=Table_board[n-1][m].color;}}if(totoal==Horizontal_boxs)/*发现上面有连续的空行提前结束*/{top=n;break;}}return(top);/*返回最高点*/}/*找到一行满的情况*/voidsetFullRow(intt_boardy){intn,full_numb=0,top=0;/*top保存的是当前方块的最高点*/registerm;/*t_boardy口5口6口口口口口口7n口口口口口口8*/for(n=t_boardy+3;n=t_boardy;n--){if(n0||n=Vertical_boxs){continue;}/*超过低线了*/for(m=0;mHorizontal_boxs;m++)/*水平的方向*/{if(!Table_board[n+full_numb][m].var)break;/*发现有一个是空就跳过该行*/}if(m==Horizontal_boxs)/*找到满行了*/{if(n==t_boardy+3)/*第一次献给了n,最高的*/top=DelFullRow(n+full_numb);/*清除游戏板里的该行,并下移数据*/elseDelFullRow(n+full_numb);full_numb++;/*统计找到的行数*/}}if(full_numb){intoldx,x=Sys_x,y=BSIZE*top+Sys_y;oldx=x;score=score+full_numb*10;/*加分数*//*这里相当于重显调色板*/for(n=top;nt_boardy+4;n++){if(n=Vertical_boxs)continue;/*超过低线了*/for(m=0;mHorizontal_b