第1个回答 2009-05-11
自己倒是写过一个.400多行.不过注释都是写的英文,而且是很早以前写的.不好看,比前面那位兄台的好处在于是图形界面的,(* ̄▽ ̄*).......
/***************************************
TETRIS
by chichujn
version 1.1
start at 2008.01.18
finish at 2008.01.24
modify at 2008.02.27
***************************************/
/* Head Files */
#include <stdio.h>
#include <bios.h>
#include <stdlib.h>
#include <graphics.h>
/*Struct of block*/
/**************************************
Shape of block:
The block is put in 4x4 area
First row, bit 31-28;
Second row, bit 27-24...
Postion of block:
bit 15-8, bottom
bit 7-4, wide
bit 3-0, left
**************************************/
long all[19];
/***************************************
□□□□ □□□□ □□□□ □□□□ □□□□ □□□□ □□□□ □□□□ □□□□
□□□□ □□□□ □■□□ □□□□ ■□□□ □□□□ ■■□□ □□□□ □■□□
■■□□ ■■□□ ■■□□ □■■□ ■■□□ ■□□□ ■□□□ ■■■□ □■□□
■■□□ □■■□ ■□□□ ■■□□ □■□□ ■■■□ ■□□□ □□■□ ■■□□
□□□□ □□□□ □□□□ □□□□ □□□□ □□□□ □□□□ □□□□ □□□□ ■□□□
□□□□ ■□□□ □□□□ ■■□□ □□□□ ■□□□ □□□□ □■□□ □□□□ ■□□□
□□■□ ■□□□ ■■■□ □■□□ □■□□ ■■□□ ■■■□ ■■□□ □□□□ ■□□□
■■■□ ■■□□ ■□□□ □■□□ ■■■□ ■□□□ □■□□ □■□□ ■■■■ ■□□□
***************************************/
int screen[25];
/*Record the fixed blocks*/
/********************************
screen[n]
bit 9-0
********************************/
/* Function Welcome */
void Welcome(void)
{
gotoxy(37,10);
printf("TETRIS");
gotoxy(1,19);
printf("Version :1.1\nProgramBy:chichujn\n\nKEY: q-Quit; w-Rotate ; a-Left; d-Right; s-Speedup.\n\n");
printf("Press any key to start...");
getch();
}
/* Function Data_Init */
void Data_Init(void)
{
int i;
all[0]=0x00CC0014;
all[1]=0x00C60024;
all[2]=0x04C80014;
all[3]=0x006C0024;
all[4]=0x08C40014;
all[5]=0x008E0024;
all[6]=0x0C880014;
all[7]=0x00E20024;
all[8]=0x044C0014;
all[9]=0x002E0024;
all[10]=0x088C0014;
all[11]=0x00E80024;
all[12]=0x0C440014;
all[13]=0x004E0024;
all[14]=0x08C80014;
all[15]=0x00E40024;
all[16]=0x04C40014;
all[17]=0x000F0034;
all[18]=0x88880004;
for(i=0;i<25;++i)
screen[i]=0;
}
/* Function Block_Init */
long Block_Init()
{
randomize();
return(all[random(19)]);
}
/* Function Block_Position */
/***********************************
Return position param of the block
n=0,bottom
n=1,left
n=2,right
************************************/
int Block_Position(long block,int n)
{
if(n==0)
return( (int)block>>8 );
if(n==1)
return( (int)block&0x000F );
if(n==2)
return( ((int)block&0x000F) + ( ((int)block>>4)&0x000F ) );
}
/* Function Diplay */
/**************************************
Display the blocks.
Postion:
16,16;32,16;48,16...
16,32;32,32;48,32...
Width of the blocks:
14 pixels
Color:
White
**************************************/
void Display(long block)
{
int i,j;
int bottom;
int left;
bottom=Block_Position(block,0);
left=Block_Position(block,1);
for(i=0;i<25;++i)
for(j=0;j<10;++j)
{
if(( (screen[i]>>(9-j))&0x0001 )==0)
setfillstyle(SOLID_FILL,BLACK);
else
setfillstyle(SOLID_FILL,WHITE);
bar( (j+1)*16, (i+1)*16, (j+1)*16+14, (i+1)*16+14 );
}
setfillstyle(SOLID_FILL,WHITE);
for(i=0;i<16;++i)
if( ( ((block>>(31-i))&0x0001)==1 ) && ((bottom-3+i/4)>=0) )
bar( (left+i%4+1)*16, (bottom+i/4-3+1)*16, (left+i%4+1)*16+14, (bottom+i/4-3+1)*16+14 );
}
/* Function delay */
void delay(int n)
{
long t1,t2;
t1=t2=biostime(0,0);
while(t2-t1<n)
t2=biostime(0,0);
}
/* Function Block_Rotate */
long Block_Rotate(long block)
{
int n;
long tmp;
tmp=block;
switch( (int)(block>>16) )
{
case 0x00C6:tmp=0x04C80000+(tmp&0x0000FFFF);break;
case 0x04C8:tmp=0x00C60000+(tmp&0x0000FFFF);break;
case 0x006C:tmp=0x08C40000+(tmp&0x0000FFFF);break;
case 0x08C4:tmp=0x006C0000+(tmp&0x0000FFFF);break;
case 0x008E:tmp=0x0C880000+(tmp&0x0000FFFF);break;
case 0x0C88:tmp=0x00E20000+(tmp&0x0000FFFF);break;
case 0x00E2:tmp=0x044C0000+(tmp&0x0000FFFF);break;
case 0x044C:tmp=0x008E0000+(tmp&0x0000FFFF);break;
case 0x002E:tmp=0x088C0000+(tmp&0x0000FFFF);break;
case 0x088C:tmp=0x00E80000+(tmp&0x0000FFFF);break;
case 0x00E8:tmp=0x0C440000+(tmp&0x0000FFFF);break;
case 0x0C44:tmp=0x002E0000+(tmp&0x0000FFFF);break;
case 0x000F:tmp=0x88880000+(tmp&0x0000FFFF);break;
case 0x8888:tmp=0x000F0000+(tmp&0x0000FFFF);break;
case 0x004E:tmp=0x08C80000+(tmp&0x0000FFFF);break;
case 0x08C8:tmp=0x00E40000+(tmp&0x0000FFFF);break;
case 0x00E4:tmp=0x04C40000+(tmp&0x0000FFFF);break;
case 0x04C4:tmp=0x004E0000+(tmp&0x0000FFFF);break;
default:return(block);
}
n=(int)(block>>4)&0x000F;
if(n==0)
tmp+=0x0030;
if(n==1)
tmp+=0x0010;
if(n==2)
tmp-=0x0010;
if(n==3)
tmp-=0x0030;
if(Block_Check(tmp))
return(block);
return(tmp);
}
/* Function Block_Check */
/***********************************
Check the status of the block
return 0:Not out of edge and no crash
return 1:Out of edge
return 2:Crash with other blocks
***********************************/
int Block_Check(long block)
{
int i;
int bottom;
int left;
int right;
bottom=Block_Position(block,0);
left=Block_Position(block,1);
right=Block_Position(block,2);
if(left==0x000F||right>9||bottom>24)
return(1);
for(i=0;i<16;++i)
if( ((block>>(31-i))&1) && ( (screen[bottom-3+i/4]>>(9-left-i%4) ) &1 ) )
return(2);
return(0);
}
/* Function Block_Move */
/***********************************
Move the block
n=0:down
n=1:left
n=2:right
***********************************/
long Block_Move(long block,int n)
{
long tmp;
tmp=block;
if(n==0)
tmp+=0x0100;
if(n==1)
tmp-=0x0001;
if(n==2)
tmp+=0x0001;
if(Block_Check(tmp))
return(block);
return(tmp);
}
/* Function Screen_Refresh */
/***********************************
If the block touchs the bottom or crashes with other blocks.
Fresh the screen.
***********************************/
int Screen_Refresh(long block)
{
int i,j;
int score;
int left;
int bottom;
int tmp;
bottom=Block_Position(block,0);
left=Block_Position(block,1);
score=0;
for(i=0;i<16;++i)
if( ((block>>(31-i))&0x0001)==1 && ((((int)block>>8)&0x00FF)-i/4)<0 )
return(-1);
tmp=left>6?( ( (block>>28) &0x000F) >> (left-6) ):( ( (block>>28) &0x000F) << (6-left) );
screen[bottom-3]=screen[bottom-3]|tmp;
tmp=left>6?( ( (block>>24) &0x000F) >> (left-6) ):( ( (block>>24) &0x000F) << (6-left) );
screen[bottom-2]=screen[bottom-2]|tmp;
tmp=left>6?( ( (block>>20) &0x000F) >> (left-6) ):( ( (block>>20) &0x000F) << (6-left) );
screen[bottom-1]=screen[bottom-1]|tmp;
tmp=left>6?( ( (block>>16) &0x000F) >> (left-6) ):( ( (block>>16) &0x000F) << (6-left) );
screen[bottom]=screen[bottom]|tmp;
for(i=0;i<25;++i)
if(screen[i]==0x03FF)
{
score++;
for(j=i;j>0;--j)
screen[j]=screen[j-1];
}
return(score);
}
/* Function Block_Next */
/**********************************
Display the next block
**********************************/
void Block_Next(long next)
{
int i;
int bottom;
setfillstyle(SOLID_FILL,BLACK);
bar(306,98,328,120);
setfillstyle(SOLID_FILL,WHITE);
bottom=Block_Position(next,0);
for(i=0;i<16;++i)
if((next>>(31-i))&1)
bar( (i%4+1)*6+300, (bottom+i/4-3+1)*6+110, (i%4+1)*6+304, (bottom+i/4-3+1)*6+114 );
}
/* Function Graph_Text */
/*********************************
In graph mode,put a number on screen
position:left,bottom
number:n
*********************************/
void Graph_Text(int left,int bottom,int n,int color)
{
char *ch;
itoa(n,ch,10);
setcolor(color);
outtextxy(left,bottom,ch);
}
/* Function Game */
int Game()
{
long block;
long block_tmp;
long next;
int i;
int tmp;
int t;
int speed_tmp;
int Game_Speed;
int Game_Score;
char key;
char* score;
char* speed;
Game_Score=0;
Game_Speed=speed_tmp=1;
t=0;
block=Block_Init();
Display(block);
setcolor(WHITE);
settextstyle(4,0,3);
outtextxy(250,50,"Score:");
outtextxy(250,80,"SPeed:");
outtextxy(250,110,"Next :");
rectangle(14,14,176,416);
Graph_Text(300,50,Game_Score,WHITE);
Graph_Text(300,80,Game_Speed,WHITE);
next=Block_Init();
Block_Next(next);
while(1)
{
if(bioskey(1)!=0)
{
key=getch();
if(key=='q'||key=='Q')
break;
if(key=='s'||key=='S')
speed_tmp=10;
else
speed_tmp=Game_Speed;
}
delay(1);
++t;
if(t==30000)
t=0;
if(t%(11-speed_tmp)==0)
{
block_tmp=block;
block=Block_Move(block,0);
if(block_tmp==block)
{
tmp=Game_Score;
Graph_Text(300,50,Game_Score,BLACK);
Game_Score+=Screen_Refresh(block);
if(Game_Score<tmp)
return(tmp);
Graph_Text(300,50,Game_Score,WHITE);
if(Game_Score>tmp&&Game_Score%20==0&&Game_Speed<10&&Game_Score>0)
{
Graph_Text(300,80,Game_Speed,BLACK);
Game_Speed++;
Graph_Text(300,80,Game_Speed,WHITE);
}
block=next;
next=Block_Init();
Block_Next(next);
speed_tmp=Game_Speed;
}
Display(block);
}
if(key=='A'||key=='a'||key=='D'||key=='d'||key=='W'||key=='w')
{
if(key=='A'||key=='a')
block=Block_Move(block,1);
if(key=='D'||key=='d')
block=Block_Move(block,2);
if(key=='W'||key=='w')
block=Block_Rotate(block);
key='m';
Display(block);
}
}
return(Game_Score);
}
/* Function Main */
int main()
{
int gd=DETECT,gm;
int score;
Welcome();
Data_Init();
initgraph(&gd,&gm,"");
registerbgidriver(EGAVGA_driver);
score=Game();
closegraph();
gotoxy(35,12);
printf("Game Over");
gotoxy(1,23);
printf("Your score:%d\nPress any key to quit...",score);
getch();
}