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

📄 tetris.c

📁 这是一个用128*64液晶显示的俄罗斯方块游戏
💻 C
字号:


void box_build()
{
	s_box.mode=next_mode;
	s_box.shape=next_shape;
	s_box.x=3;
	s_box.y=0;
	next_mode=TL0%7;//产生随机数,但是是伪随机的
	next_shape=TL0%4;//产生随机数,但是是伪随机的
	show_next_box();//放到game_execute()函数中不知道为什么就是不正常显示
}//方块生成函数


unsigned int box_read_data(unsigned char tpmode,unsigned char tpshape)
{
	unsigned int tpbox;
	switch(tpmode)
	{
		case 0: switch(tpshape)
				{
					case 0: tpbox=0xf000;break;
					case 1: tpbox=0x4444;break;
					case 2: tpbox=0xf000;break;
					case 3: tpbox=0x4444;break;
					default:;
				}break;	
		case 1: switch(tpshape)
				{
					case 0: tpbox=0xe800;break;
					case 1: tpbox=0xc440;break;
					case 2: tpbox=0x2e00;break;
					case 3: tpbox=0x88c0;break;
					default:;
				}break;	
		case 2: switch(tpshape)
				{
					case 0: tpbox=0xe200;break;
					case 1: tpbox=0x44c0;break;
					case 2: tpbox=0x8e00;break;
					case 3: tpbox=0xc880;break;
					default:;
				}break;	
		case 3: switch(tpshape)
				{
					case 0: tpbox=0xcc00;break;
					case 1: tpbox=0xcc00;break;
					case 2: tpbox=0xcc00;break;
					case 3: tpbox=0xcc00;break;
					default:;
				}break;	
		case 4: switch(tpshape)
				{
					case 0: tpbox=0xc600;break;
					case 1: tpbox=0x4c80;break;
					case 2: tpbox=0xc600;break;
					case 3: tpbox=0x4c80;break;
					default:;
				}break;	
		case 5: switch(tpshape)
				{
					case 0: tpbox=0x6c00;break;
					case 1: tpbox=0x8c40;break;
					case 2: tpbox=0x6c00;break;
					case 3: tpbox=0x8c40;break;
					default:;
				}break;
		case 6: switch(tpshape)
				{
					case 0: tpbox=0x4e00;break;
					case 1: tpbox=0x8c80;break;
					case 2: tpbox=0xe400;break;
					case 3: tpbox=0x4c40;break;
					default:;
				}break;
		default:;
	}
	return(tpbox);
}//方块缓存数据函数(输入方块类型和形状即可获得方块缓存数据)

void box_load()
{
	s_box.box=box_read_data(s_box.mode,s_box.shape);
}//方块载入函数


void box_to_Box_Ram(unsigned char tpx,unsigned char tpy,unsigned int tpbox)
{
	unsigned char i;
	unsigned int temp;
	temp=tpbox;
	for(i=0;i<4;i++)
	{
		Box_Ram[3-i+tpy]=Box_Ram[3-i+tpy]&(~((temp&0x000f)<<(9-tpx))); 
		temp=temp>>4;
	}//从游戏点阵缓存中删除以前的方块
	temp=s_box.box;
	for(i=0;i<4;i++)
	{
		Box_Ram[3-i+s_box.y]=((temp&0x000f)<<(9-s_box.x))|Box_Ram[3-i+s_box.y];
		temp=temp>>4;
	}//在游戏点阵缓存中加入新的方块
}//方块映射游戏点阵缓存函数(参数是原来方块的位置、缓存,先消去原有位置的方块)

void Tetris_main()
{
	unsigned char i;
	for(i=0;i<19;i++)
	{
		Box_Ram[i]=Box_Ram_data[i];
	};//载入游戏初始显示画面
	game_over_flag=0;//游戏结束标志位置0表示游戏未结束
	box_build();
	box_load();
//	next_box();

	box_to_Box_Ram(s_box.x,s_box.y,s_box.box);
	box_down_reg=(20-(speed_num<<1)-1);//为了使方块一出现就能变换形状,所以需要尽快使得方块下降一行,不知道为什么最高行不能变换形状
	time0_initialize();
	while(!game_over_flag)//如果游戏结束标志位置1,表示游戏结束,打破循环,调用游戏结束画面显示函数
	{
		game_button();
	}
	EA=0;//游戏结束后关中断
}//俄罗斯方块游戏主函数

void time0_initialize()
{
	TMOD=0x03;//定时器0,16位工作方式
	TR0=1; //启动定时器
	ET0=1; //打开定时器0中断
			//默认中断优先级为低
	EA=1; //打开总中断
}//定时器0初始化函数

