单片机控制点阵俄罗斯方块的程序源码

来源:互联网 发布:linux查看运行内存大小 编辑:程序博客网 时间:2024/05/18 16:39

主函数

#include<reg52.h>
#include "boxfunction.h"

#define uchar unsigned char
#define uint unsigned int

sbit swit = P1^0;
sbit left = P1^1;
sbit right = P1^2;
sbit down = P1^3;
sbit reset = P1^4;
sbit led = P1^7;
sbit led1 = P1^6;
sbit led2 = P1^5;

uchar arry[33];
uchar tmp[33];
char stat = 0;
char key1;
char key2;
char key_for_extern;
char flag = 0;

int seed1,seed2;

//********************************************************8888

//*************************************************************

unsigned char code table_num[] = {
0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,//0
0x00,0x00,0x00,0x10,0x70,0x10,0x10,0x10,//1
0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x04,//2
0x00,0x00,0x00,0x3C,0x42,0x42,0x04,0x18,//3
0x00,0x00,0x00,0x04,0x0C,0x14,0x24,0x24,//4
0x00,0x00,0x00,0x7E,0x40,0x40,0x40,0x58,//5
0x00,0x00,0x00,0x1C,0x24,0x40,0x40,0x58,//6
0x00,0x00,0x00,0x7E,0x44,0x44,0x08,0x08,//7
0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x24,//8
0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,//9
};

unsigned char code tabe_start[] = {
0x01,0x00,0x01,0x00,0x7F,0xFC,0x03,0x80,
0x05,0x40,0x09,0x20,0x31,0x18,0xC1,0x06,
0x0F,0xE0,0x00,0x40,0x00,0x80,0xFF,0xFE,
0x01,0x00,0x01,0x00,0x05,0x00,0x02,0x00,//李",0

0x10,0x40,0x10,0x40,0x2F,0xFE,0x40,0x40,
0x97,0xFC,0x14,0xA4,0x24,0xA4,0x67,0xFC,
0xA0,0x00,0x2F,0xFE,0x20,0x40,0x20,0x24,
0x25,0x22,0x25,0x0A,0x29,0x08,0x20,0xF8,//德",1

0x00,0x00,0x07,0xFC,0xFC,0x04,0x24,0xA4,
0x21,0x10,0x22,0x08,0x20,0x40,0xF8,0x40,
0x27,0xFC,0x20,0x40,0x20,0xE0,0x39,0x50,
0xE2,0x48,0x4C,0x46,0x00,0x40,0x00,0x40,//琛",2

0x01,0x00,0x02,0x00,0x04,0x00,0x1F,0xF0,
0x10,0x10,0x10,0x10,0x10,0x10,0x1F,0xF0,
0x10,0x10,0x10,0x10,0x1F,0xF0,0x10,0x10,
0x10,0x10,0x10,0x10,0x1F,0xF0,0x10,0x10,//自",3

0x00,0x40,0x00,0x40,0x7C,0x40,0x00,0x40,
0x01,0xFC,0x00,0x44,0xFE,0x44,0x20,0x44,
0x20,0x44,0x20,0x84,0x48,0x84,0x44,0x84,
0xFD,0x04,0x45,0x04,0x02,0x28,0x04,0x10,//动",4

0x08,0x80,0x08,0x80,0x08,0x84,0x10,0x88,
0x10,0x90,0x30,0xA0,0x30,0xC0,0x50,0x80,
0x91,0x80,0x12,0x80,0x14,0x80,0x10,0x82,
0x10,0x82,0x10,0x82,0x10,0x7E,0x10,0x00,//化",5

0x00,0x00,0x00,0x00,0x7F,0xFC,0x44,0x44,
0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
0x48,0x44,0x48,0x3C,0x50,0x04,0x60,0x04,
0x40,0x04,0x7F,0xFC,0x40,0x04,0x00,0x00,//四",6

0x00,0x80,0x00,0x80,0xF8,0xBE,0x22,0x88,
0x22,0x88,0x22,0x88,0x22,0x88,0xFA,0xBE,
0x22,0x88,0x24,0x88,0x20,0x88,0x39,0x08,
0xE1,0x08,0x42,0x3E,0x04,0x00,0x08,0x00,//班",7


};
//******************************用于测试led***********************************
void init_arry()
{
 int i;
 for(i=0; i<=32; i++)
  arry[i]=0x00;
 //arry[30] = 0xff;
 //arry[16] = 0xf8;
 arry[32] = 0xff;//人为加一个底行 不作为显示,仅作为下落判断依据
 draw_line(arry);
}

