/* 程序名称: 俄罗斯方块 * 所用编译器: Turboc 2.0 * 作者:Killua * 学校:电子科技大学 * 专业班级:04级软件工程2班 * 版本:1.0 *//* 头文件 */#include<stdio.h>#include<conio.h>#include<stdlib.h>#include<time.h>#include<alloc.h>#include<dos.h>#include<graphics.h>/* ----------定义游戏中用到的常量-----------------*/#define BGI#define size 20/* 方块的边长 */#define TRUE 1#define FALSE 0#define ROWS 20 /* 游戏板的行数 */#define COLS 10 /* 游戏板的列数 */#define UP 0x48 /* 光标键上的扫描码 */#define DOWN 0X50 /* 光标键下的扫描码 */#define RIGHT 0x4d /* 光标键下的扫描码 */#define LEFT 0x4b /* 光标键左的扫描码 */#define ESC 0x01 /* ESC键的扫描码 */#define P 0x19 /* 键P的扫描码 */#define TIMER 0x1c /* 时间中断号 */#ifdef __cplusplus#define __CPPARGS ...#else#define __CPPARGS#endif/*-------------------------------------------------*//*--------------用到的全局变量---------------------*/int board[COLS][ROWS]; /* 20行10列的游戏板 */int x; /* 方块的在面板中的横坐标 */int y; /* 方块的在面板中的纵坐标 */int NO = 3; /* 初始方块序号 */int buf[4]; /* 存储要消掉的行数标号 */int TimerCounter; /* 计时器 */int speed = 1; /* 游戏速度 */int lines = 0; /* 玩家消掉的行数 */int scores = 0; /* 玩家得到分数 *//*-------------------------------------------------*//*--------------存储19种方块的图形数据-------------*/struct shape{ int xy[8]; int COLOR; int next; }shapes[19]= { /* 坐标系为: -1 0 1 2 x * -3 * -2 * -1 * 0 * y */ /* ■ * ■ * ■ * ■ */ {0,-3,0,-2,0,-1,0,0,GREEN,1}, /* ■ ■ ■ ■ */ {-1,-1,0,-1,1,-1,2,-1,GREEN,0}, /* ■ ■ * ■ ■ */ {0,-2,0,-1,1,-2,1,-1,LIGHTBLUE,2}, /* ■ * ■ * ■ ■ */ {0,-3,0,-2,0,-1,1,-1,LIGHTRED,4}, /* ■ ■ ■ * ■ */ {0,-1,0,-2,1,-2,2,-2,LIGHTRED,5}, /* ■ ■ * ■ * ■ */ {0,-2,1,-2,1,-1,1,0,LIGHTRED,6}, /* ■ * ■ ■ ■ */ {-1,-1,0,-1,1,-1,1,-2,LIGHTRED,3}, /* ■ * ■ ■ ■ */ {0,-2,-1,-1,0,-1,1,-1,LIGHTGREEN,8}, /* ■ * ■ ■ * ■ */ {0,-2,0,-1,0,0,1,-1,LIGHTGREEN,9}, /* ■ ■ ■ * ■ */ {-1,-1,0,-1,1,-1,0,0,LIGHTGREEN,10}, /* ■ * ■ ■ * ■ */ {0,-2,0,-1,0,0,-1,-1,LIGHTGREEN,7}, /* ■ ■ * ■ ■ */ {-1,-1,0,-1,0,-2,1,-2,YELLOW,12}, /* ■ * ■ ■ * ■ */ {0,-2,0,-1,1,-1,1,0,YELLOW,11}, /* ■ ■ * ■ ■ */ {-1,-2,0,-2,0,-1,1,-1,BROWN,14}, /* ■ * ■ ■ * ■ */ {0,-1,0,0,1,-2,1,-1,BROWN,13}, /* ■ * ■ * ■ ■ */ {0,-1,1,-3,1,-2,1,-1,LIGHTCYAN,16}, /* ■ * ■ ■ ■ */ {0,-2,0,-1,1,-1,2,-1,LIGHTCYAN,17}, /* ■ ■ * ■ * ■ */ {0,-2,0,-1,0,0,1,-2,LIGHTCYAN,18}, /* ■ ■ ■ * ■ */ {-1,-1,0,-1,1,-1,1,0,LIGHTCYAN,15} };/*-------------------------------------------------*//*--------------函数的声明-------------------------*/void init(); /* 初始化*/void init_graph(); /* 初始化图形 */void init_board(); /* 初始化界面 */void drawboard(); /* 画界面 */void draw(); /* 画出全部的界面包括文字 */void interrupt ( *oldhandler)(__CPPARGS); /* 系统中断函数 */void interrupt newhandler(__CPPARGS); /* 系统中断函数 */void interrupt newhandler(); /* 系统中断函数 */void show_sqr(int,int,int); /* 在游戏板中显示当前方块 */void show_next(int); /* 显示下一个方块 */int is_full(int); /* 判断是否有满的行 */void del_lines(int); /* 删除满的行 */void update_board(int); /* 更新游戏板的数据 */void update_image(int); /* 更新游戏板的图形 */void update(); /* 更新玩家的得分和消去的行数 */int move(int); /* 移动方块 */void play(); /* 玩函数*/int confilict(); /* 判断方块是否与游戏板的左右上下边界以及已经存在方块的地方发生冲突 */int get_speed(int,int); /* 当前的游戏速度 */int getkey(); /* 获得键盘扫描码 *//*-------------------------------------------------*//*--------------函数的详细定义---------------------*//*---------------------init_graph-------------------------------*/void init_graph(void){ int gdriver=DETECT,gmode; registerbgidriver(EGAVGA_driver); initgraph(&gdriver, &gmode, "c:\\turboc2");}/*----------------------------------------------------*//*-----------------drawboard--------------------------*/void drawboard() /* 画游戏板 */{ int space = 5; setfillstyle(XHATCH_FILL, YELLOW); bar(120, 50-space-1, 200, 50-1); bar(120, 130+1, 200, 130+space+1); bar(120-space-1, 50-space-1, 120-1, 130+space+1); bar(200+1, 50-space-1, 200+space+1,130+space+1); bar(320, 50-space-1, 520, 50-1); bar(320, 450+1, 520, 450+space+1); bar(320-space-1, 50-space-1, 320-1, 450+space+1); bar(520+1, 50-space-1, 520+space+1, 450+space+1);}/*----------------------------------------------------*//*------------------drawtext-------------------------*/void drawtext() /* 写一些提醒文字 */{ setcolor(RED); outtextxy(365,10,"Tetrics"); outtextxy(360,30,"---Programmed by Liu Chao"); outtextxy(110,30,"Preview Block:"); outtextxy(120,180,"Speed:"); outtextxy(120,210,"Score:"); outtextxy(120,240,"Lines:"); setcolor(GREEN); outtextxy(60,310,"Press \*ESC\* to exit..."); outtextxy(90,330,"or \*p\* to pause."); setcolor(BLUE); outtextxy(40,390,"Author: Liu Chao"); outtextxy(40,410,"Email:kangtalc@163.com"); outtextxy(40,430,"QQ:53408770"); outtextxy(40,450,"Software School of UESTC "); setcolor(GREEN);}/*----------------------------------------------------*//*------------------draw--------------------------*/void draw(){ drawboard(); drawtext();}/*---------------------------------------------------------*//*---------------------init_board--------------------------*/void init_board(){ int i,j; for (i=0; i<COLS; i++) for (j=0; j<ROWS; j++) board[i][j] = 0; for (i=0; i<4; i++) buf[i] = 0;}/*----------------------------------------------------*//*-------------------init----------------------------*/void init(){ clrscr(); init_board(); init_graph();}/*----------------------------------------------------*//*--------------------SetTimer--------------------------*/void SetTimer(void interrupt (*IntProc)(__CPPARGS)){ oldhandler=getvect(TIMER); disable(); setvect(TIMER,IntProc); enable();}/*-----------------KillTimer----------------------------*/void KillTimer(){ disable(); setvect(TIMER,oldhandler); enable();}/*----------------------------------------------------*//*----------------------------------------------------*/void interrupt newhandler(){ TimerCounter++; oldhandler();}/*----------------------------------------------------*//*------------------is_full----------------------------*/int is_full(int y){ int i,j; int line = 0; /* 初始化消去的行数为0 */ int full = TRUE; int *p = buf; for (i=y; i>=y-3; i--) { for (j=0; j<=9; j++) { if(board[j][i] == 0) full=FALSE; } if (full) { line++; /* 如果有行消去则line+1 */ *(p++) = i; /* 存储要消去的行标识 */ } else full = TRUE; } if (line) /* 根据一次消去的行数得不同的得分*/ { lines += line; switch (line) { case 1:scores+=20;break; case 2:scores+=50;break; case 3:scores+=90;break; case 4:scores+=140; } return line; } return FALSE;}/*----------------------------------------------------*//*-------------------update_board-----------------------*/void update_board(int line) /* 更改面板的数据,使面板数据依次想下移动 */{ int i; int n; int full_y; int scan_y; for (i=line-1; i>=0; i--) { full_y = buf[i]; for (n=0; n<10; n++) board[n][full_y] = 0; for (n=0;n<10;n++) for (scan_y=full_y-1; scan_y>=0; scan_y--) if (board[n][scan_y] == 0) continue; else { board[n][scan_y] = 0; board[n][scan_y+1] = 1; } }}/*----------------------------------------------------*//*------------------update_image----------------------*/void update_image(int line) /* 更改游戏板的图象,消去满了的行 */{ int i,del_y; unsigned line_size; void *del_image = NULL; void *left_image = NULL; line_size = imagesize(320,50,520,70); for (i=line-1; i>=0; i--) { del_y = buf[i]; del_image = malloc(line_size); left_image = malloc(line_size*del_y); if((del_image==NULL) || (left_image==NULL)) { closegraph(); printf("not enough memory./n"); exit(1); } getimage(320, del_y*size+50, 520, 50+(del_y+1)*size, del_image); getimage(320, 50, 520, 50+del_y*size, left_image); putimage(320, del_y*size+50, del_image, XOR_PUT); putimage(320, 70, left_image, COPY_PUT); free(del_image); free(left_image); }}/*----------------------------------------------------*//*------------------del_lines------------------------*/void del_lines(int line) /* 删掉满的行 */{ update_board(line); update_image(line);}/*---------------------------------------------------------*//*-----------------show_sqr-----------------------------*/void show_sqr(int x,int y,int NO) /* 画出当前的图形 */{ int realx,realy,i; for (i=0; i<=7; i+=2) { realx = (x+shapes[NO].xy[i])*size+320; /* 取得真实的横坐标 */ realy=(y+shapes[NO].xy[i+1])*size+50; /* 取得真实的纵坐标 */ bar(realx+1,realy+1,realx+size-1,realy+size-1); }}/*----------------------------------------------------*//*-------------------show_next-----------------------*/void show_next(int NO) /* 画出下一个图形 */{ int realx,realy,i; for (i=0; i<=7; i+=2) { realx = (1+shapes[NO].xy[i])*size+120; /* 取得真实的横坐标 */ realy=(3+shapes[NO].xy[i+1])*size+50; /* 取得真实的纵坐标 */ bar(realx+1,realy+1,realx+size-1,realy+size-1); }}/*----------------------------------------------------*//*--------------------update---------------------------*/void update() /* 更新玩家的得分,游戏速度和消去的行数 */{ char *str=NULL; struct viewporttype vp; getviewsettings(&vp); setviewport(120+textwidth("SPEED:"), 150, 120+textwidth("SPEED:OO") + 40, 250,1); clearviewport(); setcolor(GREEN); sprintf(str,"%d",speed); outtextxy(4,30,str); sprintf(str,"%d",scores); outtextxy(4,60,str); sprintf(str,"%d",lines); outtextxy(4,90,str); setviewport(vp.top,vp.left,vp.right,vp.bottom,1);}/*----------------------------------------------------*//*------------------get_speed----------------------------*/int get_speed(int scores,int lines) /* 根据玩家的分数和消去的行数变更速度 */{ if(scores>5000||lines>200)return 6; if(scores>4000||lines>180)return 5; if(scores>3000||lines>120)return 4; if(scores>2000||lines>80)return 3; if(scores>1000||lines>40)return 2; return 1;}/*----------------------------------------------------*//*--------------------getkey-------------------------*/int getkey() /* 返回键盘扫描码 */{ union REGS r; r.h.ah=0; int86(0x16,&r,&r); return r.h.ah;}/*----------------------------------------------------*//*---------------------confilict---------------------*/int confilict(int x,int y,int NO) /* 看方块是否与游戏板的内容不冲突 */{ int i; for(i=0; i<=7; i+=2) { if((shapes[NO].xy[i]+x<0) || (shapes[NO].xy[i]+x>9)) /* 与游戏板左右边界冲突 */ return TRUE; if(shapes[NO].xy[i+1]+y > 19) /* 与游戏板的下边界冲突 */ return TRUE; if(board[shapes[NO].xy[i]+x][shapes[NO].xy[i+1]+y]) /* 与游戏版内已经存在方块的地方冲突 */ return TRUE; } return FALSE;}/*----------------------------------------------------*//*-------------------move----------------------------*/int move(int direction) /* 移动方块的函数 */{ switch (direction){ case RIGHT: /* 方块向右移动 */ if( !confilict(x+1, y, NO) ) { setfillstyle(SOLID_FILL, BLACK); show_sqr(x, y, NO); delay(100); ++x; setfillstyle(SOLID_FILL, shapes[NO].COLOR); show_sqr(x, y, NO); } break; case LEFT : /* 方块向左移动 */ if( !confilict(x-1 , y, NO) ) { setfillstyle(SOLID_FILL, BLACK); show_sqr(x, y, NO); delay(100); --x; setfillstyle(SOLID_FILL, shapes[NO].COLOR); show_sqr(x, y, NO); } break; case DOWN : /* 方块向下移动 */ if( !confilict(x, y+1, NO) ) { setfillstyle(SOLID_FILL, BLACK); show_sqr(x, y, NO); delay(100); ++y; setfillstyle(SOLID_FILL, shapes[NO].COLOR); show_sqr(x, y, NO); break; } else return 0; case UP: /* 改变方块到下一个形态*/ if( !confilict(x, y, shapes[NO].next) ) { setfillstyle(SOLID_FILL, BLACK); show_sqr(x, y, NO); NO = shapes[NO].next; setfillstyle(SOLID_FILL, shapes[NO].COLOR); show_sqr(x, y, NO); } break; case P: getch(); break; case ESC : closegraph(); exit(0); }}/*----------------------------------------------------*//*------------------play----------------------------*/void play(){ int direction; int n; int i; int line=0; int over=FALSE; draw(); update(); SetTimer(newhandler); while (!over) { x=4; y=3; setfillstyle(SOLID_FILL, shapes[NO].COLOR); speed = get_speed(scores,lines); show_sqr(x, y, NO); /*显示当前的图形*/ srand(time(NULL)); n=rand()%19; setfillstyle(SOLID_FILL, shapes[n].COLOR); show_next(n); /*随机的产生图形并且显示*/ while (1) { mm: while(!kbhit()) /*如果没有敲键盘*/ { if(TimerCounter>16-get_speed(scores,lines)&&!confilict(x,y+1,NO))/* 如果在时间超过方块的停留时间就自动下落,并且判断下落会不会发生冲突,如果不会发生冲突的话就下落*/ { TimerCounter=0; move(DOWN); } else if(confilict(x,y+1,NO)) /* 如果这个时候下落会冲突的话就跳到ep */ goto ep; } direction=getkey(); /* 如果有接受键盘信息 */ move(direction); /* 就执行键盘的行动 */ if (TimerCounter<16-get_speed(scores,lines)) goto mm; /* 此时的时间还是小于方块的时间间隔依然就跳转到mm*/ if (TimerCounter>16-get_speed(scores,lines) && !confilict(x,y+1,NO))/* 此时的时间大于方块的跳转时间并且下移不发生冲突就下移*/ { TimerCounter=0; move(DOWN); } ep: if(!move(DOWN)) /* 如果不能够向下移动 */ { for(i=0;i<=7;i+=2) board[x+shapes[NO].xy[i]][y+shapes[NO].xy[i+1]]=1;/*将方块占据的空间置为1*/ NO=n; setfillstyle(SOLID_FILL, BLACK); show_next(NO); /*消去随机产生的方块 */ if ((line=is_full(y))!= 0) /*如果有消去的行就消去*/ { update(); del_lines(line); } break; } } for(i=0;i<10;i++) if(board[i][0]) over=TRUE; /*检查游戏是否结束*/ }moveto(280,200);setcolor(GREEN);outtext("GameOver!");getch();}/*----------------------------------------------------*//*--------------------main---------------------------*/int main(){ init(); play(); KillTimer(); closegraph(); return 0;}/*----------------------------------------------------*/
引用第10楼newton于2006-08-15 23:29发表的:对了。.学校不是"成都电子科大"
引用第13楼kangtalc于2006-08-15 23:34发表的:那是???