⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tetris.txt

📁 数据结构的源代码和配套讲义
💻 TXT
字号:
#include <stdio.h>

#include <stdlib.h>

#include <dos.h>

#include <malloc.h>

#include <memory.h>

#include <string.h>

#include <bios.h>

#include <math.h>

#define MAX_SPEED 11

#define MAX_LINE 30

#define random(num) (rand()%(num))

#define randomize() srand((unsigned)time(NULL))

typedef struct SQU_typ 

{int cur_num,cur_dir,x,y;}SQU;

SQU next_squ={0,0,254,55},this_squ={0,0,4,0};

char LINE[8],SCORE[8],SPEED[8];

long score;

int line,speed=0,line_nums=0,line_cnt=1,scr_cnt=0;

int back_arr[21][16]; //游戏背景数组

int mode[7][4][4][4]= //方块模板

{

1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,1,1,1,
0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,1,1,0,0,1,0,0,
0,0,0,0,0,0,0,0,0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,1,1,0,0,0,0,0,

0,0,0,0,1,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,

1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,

1,0,0,0,1,1,0,0,0,0,0,0,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,

1,1,0,0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,1,0,0,0,

0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,

1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0,

1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,1,1,0,1,1,0,0,

0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,1,1,0,0,1,1,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,1,1,0,0,1,1,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,

};

unsigned char IMAGE_BACK[64]; //底背景图案

unsigned char IMAGE_BOX[64]= //边框图案

{

1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,1,1,2,2,2,2,2,2,1,1,2,2,2,2,2,2,1,

1,2,2,2,2,2,2,1,1,2,2,2,2,2,2,1,1,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,

};

unsigned char IMAGE_SQU[64]= //方块图案

{

3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,3,3,0,4,4,4,4,0,3,3,0,4,4,4,4,0,3,

3,0,4,4,4,4,0,3,3,0,4,4,4,4,0,3,3,0,0,0,0,0,0,3,3,3,3,3,3,3,3,3,

};

#define TIMER_60HZ 0x4dae

#define TIMER_30HZ 0x965c

#define TIMER_20HZ 0xe90b


#define TIMER_18HZ 0xffff

#define LOW_BYTE(n) (n&0x00ff)

#define HI_BYTE(n) ((n>>8)&0x00ff)

unsigned far *clock=(unsigned far *)0x0000046c; //定时值指针

void chang_time(unsigned cnt) //重设定时器

{_outp(0x43,0x3c);outp(0x40,LOW_BYTE(cnt));_outp(0x40,HI_BYTE(cnt));}

void DELAY(int d) //延时

{int tm=*clock;while(*clock-tm<d);}

typedef struct RGB_color_typ

{unsigned char red,green,blue;}RGB_color,*RGB_color_ptr;

RGB_color PAL[6]={0,0,0,255,0,0,0,255,0,255,255,255,255,0,255,255,255,0};

void set_palette_register(int index,RGB_color_ptr pal) //重设颜色寄存器

{

_outp(0x3c6,0xff);_outp(0x3c8,index);

_outp(0x3c9,pal->red);_outp(0x3c9,pal->green);_outp(0x3c9,pal->blue);

}

#define KEY_ESC 0x01

#define KEY_UP 0x48

#define KEY_LEFT 0x4b

#define KEY_RIGHT 0x4d

#define KEY_DOWN 0x50

#define KEY_ENTER 0x1c

void (interrupt far *oldint9handler)(); //旧的INT 9中断程序指针

unsigned char key_state[128],key_pressed[128];

void far interrupt new_int9(void) //新的INT 9中断程序

{

unsigned char ScanCode,temp;ScanCode=_inp(0x60);temp=_inp(0x61);

_outp(0x61,temp | 0x80);_outp(0x61,temp & 0x7f);

if(ScanCode&0x80) {ScanCode&=0x7f;key_state[ScanCode]=0;}

else {key_state[ScanCode]=1;key_pressed[ScanCode]=1;} _outp(0x20,0x20);

}

void install_keyboard(void) //重设键盘中断

{

int i;for(i=0;i<128;i++) key_state[i]=key_pressed[i]=0;

oldint9handler=_dos_getvect(9);_dos_setvect(9,new_int9);

}

void shut_down_keyboard(void) //恢复旧的中断

{_dos_setvect(9,oldint9handler);}

int get_key(int ScanCode) //取按键状态