void timer0() interrupt 1
{
	TH0=0x00;
	TL0=0x00;
	if(time0_reg<10)
	{				  
		time0_reg++;
	}
	else
	{
		time0_reg=0;
		if(pause_game_flag==0)
		{
			game_execute();
			refurbish_display();
		}
	}
	
}//定时器0中断服务


bit check_cover(unsigned char tpx,unsigned char tpy,unsigned int tpbox)
{
	unsigned char i;
	bit tpflag=1;
	unsigned int temp;
	temp=s_box.box;
	for(i=0;i<4;i++)
	{
		Box_Ram[3-i+s_box.y]&=(~((temp&0x000f)<<(9-s_box.x))); 
		temp=temp>>4;
	}//先将现有的方块从游戏点阵缓存中删除
	temp=tpbox;
	for(i=0;i<4;i++)
	{
		if((((temp&0x000f)<<(9-tpx))&Box_Ram[3-i+tpy])!=0x0000)
		{
			tpflag=0;
		}
		temp=temp>>4;
	}//检查方块是否和原有图形重叠,重叠置标志位tpflag为0,不重叠不置标志位,即tpflag为1
	temp=s_box.box;
	for(i=0;i<4;i++)
	{
		Box_Ram[3-i+s_box.y]|=((temp&0x000f)<<(9-s_box.x));
		temp=temp>>4;
	}//在游戏点阵缓存中恢复原有方块
	return(tpflag);
}//检查覆盖函数(检查此时带入的参数所确定的方块是否会覆盖原有图形,不会覆盖返回1,覆盖返回0)
   


void destroy_row()
{
	unsigned char i,j=0;
	unsigned char tpflag[4]={0,0,0,0};//最多一次只能消四行,所以设置四个标志位即可,初值为0
	for(i=0;i<16;i++)
	{
		if((Box_Ram[i]&0x3ffc)==0x3ffc)
		{
			tpflag[j]=i+1;//tpflag为0表示不标志,1表示第0行缓存为0xffff,n表示第n+1行缓存为0xffff
			destroy_row_num++;//消除的行数加一
			/*如不把Box_Ram[19]定义成idata类型的话加入这段代码显示数据区就溢出了*/
			if(destroy_row_num%30==0&&speed_num!=9)
			{
				speed_num++;//消够三十行游戏速度加一
				show_speed_num(13,4);//调用显示游戏速度函数
			}
			/*如不把Box_Ram[19]定义成idata类型的话加入这段代码显示数据区就溢出了*/
			j++;
			if(j==4)
			{
				break;
			}//检查完有四行要消除则退出检查循环
		}

	}//依次检测是否有行缓存为0xffff,如果是则标志tpflag为此行的行号
	for(j=0;j<4;j++)
	{
		if(tpflag[j]!=0)
		{
			for(i=tpflag[j]-1;i>0;i--)
			{
			Box_Ram[i]=Box_Ram[i-1];
			Box_Ram[0]=0x2004;
			}
		}
	}//被标志的行依次被上一行所取代,即被消去
	show_score_num(3,1);
}//消行函数

void show_next_box()
{
	unsigned char i,tpdata;
	unsigned int temp;
	temp=box_read_data(next_mode,next_shape);
	for(i=0;i<4;i++)
	{
		tpdata=0x00;
		if(  ((temp>>(15-i))&0x0001)==1  )
		{
			tpdata=0x0f;
		}
		if(  ((temp>>(11-i))&0x0001)==1  )
		{
			tpdata|=0xf0;
		}
		LCD_display_byte(7+i*4,6,tpdata);
		LCD_display_byte(8+i*4,6,0xbb&tpdata);
		LCD_display_byte(9+i*4,6,0xdd&tpdata);
		LCD_display_byte(10+i*4,6,tpdata);	
		tpdata=0x00;
		if(  ((temp>>(7-i))&0x0001)==1  )
		{
			tpdata=0x0f;
		}
		if(  ((temp>>(3-i))&0x0001)==1  )
		{
			tpdata|=0xf0;
		}
		LCD_display_byte(7+i*4,7,tpdata);
		LCD_display_byte(8+i*4,7,0xbb&tpdata);
		LCD_display_byte(9+i*4,7,0xdd&tpdata);
		LCD_display_byte(10+i*4,7,tpdata);		
	}
	
}//显示下一个方块函数


bit check_game_over()
{
	unsigned char i;
	bit tpflag=0;
	unsigned int temp;
	temp=s_box.box;
	for(i=0;i<4;i++)
	{
		if((((temp&0x000f)<<(9-s_box.x))&Box_Ram[3-i+s_box.y])!=0x0000)
		{
			tpflag=1;
		}
		temp=temp>>4;
	}//检查新建方块是否和原有图形重叠,重叠置标志位tpflag为1,不重叠不置标志位,即tpflag为0
	return(tpflag);
}//检查游戏结束函数(游戏结束返回1,游戏没有结束返回0)


