📄 tetris.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 + -