{

int res;res=key_state[ScanCode]|key_pressed[ScanCode];

key_pressed[ScanCode]=0;return res;

}

unsigned char far *video_buffer=(unsigned char far *)0xa0000000; //显存地址

unsigned char far *double_buffer; //双缓冲区指针

void set_video_mode(char m) //设置视频模式

{union REGS r;r.h.ah=0;r.h.al=m;int86(0x10,&r,&r);}

void draw_bitmap(int x,int y,int w,int h,unsigned char far *image) //画位图

{

int i;unsigned char far *temp_buf=double_buffer+(y<<6)+(y<<8)+x;

for(i=0;i<h;i++) {_fmemcpy(temp_buf,image,w);temp_buf+=320;image+=w;}

}

void creat_double_buffer(void) //创建双缓冲区

{double_buffer=(unsigned char far *)_fmalloc((unsigned)64000);}

void show_double_buffer(void) //显示双缓冲区内容

{_fmemcpy(video_buffer,double_buffer,(unsigned)64000);}

unsigned char far *rom_char_set=(unsigned char far *)0xf000fa6e;//ROM字符地址

void print_char(int cx,int cy,char c,int color,int trans_flag) //显示一个字符

{

int offset,x,y;char far *work_char;unsigned char bit_mask;

work_char=rom_char_set+(c<<3);offset=(cy<<8)+(cy<<6)+cx;

for(y=0;y<8;y++)

{

bit_mask=0x80;

for(x=0;x<8;x++)

{

if((*work_char&bit_mask)) *(double_buffer+offset+x)=color;

else if(trans_flag) *(double_buffer+offset+x)=0;

bit_mask=(bit_mask>>1);

}

offset+=320;work_char++;

}

}

void print_string(int x,int y,int color,char *string,int trans_flag)

{ //显示字符串

int index;

for(index=0;string[index]!=0;index++)

print_char(x+(index<<3),y,string[index],color,trans_flag);

}

void draw_back(void) //画背景图案

{

int x,y;

for(y=1;y<=19;y++)

for(x=2;x<=13;x++)

if(back_arr[y][x]==0)

draw_bitmap(112+((x-2)<<3),24+((y-1)<<3),8,8,IMAGE_BACK);

else draw_bitmap(112+((x-2)<<3),24+((y-1)<<3),8,8,IMAGE_SQU);

}

void draw_squ(void) //画方块图案

{


int x,y;

for(y=0;y<4;y++)

for(x=0;x<4;x++)

if(mode[this_squ.cur_num][this_squ.cur_dir][y][x]==1)

draw_bitmap(112+((this_squ.x+x)<<3),24+((this_squ.y+y)<<3),8,8,IMAGE_SQU);

}

void draw_next_squ(void) //画下一个方块图案

{


int x,y;

for(y=0;y<4;y++)

for(x=0;x<4;x++)

if(mode[next_squ.cur_num][next_squ.cur_dir][y][x]==1)

draw_bitmap(next_squ.x+(x<<3),next_squ.y+(y<<3),8,8,IMAGE_SQU);

else draw_bitmap(next_squ.x+(x<<3),next_squ.y+(y<<3),8,8,IMAGE_BACK);

}

int is_collided(int X,int Y) //判断方块是否遇到障碍

{

int x,y;

for(y=0;y<4;y++)

for(x=0;x<4;x++)

if(mode[this_squ.cur_num][this_squ.cur_dir][y][x]==1

&&back_arr[Y+y+1][X+x+2]!=0)

return 1;

return 0;

}

void squ_into_back(void) //将方块放入背景数组

{

int x,y;

for(y=0;y<4;y++)

for(x=0;x<4;x++)

if(mode[this_squ.cur_num][this_squ.cur_dir][y][x]==1)

back_arr[1+this_squ.y-1+y][2+this_squ.x+x]=1;

}

void print_num(void) //显示游戏得分等信息

{

ltoa(score,SCORE,10);itoa(line,LINE,10);itoa(speed,SPEED,10);

print_string(85-strlen(SCORE)*8,35,3,SCORE,1);

print_string(85-strlen(LINE)*8,52,3,LINE,1);

print_string(85-strlen(SPEED)*8,70,3,SPEED,1);

}

int is_line(void) //判断方块是否成行