void init_timer()
{
  TMOD = 0X01;
  TH0 = (65535-10000)/256;
  TL0 = (65535-10000)%256;
  ET0 = 1;
  TR0 = 1;
  EA = 1;
}

char keyscan()
{
  int i;  
  P1 = P1|0x1f;
  for(i=2;i>0;i--);
 
  if(swit == 0)
  {
   if(stat <= 2)
   {
    stat ++;
   // led = ~led;
   }
   return 1;
  }
  else if(left == 0)
  {
   if(stat <= 2)
   {
    stat ++;
   }
   return 2;
  }
  else if(right == 0)
  {
   if(stat <= 2)
   {
    stat ++;
   }
   return 3;
  }
  else if(down == 0)
  {
   if(stat <= 2)
   {
    stat ++;
   }
   return 4;
  }
  else if(reset == 0)
  {
   if(stat <= 2)
   {
    stat ++;
   }
   return 5;
  }
  else
  { 
   stat = 0;
   return 0;
  }
}
/*
typedef struct{
 unsigned char x;
 unsigned char y;
 unsigned char shap;
 unsigned char mode;
 unsigned int tpbox;
 unsigned int box_new;
*/

void delay_ms()
{
  int x,y;
  for(x=2;x>0;x--)
    for(y=110;y>0;y--);
}

/*void start()
{
  char j,k,*temp;
  int i;

 for(i=0; i<=8*32; i+=2)
 {
   temp = &tabe_start[i];
   for(k=0; k<2; k++)
   {
     for(j=0; j<6; j++)
     {
       display(temp);
     }
   }
 }
}*/

void init()
{
   porta = 0x00;
   portd = 0x00;
   init_arry();
}

uint deal_to_key;

void main()
{
 
 uint deal;
 box b;
 uint time=2;

 init();

   box_init(&b,seed1%7,seed2%4);
 
   init_timer();
   while(1)
   {

    // start();
     while(deal != 1)
   {
      deal = box_drop_down(&b,time,arry,tmp);    //方块下降函数
      box_init(&b,seed1%7,seed2%4);
   //led = 0;
   }
   
   init();
   time=2;
   deal = 0;
  }
}

void timer() interrupt 1 //10ms *******************************中断一次,用于键盘检测***********************************************
{
  TH0 = (65535-10000)/256;
  TL0 = (65535-10000)%256;

  seed1++;
  seed2+=3;
  if(seed1 == 100)
    seed1 = 0;
  if(seed2 == 100)
    seed2 = 0;

  EA = 0;
 
  key1 = keyscan();

  if(stat == 1)
  {
   key2 = key1;   //key2为第一次的保存值
   //led = 0;
  }
  else if(stat == 2)
  {
   if(key2 == key1)
   {
    //led = 0;
    stat++;
   }
   else
    stat = 0;
  }
  else if(stat == 3)
  {
   flag = 1;  //确定有按键按下,等待按键弹起,状态始终保持为3,直到按键弹起,状态归零,标志位清零
  }

  if(flag==1 && swit==1 && left==1 && right==1 && down==1 && reset==1)
  {
     flag = 0;
     //led = 0;
     stat = 0;
     key_for_extern = key2;//给按键赋值 付的是第一次保存下来的数值
  }
    
  EA = 1; 

}

 

 

 

 

功能模块:

#include "boxfunction.h"
#include<reg52.h>

sbit en1 = P2^3;
sbit en2 = P2^7;
sbit led = P1^7;

void test()
{
 P1 = 0xf0;
}

void delay(unsigned int x)
{
 unsigned int y,z;
 for(y=x ;y>0 ;y--)
  for(z=110 ;z>0 ; z--);
}

//*******************************显示数组内容***********************************
void display(uchar* arry)
{
 int i;
 for(i=0; i<16; i++)
 {
  P2 = 0X00;
  if(i<8)
  {
   P2 = (P2|i)|0x08;
  }
  else
   P2 = (P2|(i<<4))|0x80;

  portd = arry[2*i];
  porta = arry[2*i+1];
  delay(1);
 }
}
//***************************************************************************
//********************************用于存储方块状态***************************
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=0x8888;break;
     case 2: tpbox=0xf000;break;
     case 3: tpbox=0x8888;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 write_box_to_arry(unsigned char position_x,unsigned char position_y,unsigned int tpbox_new,unsigned int tpbox_old,unsigned char *arry)
{
  char i;
  unsigned int temp,temp_y;
  //删除旧的方块
  temp = tpbox_old;
  temp_y = position_y;
  for(i=3;i>=0;i--)
  {
    arry[2*temp_y + i*2] = ( arry[2*temp_y + i*2] & (~ (((temp&0x000f)<<4) >> position_x)) ); //需要保证只修改方块所经过的列 而不会影响到此行其他位置 
    temp = temp>>4; 
  }

  temp = tpbox_new;
  temp_y = position_y;
     for(i=3;i>=0;i--)
  {
    arry[2*(temp_y+i)] = arry[2*(temp_y+i)] | ( ((temp&0x000f)<<4) >> position_x );
    temp = temp>>4; 
  }
  
}

void delet_box_from_arry(unsigned char position_x,unsigned char position_y,unsigned int tpbox_old,unsigned char *arry)
{
  char i;
  unsigned int temp,temp_y;
  //删除旧的方块
  temp = tpbox_old;
  temp_y = position_y;
  for(i=3;i>=0;i--)
  {
    arry[2*temp_y + i*2] = ( arry[2*temp_y + i*2] & (~ (((temp&0x000f)<<4) >> position_x)) ); //需要保证只修改方块所经过的列 而不会影响到此行其他位置 
    temp = temp>>4; 
  }  
}

//*********************************************擦除某一行******************************
void line_cleared(char line,unsigned char *arry)
{
  arry[line*2] = 0x00;  
}

//**************************************检查是否可以继续下降***************************
/*char box_enable_drop_down(unsigned char *arry, box *b)
{
  char i;
  unsigned char temp;
  unsigned char reg[4];

  temp = b->tpbox;
  for(i=3; i>=0; i--)//当前位置的
  {
      // arry[2*(b.y+i)] = arry[2*(b.y+i)] & (~((temp&0x000f)<<4) >> b.x);
      reg[i] = (((temp&0x000f)<<4) >> b->x);   //reg[i]相当于方块的数据
      temp = temp >> 4;
  }
  for(i=3; i>=0; i--)
  {
      if( ( reg[i] & (arry[(b->y+i+1)*2]) )  != 0x00 )//阻塞 方块的上一行和真实显示数组中方块位置的下一行 相与 全为0 则无阻塞
        return 0;
  }
  return 1;    
}*/
char box_enable_drop_down(unsigned char *arry, box *b)
{
  char i;
  unsigned int temp;
  unsigned char reg;

  temp = b->tpbox;
  for(i=3; i>=0; i--)//当前位置的
  {
      // arry[2*(b.y+i)] = arry[2*(b.y+i)] & (~((temp&0x000f)<<4) >> b.x);
      reg = (((temp&0x000f)<<4) >> b->x);   //reg[i]相当于方块的数据
      temp = temp >> 4;
      if( ( reg & (arry[(b->y+i+1)*2]) )  != 0x00 )//阻塞 方块的上一行和真实显示数组中方块位置的下一行 相与 全为0 则无阻塞
      {  
        return 0;
    }
  }
  return 1;    
}
/**************************************************************
 此处出现一个大bug,表现在有的方块下落时会正常卡住,有的卡不住。由于有些可以正常卡住,基本确定主要程序没有大问题,
初步估计char box_enable_drop_down(unsigned char *arry, box *b) 函数中卡值的if语句出错。 根据出错统计规律,有两行的子模
出问题,三行以上的就没问题。检测if语句没错, 问题出在temp类型定义为char 产生了丢位。
*************************************************************/


//***************************************初始化方块************************************
void box_init(box *b, char mod ,char sha)
{
  b->x = 4;
  b->y = 0;
  b->mode = mod;
  b->shap = sha;
  b->tpbox = box_read_data(b->mode,b->shap);
}

//****************************************画线*************************************
void draw_line(unsigned char *arry) //先赋值给缓存数组 此处运行效率不高 但是和后面 更新显示数组有耦合 有待改进
{
  int i;
  for(i=0; i<32; i+=2)
    arry[i+1] = arry[i+1] | 0x80;
}

//**************************************下降*******************************************
void arry_to_tmp(unsigned char *arry,unsigned char *tmp)
{
  int i;
  for(i=0;i<33;i++)
   tmp[i] = arry[i];

    arry[32] = 0xff;
}
/*
typedef struct{
 unsigned char x;
 unsigned char y;
 unsigned char shap;
 unsigned char mode;
 unsigned int tpbox;
 unsigned int box_new;
}box;
*/

/*char box_enable_move_left(box* b,unsigned char *arry)
{
  int i,j;
  unsigned int temp;
  unsigned char reg,tmp;

  temp = b->tpbox;
  j = b->y * 2;
  for(i=3; i>=0; i--)
  {
    reg =( ((temp&0x000f)<<4) >> b->x);
    tmp = ( ( ( reg | arry[j + i] ) & ((0x80>>(b->x - 1)) ) | 0xf0>>b->x));
    if(  (tmp ==  (0x80>>(b->x - 1)) )  ||  (tmp&0x80 == 0x80) )
      return 0;

    temp = temp >>4;
  }
  return 1;
}*/


//*************************删除满行***************************************
char delet_full_line(unsigned char *arry)
{
  char i=0,j=30,k;
  while(i<=4 && j>=2)   //    
  {
    if(arry[j] == 0xff) 
    {
      for(k=j;k>=2;k-=2)
      {
       *(arry+k) = *(arry+k-2);
      }
      arry[0] = 0x00;

      i++;

      j = 30;
    }
    else
     j = j-2;
  }
  return i;
}
/**************************************全局变量***********************************************88
来源: main.c
作用函数 :  char keyfunc(box* b,char key)  用来赋值
    char box_drop_down(box *b,unsigned int time,unsigned char *arry,unsigned char *tmp) 用来检测
 传来的全局变量 当按键reset按下赋值1,传值到box_drop_down ,使跳出循环 ,游戏复位
************************************************************************************************/
extern unsigned int deal_to_key;//main.c

char keyfunc(box* b,char key)//定义结构体指针函数中应出现相应的赋值 这样编译才能通过
{
 //led = 0;
  char down = 0;
  switch(key)
  {
   case 1:{
      b->shap++;         //按键1 shap自增 旋转但是形状不变
      if(b->shap == 4)
       b->shap = 0;

      b->box_new = box_read_data(b->mode,b->shap);

   }break;

   case 2:{
      b->x--;
      
   }break;

   case 3:{
          b->x++;
   }break;

   case 4:{
     down = 1;
     return down;//产生快速下降标志 使time加快
   }break;

   case 5:{
      deal_to_key = 1;
   }break;
   
  }
}

extern char key_for_extern;

char box_drop_down(box *b,unsigned int time,unsigned char *arry,unsigned char *tmp)
{
 char i,j,k,temp_time,first_time,t;   //temp_time用于加速   first_time用于保存参数time的值
 b->box_new = b->tpbox;
 b->y = 0;//y从第0行开始下降 每次走一个

 first_time = time;
 t = first_time;

 for(i=0; i<19; i++)
 { 
  if(deal_to_key == 1)//复位键按下 游戏结束
  {
    deal_to_key = 0;
    return 1;
  }
      
  for(k=0; k<10; k++)//每下降到新的一层 都有十次改变的机会。
  {
   temp_time = keyfunc(b,key_for_extern); //查看按键的值 更新方块状态
   key_for_extern = 0;

  /* if(temp_time == 0)//加速判断
     t = first_time;
   else
     t = temp_time;*/

   delet_box_from_arry(b->x, b->y, b->tpbox,arry);//清除记录数组中的内容,防止下落时留下尾巴
   write_box_to_arry(b->x, b->y, b->box_new, b->tpbox, arry);//写入新的数据

   arry_to_tmp(arry,tmp);

   for(j=0; j<t; j++)//循环显示同一个数组 达到下落时暂停的效果 通过改变time值来改变方块下降速度
   {      
    display(tmp);
   }
   delet_box_from_arry(b->x, b->y, b->tpbox,arry);//清除记录数组中的内容,防止下落时留下尾巴 
   delet_box_from_arry(b->x, b->y, b->tpbox,tmp);//清除显示数组中的内容

   b->tpbox = b->box_new;//显示完毕后 新方块的数据编程旧方块
  }
  
  //arry_to_tmp(arry,tmp);  
  if(box_enable_drop_down(tmp, b) == 1)//如果可以继续下降则下降
  {
   b->y++;
  }
  else                               //如果有阻塞 将方块重新写到最后的位置 更新显示数组
  { 
   write_box_to_arry(b->x, b->y, b->box_new, b->tpbox, arry);

   delet_full_line(arry);

   if(tmp[0] != 0x00)  //最顶层一行不为空 游戏结束
   {
     return 1;
    }

   arry_to_tmp(arry,tmp);
   return 0;
  }
 }
 return 0;
}

 

5 0
原创粉丝点击