void game_execute()
{
	if(box_down_reg<20-(speed_num<<1))
	{				  
		box_down_reg++;
	}
	else
	{
		box_down_reg=0;
		if(check_cover(s_box.x,s_box.y+1,s_box.box))
		{
			s_box.y++;
			box_to_Box_Ram(s_box.x,s_box.y-1,s_box.box);
		}//检测是否还可以下降,如果还能下降则继续下降
		else
		{
			destroy_row();
			box_build();
			box_load();
			game_over_flag=check_game_over();//游戏结束标志位置1表示游戏结束
			box_to_Box_Ram(s_box.x,s_box.y,s_box.box);
			box_down_reg=(20-(speed_num<<1)-1);//为了使方块一出现就能变换形状,所以需要尽快使得方块下降一行,不知道为什么最高行不能变换形状
		}//如果不能下降则调用消行函数检查是否可以消行,之后重新建立方块
	}	
}//游戏执行函数(控制方块下落,检测是否到底,如果到底调用消行函数)

void show_num(unsigned char x,
					  unsigned char y,
					  unsigned char tpdata)
{
	unsigned char i;
	for(i=0;i<4;i++)
	{
		LCD_display_byte(x+i,y,num_data[tpdata*4+i]);	
	}
} //显示数字函数(
  //x表示x坐标,
  //y表示y坐标,
  //tpdata表示要显示的数字)
void show_score_num(unsigned char x,unsigned char y)
{
	show_num(x,y,destroy_row_num/10000);
	show_num(x+=5,y,(destroy_row_num%10000)/1000);
	show_num(x+=5,y,(destroy_row_num%1000)/100);
	show_num(x+=5,y,(destroy_row_num%100)/10);
	show_num(x+=5,y,destroy_row_num%10);
}//显示得分函数


void show_speed_num(unsigned char x,unsigned char y)
{
	show_num(x,y,speed_num);
}//显示速度函数


void game_start_show()
{
	bit tpflag=1;//置循环标志位为1
	LCD_full_draw(start_pic);
	while(tpflag)
	{
		switch(basic_button())
		{
			case 3: tpflag=0;
					while(button_a==0);
					break;
			default:;
		}
	}//game_start_show循环
}//游戏开始显示画面


void select_speed()
{
	unsigned char i;
	bit tpflag=1;//置循环标志位为1
	LCD_clear();
	for(i=0;i<128;i++)
	{
		LCD_display_byte(i,0,0xff);
		LCD_display_byte(i,7,0xff);
	}
	LCD_display_byte(60,4,0x7f);
	LCD_display_byte(59,4,0x3e);
	LCD_display_byte(58,4,0x1c);
	LCD_display_byte(57,4,0x08);
	LCD_display_byte(67,4,0x7f);
	LCD_display_byte(68,4,0x3e);
	LCD_display_byte(69,4,0x1c);
	LCD_display_byte(70,4,0x08);
	LCD_display_word(speed_data,24,3,52);
	show_speed_num(62,4);
	while(tpflag)
	{
		switch(basic_button())
		{
			case 4: if(speed_num!=0)
					{
						speed_num--;
						show_speed_num(62,4);
					}
					while(left==0);
					break;
			case 5: if(speed_num!=9)
					{
						speed_num++;
						show_speed_num(62,4);
					}
					while(right==0);
					break;
			case 3: tpflag=0;
					while(button_a==0);
					break;
			default:;
		}
	}//选择游戏速度循环
}//选择游戏速度函数

void game_initialize()
{
	box_down_reg=0;
	next_mode=6;
	next_shape=2;
	destroy_row_num=0;
	game_over_flag=0;
	pause_game_flag=0;
	LCD_clear();
	time0_reg=0;
	display_basic();	
	LCD_display_word(score_data,24,0,3);
	LCD_display_word(speed_data,24,3,3);
	show_score_num(3,1);
	show_speed_num(13,4);
}//游戏初始化函数


void game_over_show()
{
	unsigned char i;
	bit tpflag=1;//置循环标志位为1
	LCD_full_draw(over_pic);
	while(button_a==0);
	while(tpflag)
	{
		switch(basic_button())
		{
			case 3: tpflag=0;
					while(button_a==0);
					break;
			default:;
		}
	}//game over画面循环
	LCD_clear();
	for(i=0;i<128;i++)
	{
		LCD_display_byte(i,0,0xff);
		LCD_display_byte(i,7,0xff);
	}
	LCD_display_word(score_data,24,3,52);
	show_score_num(52,4);
	tpflag=1;
	while(tpflag)
	{
		switch(basic_button())
		{
			case 3: tpflag=0;
					while(button_a==0);
					break;
			default:;
		}
	}//游戏得分显示循环
}//游戏结束画面显示函数

⌨️ 快捷键说明

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