{

int y=19,x,y2,s;

while(y>=1)

{

s=0;for(x=2;x<=13;x++) if(back_arr[y][x]>0) s+=1;

if(s==12)

{

line_nums++;

for(y2=y;y2>=1;y2--)

for(x=2;x<=13;x++)

{if(y2==1) back_arr[y2][x]=0; else back_arr[y2][x]=back_arr[y2-1][x];}

return 1;

}

else --y;

}

if(line_nums) //计分

{

switch(line_nums)

{

case 1:score+=100;break;case 2:score+=200;break;case 3:score+=800;break;

case 4:score+=1600;

}

line+=line_nums;

if(line>=line_cnt*MAX_LINE)

{++speed;++line_cnt;if(speed=MAX_SPEED) speed=MAX_SPEED-1;}

}

return 0;

}

void game_over(void) //游戏结束

{

print_string(124,96,35,"GAME OVER",1);show_double_buffer();

while(!get_key(KEY_ESC));

chang_time(TIMER_18HZ);shut_down_keyboard();set_video_mode(0x03);exit(0);

}

void init_game(void) //初始化游戏

{

int i,j;

set_video_mode(0x13);install_keyboard();chang_time(TIMER_18HZ);

creat_double_buffer();_fmemset(double_buffer,0,(unsigned)64000);

randomize();_fmemset(IMAGE_BACK,0,64);

for(i=0;i<21;i++) for(j=0;j<16;j++) back_arr[i][j]=-1;

for(i=1;i<20;i++) for(j=2;j<14;j++) back_arr[i][j]=0;

for(i=0;i<5;i++) set_palette_register(i,(RGB_color_ptr)&PAL[i]);

for(i=104;i<212;i+=8)

{draw_bitmap(i,16,8,8,IMAGE_BOX);draw_bitmap(i,176,8,8,IMAGE_BOX);}

for(i=24;i<176;i+=8)

{draw_bitmap(104,i,8,8,IMAGE_BOX);draw_bitmap(208,i,8,8,IMAGE_BOX);}

print_string(19,27,5,"SCORE",1);print_string(19,44,5,"LINE",1);

print_string(19,61,5,"SPEED",1);print_string(244,42,2,"NEXT",1);

next_squ.cur_num=random(7);next_squ.cur_dir=random(4);

this_squ.cur_num=next_squ.cur_num;this_squ.cur_dir=next_squ.cur_dir;

draw_next_squ();print_num();

}

void main(void)
{
init_game();

while(1)



{
draw_back();draw_squ();show_double_buffer();DELAY(2); //显示画面

if(get_key(KEY_ESC)) game_over();

else if(get_key(KEY_LEFT)) //方块左移

{if(!is_collided(this_squ.x-1,this_squ.y)) this_squ.x--;}

else if(get_key(KEY_RIGHT)) //方块右移

{if(!is_collided(this_squ.x+1,this_squ.y)) this_squ.x++;}

else if(get_key(KEY_UP)) //向右旋转方块


{

if(this_squ.cur_num>0)

{

if(this_squ.cur_dir==1||this_squ.cur_dir==3)

{

if(++this_squ.cur_dir>3) this_squ.cur_dir=0;

if(is_collided(this_squ.x,this_squ.y))

{

if(!is_collided(this_squ.x-1,this_squ.y)) --this_squ.x;

else if(--this_squ.cur_dir<0) this_squ.cur_dir=3;

}

}

else

{

if(++this_squ.cur_dir>3) this_squ.cur_dir=0;

if(is_collided(this_squ.x,this_squ.y))

if(--this_squ.cur_dir<0) this_squ.cur_dir=3;

}

}

else

{

if(++this_squ.cur_dir>3) this_squ.cur_dir=0;

if(is_collided(this_squ.x,this_squ.y))

if(--this_squ.cur_dir<0) this_squ.cur_dir=3;

}

}

else if(get_key(KEY_DOWN)) scr_cnt=MAX_SPEED; //方块下移

if(++scr_cnt>MAX_SPEED-speed)

{

scr_cnt=0;this_squ.y++;

if(is_collided(this_squ.x,this_squ.y))

{

squ_into_back();line_nums=0;while(is_line());this_squ.y=0;this_squ.x=4;

this_squ.cur_num=next_squ.cur_num;this_squ.cur_dir=next_squ.cur_dir;

next_squ.cur_num=random(7);next_squ.cur_dir=random(4);

draw_next_squ();print_num();

if(is_collided(this_squ.x,this_squ.y)) game_over();

}

}

}

}



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -