> 文档中心 > STM32之俄罗斯方块

STM32之俄罗斯方块


STM32之俄罗斯方块

1.硬件平台

  • STM32开发板
  • 3.5寸LCD屏(16位并口8080时序)
  • 字库存储W25Q64(SPI)
  • 4个按键

2.示例效果

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.软件设计

 3.1 绘制单个方块函数

/*************绘制单个方块**************/void Lcd_DrawDiamond(u16 x,u16 y,u16 c){  u16 i;  LcdWriteReg(0x2A);//设置x坐标  LcdWriteData((x>>8)&0xff);//x坐标高8位  LcdWriteData(x&0xff);//x坐标低8位  LcdWriteData(((x+8)>>8)&0xff);//x坐标高8位  LcdWriteData((x+8)&0xff);//x坐标低8位  LcdWriteReg(0x2B);//设置Y坐标  LcdWriteData((y>>8)&0xff);//Y坐标高8位  LcdWriteData(y&0xff);//Y坐标低8位  LcdWriteData(((y+8)>>8)&0xff);//Y坐标高8位  LcdWriteData((y+8)&0xff);//Y坐标低8位  LcdWriteReg(0x2C);//设置x坐标  for(i=0;i<9*9;i++)LcdWriteData(c);}

 3.2 清空一行显示

/******************消除一行*******************/void Lcd_ClearOneLineDisplay(u16 y,u16 c){  u16 i=0;  for(i=2;i<LCD_WIDTH-98;i+=10)  {    Lcd_DrawDiamond(i,y,c);  }}

 3.3 定义屏幕大小数组,保存方块图形掉落位置状态信息,显示区域宽度为220,高度为480

u8 shape_place_stat[49][24]={  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},//第一行y=0的状态信息  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},//第二行y=10的状态信息  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},//y=20  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},//y=30  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},//y=40   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},//y=50  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},//y=200  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},//y=300  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},//y=400  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},   {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},//y=460  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},//y=470    {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},//最后一行为状态 };

 3.4 更新当前状态到二维数组中

/*更新一个状态到二维数组中*/void Lcd_Refreshbuff(u16 x,u16 y,u8 stat){  shape_place_stat[y/10][x/10+1]=(stat&0x01);}

 3.5 设置每个方块种类颜色,绘制各个方块

 /*每一个种类的颜色*//*1  -- DARKBLUE --Drawshape_color[0]2,3 -- BRRED  --Drawshape_color[1]4,5,6,7 -- BLUE --Drawshape_color[2]8,9,10,11,12,13,14,15 -- GRAY --Drawshape_color[3]16,17,18,19  --BLACK -- Drawshape_color[4]*/const u16 Drawshape_color[]={DARKBLUE,BRRED,BLUE,GRAY,BLACK};/*******************绘制一个俄罗斯方块*****************************形参:x,y -- 要显示的位置**what  --要绘制的方块序号(1~19)**      c   --方块颜色**stat  --更新到二维数组中的状态(0表示清除,1表示写入状态)*******************************************************************/void Lcd_Drawshape(u16 x,u16 y,u8 what,u16 c,u8 stat){switch (what){case 1:{      Lcd_DrawDiamond(x,y,c);      Lcd_DrawDiamond(x+10,y,c);      Lcd_DrawDiamond(x,y+10,c);      Lcd_DrawDiamond(x+10,y+10,c);     Lcd_Refreshbuff(x,y,stat);      Lcd_Refreshbuff(x+10,y,stat);      Lcd_Refreshbuff(x,y+10,stat);      Lcd_Refreshbuff(x+10,y+10,stat);}break;case 2:{      Lcd_DrawDiamond(x,y,c);      Lcd_DrawDiamond(x+10,y,c);      Lcd_DrawDiamond(x+20,y,c);      Lcd_DrawDiamond(x+30,y,c);      Lcd_Refreshbuff(x,y,stat);      Lcd_Refreshbuff(x+10,y,stat);      Lcd_Refreshbuff(x+20,y,stat);      Lcd_Refreshbuff(x+30,y,stat);}break;case 3:{      Lcd_DrawDiamond(x,y,c);      Lcd_DrawDiamond(x,y+10,c);      Lcd_DrawDiamond(x,y+20,c);      Lcd_DrawDiamond(x,y+30,c);     Lcd_Refreshbuff(x,y,stat);      Lcd_Refreshbuff(x,y+10,stat);      Lcd_Refreshbuff(x,y+20,stat);      Lcd_Refreshbuff(x,y+30,stat);}break;case 4:{      Lcd_DrawDiamond(x+10,y,c);      Lcd_DrawDiamond(x,y+10,c);      Lcd_DrawDiamond(x+10,y+10,c);      Lcd_DrawDiamond(x+20,y+10,c); Lcd_Refreshbuff(x+10,y,stat);      Lcd_Refreshbuff(x,y+10,stat);      Lcd_Refreshbuff(x+10,y+10,stat);      Lcd_Refreshbuff(x+20,y+10,stat);}break;case 5:{      Lcd_DrawDiamond(x+10,y+10,c);      Lcd_DrawDiamond(x,y,c);      Lcd_DrawDiamond(x,y+10,c);      Lcd_DrawDiamond(x,y+20,c);     Lcd_Refreshbuff(x+10,y+10,stat);      Lcd_Refreshbuff(x,y,stat);      Lcd_Refreshbuff(x,y+10,stat);      Lcd_Refreshbuff(x,y+20,stat);}break;case 6:{      Lcd_DrawDiamond(x,y+10,c);      Lcd_DrawDiamond(x+10,y,c);      Lcd_DrawDiamond(x+10,y+10,c);      Lcd_DrawDiamond(x+10,y+20,c);     Lcd_Refreshbuff(x,y+10,stat);      Lcd_Refreshbuff(x+10,y,stat);      Lcd_Refreshbuff(x+10,y+10,stat);      Lcd_Refreshbuff(x+10,y+20,stat);}break;case 7:{      Lcd_DrawDiamond(x+10,y+10,c);      Lcd_DrawDiamond(x,y,c);      Lcd_DrawDiamond(x+10,y,c);      Lcd_DrawDiamond(x+20,y,c);     Lcd_Refreshbuff(x+10,y+10,stat);      Lcd_Refreshbuff(x,y,stat);      Lcd_Refreshbuff(x+10,y,stat);      Lcd_Refreshbuff(x+20,y,stat);    }break;case 8:{      Lcd_DrawDiamond(x,y,c);      Lcd_DrawDiamond(x,y+10,c);      Lcd_DrawDiamond(x,y+20,c);      Lcd_DrawDiamond(x+10,y+20,c);     Lcd_Refreshbuff(x,y,stat);      Lcd_Refreshbuff(x,y+10,stat);      Lcd_Refreshbuff(x,y+20,stat);      Lcd_Refreshbuff(x+10,y+20,stat);}break;case 9:{      Lcd_DrawDiamond(x,y,c);      Lcd_DrawDiamond(x,y+10,c);      Lcd_DrawDiamond(x+10,y,c);      Lcd_DrawDiamond(x+20,y,c);     Lcd_Refreshbuff(x,y,stat);      Lcd_Refreshbuff(x,y+10,stat);      Lcd_Refreshbuff(x+10,y,stat);      Lcd_Refreshbuff(x+20,y,stat);}break;case 10:{      Lcd_DrawDiamond(x,y,c);      Lcd_DrawDiamond(x+10,y,c);      Lcd_DrawDiamond(x+10,y+10,c);      Lcd_DrawDiamond(x+10,y+20,c);     Lcd_Refreshbuff(x,y,stat);      Lcd_Refreshbuff(x+10,y,stat);      Lcd_Refreshbuff(x+10,y+10,stat);      Lcd_Refreshbuff(x+10,y+20,stat);}break;case 11:{      Lcd_DrawDiamond(x,y+10,c);      Lcd_DrawDiamond(x+10,y+10,c);      Lcd_DrawDiamond(x+20,y+10,c);      Lcd_DrawDiamond(x+20,y,c);     Lcd_Refreshbuff(x,y+10,stat);      Lcd_Refreshbuff(x+10,y+10,stat);      Lcd_Refreshbuff(x+20,y+10,stat);      Lcd_Refreshbuff(x+20,y,stat);}break;case 12:{      Lcd_DrawDiamond(x+10,y,c);      Lcd_DrawDiamond(x+10,y+10,c);      Lcd_DrawDiamond(x+10,y+20,c);      Lcd_DrawDiamond(x,y+20,c);     Lcd_Refreshbuff(x+10,y,stat);      Lcd_Refreshbuff(x+10,y+10,stat);      Lcd_Refreshbuff(x+10,y+20,stat);      Lcd_Refreshbuff(x,y+20,stat);}break;case 13:{      Lcd_DrawDiamond(x,y,c);      Lcd_DrawDiamond(x+10,y,c);      Lcd_DrawDiamond(x+20,y,c);      Lcd_DrawDiamond(x+20,y+10,c);     Lcd_Refreshbuff(x,y,stat);      Lcd_Refreshbuff(x+10,y,stat);      Lcd_Refreshbuff(x+20,y,stat);      Lcd_Refreshbuff(x+20,y+10,stat);}break;case 14:{      Lcd_DrawDiamond(x,y,c);      Lcd_DrawDiamond(x+10,y,c);      Lcd_DrawDiamond(x,y+10,c);      Lcd_DrawDiamond(x,y+20,c);     Lcd_Refreshbuff(x,y,stat);      Lcd_Refreshbuff(x+10,y,stat);      Lcd_Refreshbuff(x,y+10,stat);      Lcd_Refreshbuff(x,y+20,stat);}break;case 15:{      Lcd_DrawDiamond(x,y,c);      Lcd_DrawDiamond(x,y+10,c);      Lcd_DrawDiamond(x+10,y+10,c);      Lcd_DrawDiamond(x+20,y+10,c);     Lcd_Refreshbuff(x,y,stat);      Lcd_Refreshbuff(x,y+10,stat);      Lcd_Refreshbuff(x+10,y+10,stat);      Lcd_Refreshbuff(x+20,y+10,stat);}break;case 16:{      Lcd_DrawDiamond(x+10,y,c);      Lcd_DrawDiamond(x,y+10,c);      Lcd_DrawDiamond(x+10,y+10,c);      Lcd_DrawDiamond(x,y+20,c);     Lcd_Refreshbuff(x+10,y,stat);      Lcd_Refreshbuff(x,y+10,stat);      Lcd_Refreshbuff(x+10,y+10,stat);      Lcd_Refreshbuff(x,y+20,stat);}break;case 17:{      Lcd_DrawDiamond(x,y,c);      Lcd_DrawDiamond(x+10,y,c);      Lcd_DrawDiamond(x+10,y+10,c);      Lcd_DrawDiamond(x+20,y+10,c);     Lcd_Refreshbuff(x,y,stat);      Lcd_Refreshbuff(x+10,y,stat);      Lcd_Refreshbuff(x+10,y+10,stat);      Lcd_Refreshbuff(x+20,y+10,stat);}break;case 18:{      Lcd_DrawDiamond(x,y,c);      Lcd_DrawDiamond(x,y+10,c);      Lcd_DrawDiamond(x+10,y+10,c);      Lcd_DrawDiamond(x+10,y+20,c);     Lcd_Refreshbuff(x,y,stat);      Lcd_Refreshbuff(x,y+10,stat);      Lcd_Refreshbuff(x+10,y+10,stat);      Lcd_Refreshbuff(x+10,y+20,stat);}break;case 19:{      Lcd_DrawDiamond(x,y+10,c);      Lcd_DrawDiamond(x+10,y+10,c);      Lcd_DrawDiamond(x+10,y,c);      Lcd_DrawDiamond(x+20,y,c);     Lcd_Refreshbuff(x,y+10,stat);      Lcd_Refreshbuff(x+10,y+10,stat);      Lcd_Refreshbuff(x+10,y,stat);      Lcd_Refreshbuff(x+20,y,stat);}break;}}

 3.6 方块移动和切换方向

/******************向下移动*****************/int Lcd_DownMove(u16 x,u16 y,u16 what,u16 c){  Lcd_Drawshape(x,y,what,WHITE,0);  Lcd_Drawshape(x,y+10,what,c,1);  return y+10;}/***************向左移动*********************/int Lcd_LeftMove(u16 x,u16 y,u16 what,u16 c){  Lcd_Drawshape(x,y,what,WHITE,0);  Lcd_Drawshape(x-10,y,what,c,1);  return x-10;}/****************向右移动********************/int Lcd_RightMove(u16 x,u16 y,u16 what,u16 c){  Lcd_Drawshape(x,y,what,WHITE,0);  Lcd_Drawshape(x+10,y,what,c,1);  return x+10;}/**************************改变图形***************/u8 Lcd_Changshape(u16 x,u16 y,u16 what,u16 c){  u8 stat;switch(what){case 1:stat=1;break;case 2:{if(shape_place_stat[(y+40)/10][x/10] || shape_place_stat[(y+30)/10][x/10] || shape_place_stat[(y+20)/10][x/10] || shape_place_stat[(y+10)/10][x/10]){stat=2;break;}Lcd_Drawshape(x,y,2,WHITE,0);Lcd_Drawshape(x,y,3,c,1);stat=3;break;}    case 3:{if(shape_place_stat[(y+40)/10][(x+40)/10]){stat=3;break;}Lcd_Drawshape(x,y,3,WHITE,0);Lcd_Drawshape(x,y,2,c,1);stat=2;break;}    case 4:{Lcd_Drawshape(x,y,4,WHITE,0);Lcd_Drawshape(x,y,5,c,1);stat=5;break;}    case 5:{Lcd_Drawshape(x,y,5,WHITE,0);Lcd_Drawshape(x,y,6,c,1);stat=6;break;}    case 6:{if(shape_place_stat[y/10][(x+30)/10]){stat=6;break;}Lcd_Drawshape(x,y,6,WHITE,0);Lcd_Drawshape(x,y,7,c,1);stat=7;break;}    case 7:Lcd_Drawshape(x,y,7,WHITE,0);Lcd_Drawshape(x,y,4,c,1);stat=4;break; case 8:{if(shape_place_stat[y/10][(x+30)/10]){stat=8;break;}Lcd_Drawshape(x,y,8,WHITE,0);Lcd_Drawshape(x,y,9,c,1);stat=9;break;}    case 9:{if(shape_place_stat[(y+30)/10][x/10]){stat=9;break;}Lcd_Drawshape(x,y,9,WHITE,0);Lcd_Drawshape(x,y,10,c,1);stat=10;break;}    case 10:{if(shape_place_stat[y/10][(x+30)/10]){stat=10;break;}Lcd_Drawshape(x,y,10,WHITE,0);Lcd_Drawshape(x,y,11,c,1);stat=11;break;}    case 11:{if(shape_place_stat[(y+30)/10][x/10]){stat=11;break;}Lcd_Drawshape(x,y,11,WHITE,0);Lcd_Drawshape(x,y,8,c,1);stat=8;break;} case 12:{if(shape_place_stat[(y)/10][(x+30)/10] || shape_place_stat[(y+20)/10][x/10] || shape_place_stat[(y+20)/10][(x+30)/10]){stat=12;break;}Lcd_Drawshape(x,y,12,WHITE,0);Lcd_Drawshape(x,y,13,c,1);stat=13;break;}    case 13:{if(shape_place_stat[(y+30)/10][x/10]){stat=13;break;}Lcd_Drawshape(x,y,13,WHITE,0);Lcd_Drawshape(x,y,14,c,1);stat=14;break;}    case 14:{if(shape_place_stat[y/10][(x+30)/10]){stat=14;break;}Lcd_Drawshape(x,y,14,WHITE,0);Lcd_Drawshape(x,y,15,c,1);stat=15;break;}    case 15:{if(shape_place_stat[(y+30)/10][x/10]){stat=15;break;}Lcd_Drawshape(x,y,15,WHITE,0);Lcd_Drawshape(x,y,12,c,1);stat=12;break;} case 16:{if(shape_place_stat[y/10][(x+30)/10]){stat=16;break;}Lcd_Drawshape(x,y,16,WHITE,0);Lcd_Drawshape(x,y,17,c,1);stat=17;break;}    case 17:{Lcd_Drawshape(x,y,17,WHITE,0);Lcd_Drawshape(x,y,16,c,1);stat=16;break;} case 18:{if(shape_place_stat[y/10][(x+30)/10]){stat=18;break;}Lcd_Drawshape(x,y,18,WHITE,0);Lcd_Drawshape(x,y,19,c,1);stat=19;break;}    case 19:{Lcd_Drawshape(x,y,19,WHITE,0);Lcd_Drawshape(x,y,18,c,1);stat=18;break;}}    return stat;}

 3.7 判断是否到达边界

/*判断状态*/u8 Lcd_Shape_GetStat(u16 x,u16 y){//printf("x=%d,y=%d\r\n",x,y);//printf("stat=%d\r\n",shape_place_stat[y/10][x/10+1]);  if(shape_place_stat[y/10][x/10+1])return 1;  else return 0;  }//每个方块高度  //1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9const u8 shape_high[19]={2,1,4,2,3,3,2,3,2,3,2,3,2,3,2,3,2,3,2};//保存每个方块宽度      //1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9const u8 shape_widht[19]={2,4,1,3,2,2,3,2,3,2,3,2,3,2,3,2,3,2,3};/****************判断是否到到达下边界***************/u8 Lcd_Shape_GetLowerBoundary(u16 x,u16 y,u8 cnt){  switch (cnt){    case 1:    {      if(shape_place_stat[(y+20)/10][x/10+1])return 1;      else if(shape_place_stat[(y+20)/10][(x+10)/10+1])return 2;    }    break;    case 2:    {      if(shape_place_stat[(y+10)/10][x/10+1])return 1;      else if(shape_place_stat[(y+10)/10][(x+10)/10+1])return 2;      else if(shape_place_stat[(y+10)/10][(x+20)/10+1])return 3;      else if(shape_place_stat[(y+10)/10][(x+30)/10+1])return 4;    }    break;    case 3:    {      if(shape_place_stat[(y+40)/10][x/10+1])return 1;    }    break;    case 4:    {      if(shape_place_stat[(y+20)/10][x/10+1])return 1;      else if(shape_place_stat[(y+20)/10][(x+10)/10+1])return 2;      else if(shape_place_stat[(y+20)/10][(x+20)/10+1])return 3;    }    break;    case 5:    {      if(shape_place_stat[(y+30)/10][x/10+1])return 1;      else if(shape_place_stat[(y+20)/10][(x+10)/10+1])return 2;     }    break;    case 6:    {      if(shape_place_stat[(y+20)/10][x/10+1])return 1;      else if(shape_place_stat[(y+30)/10][(x+10)/10+1])return 2;    }    break;case 7:{      if(shape_place_stat[(y+10)/10][x/10+1])return 1;      else if(shape_place_stat[(y+20)/10][(x+10)/10+1])return 2;else if(shape_place_stat[(y+10)/10][(x+20)/10+1])return 3;}break;    case 8:    {      if(shape_place_stat[(y+30)/10][x/10+1])return 1;      if(shape_place_stat[(y+30)/10][(x+10)/10+1])return 1;    }    break;    case 9:    {      if(shape_place_stat[(y+20)/10][x/10+1])return 1;      else if(shape_place_stat[(y+10)/10][(x+10)/10+1])return 2;      else if(shape_place_stat[(y+10)/10][(x+20)/10+1])return 3;    }    break;    case 10:    {      if(shape_place_stat[(y+10)/10][x/10+1])return 1;      else if(shape_place_stat[(y+30)/10][(x+10)/10+1])return 2;    }    break; case 11:    {if(shape_place_stat[(y+20)/10][x/10+1])return 1;else if(shape_place_stat[(y+20)/10][(x+10)/10+1])return 2;   else if(shape_place_stat[(y+20)/10][(x+20)/10+1])return 3;     }    break;    case 12:    {      if(shape_place_stat[(y+30)/10][x/10+1])return 1;      else if(shape_place_stat[(y+30)/10][(x+10)/10+1])return 2;}    break;    case 13:    {      if(shape_place_stat[(y+10)/10][x/10+1])return 1;      else if(shape_place_stat[(y+10)/10][(x+10)/10+1])return 2;      else if(shape_place_stat[(y+20)/10][(x+20)/10+1])return 3;    }    break;    case 14:    {      if(shape_place_stat[(y+30)/10][x/10+1])return 1;      else if(shape_place_stat[(y+10)/10][(x+10)/10+1])return 2;}    break;    case 15:    {if(shape_place_stat[(y+20)/10][x/10+1])return 1;else if(shape_place_stat[(y+20)/10][(x+10)/10+1])return 2;    else if(shape_place_stat[(y+20)/10][(x+20)/10+1])return 3;    }    break;    case 16:    {if(shape_place_stat[(y+30)/10][x/10+1])return 1;else if(shape_place_stat[(y+20)/10][(x+10)/10+1])return 2; }    break;    case 17:    {if(shape_place_stat[(y+10)/10][x/10+1])return 1;else if(shape_place_stat[(y+20)/10][(x+10)/10+1])return 2;  else if(shape_place_stat[(y+20)/10][(x+20)/10+1])return 2;     }    break;    case 18:    {      if(shape_place_stat[(y+20)/10][x/10+1])return 1;      else if(shape_place_stat[(y+30)/10][(x+10)/10+1])return 2;    }    break;    case 19:    {      if(shape_place_stat[(y+20)/10][x/10+1])return 1;      else if(shape_place_stat[(y+20)/10][(x+10)/10+1])return 2;      else if(shape_place_stat[(y+10)/10][(x+20)/10+1])return 3;    }    break;}   return 0;  }

 3.8 将上一行方块放到当前行

/******************将上一行方块放到当前行************************/static void Lcd_ClearOneLine(u8 line){  u8 i=1;  for(i=1;i<23;i++)  {    if(shape_place_stat[line][i])Lcd_DrawDiamond((i-1)*10+2,line*10,BLACK);else Lcd_DrawDiamond((i-1)*10+2,line*10,WHITE);//shape_place_stat[line][i]=shape_place_stat[line-1][i];  }}

 3.9 判断得分,消行,清除方块在二维数组状态

/***********得分判断*********************/u8 Lcd_GetMark(u8 *buff){  int i,j,k;  u8 cnt=0;//保存要消除的行数  int line=0;  /*判断当前最高位置*/  for(i=47;i>=0;i--)//高度  {    for(j=1;j<23;j++)//每一行的方格数    {      if(shape_place_stat[i][j])break;    }    if(j==23)    {      line=i;//记录当前方块有多少行      break;    }  }//printf("line=%d\r\n",line);if(line<=1)return 0xff;//游戏结束  for(i=47;i>line;i--)  {    for(j=0;j<24;j++)    {      if(shape_place_stat[i][j]==0)break;    }    if(j==24)buff[cnt++]=i;//记录哪一行需要消除  }  /*得分,消行*/  if(cnt)  {    for(i=0;i<cnt;i++)    {      Lcd_ClearOneLineDisplay(buff[i]*10,RED);/*清除一行*/    }    Delay_Ms(500);    for(i=0;i<cnt;i++)    {      Lcd_ClearOneLineDisplay(buff[i]*10,WHITE);/*清除一行*/    } /*将方块往下移动*/for(k=cnt-1;k>=0;k--){for(j=buff[k];j>=line;j--){for(i=0;i<24;i++){shape_place_stat[j][i]=shape_place_stat[j-1][i];}}line--;}    for(i=buff[0];i>=line;i--)   {      Lcd_ClearOneLine(i);   }  }if(cnt==0)cnt=0;else if(cnt==1)cnt=1;//消除1行得1分else if(cnt==2)cnt=4;//消除2行得4分else if(cnt==3)cnt=8;else if(cnt==4)cnt=16;  return cnt; }/*清空图形掉落位置状态信息*/void Lcd_Clearshape(void){int i,j;for(i=0;i<48;i++){for(j=1;j<23;j++){shape_place_stat[i][j]=0;}}}

 3.10 窗口绘制

/*******************************绘制显示窗口**************************/void Lcd_TetrisShowWind(void){  LCD_DrawLine(LCD_WIDTH-97, 0, LCD_WIDTH-97, LCD_HIGHT,BLACK);//画直线  LCD_DrawLine(LCD_WIDTH-96, 0, LCD_WIDTH-96, LCD_HIGHT,BLACK);//画直线LCD_DrawLine(LCD_WIDTH-96, 170, LCD_WIDTH-1, 170,BLACK);LCD_DrawLine(LCD_WIDTH-96, 171, LCD_WIDTH-1, 171,BLACK);  LCD_Display_Str(LCD_WIDTH-96+25,30,24,(u8 *)"NEXT",DARKBLUE);//显示字符串  LCD_Display_Str(LCD_WIDTH-96+25,200,16,(u8 *)"得 分",DARKBLUE);//显示字符串LCD_Display_Str(LCD_WIDTH-96+96/2-12,200+30,24,(u8 *)"0",RED);//显示字符串LCD_Display_Str(LCD_WIDTH-96+10,320,16,(u8 *)"旋转 KEYUP ",DARKBLUE);//显示字符串LCD_Display_Str(LCD_WIDTH-96+10,360,16,(u8 *)"暂停 KEY1",DARKBLUE);//显示字符串LCD_Display_Str(LCD_WIDTH-96+10,400,16,(u8 *)"左 KEY2  ",DARKBLUE);//显示字符串LCD_Display_Str(LCD_WIDTH-96+10,440,16,(u8 *)"右 KEY0",DARKBLUE);//显示字符串}

4.主函数

#include "stm32f10x.h"#include "beep.h"#include "led.h"#include "key.h"#include "delay.h"#include "usart.h"#include "w25q64.h"#include "timer.h"#include #include "nt35310.h"#include "tetris_game.h"#include int main(){  u8 buff[49];  u8 stat=1;  int x0=112,y0=0;  u16 cnt=1,cnt2=0;  u8 key;u16 mark=0,res,mark2=0;u16 color;//方块颜色  u16 i=200;  Beep_Init();  Led_Init();  Key_Init();//按键初始化TIMx_Init(TIM4,7200,65535);  Usartx_Init(USART1,115200,72);  printf("串口初始化完成\r\n");  W25Q64_Init();  LCD_Init();AA:LCD_Clear(WHITE);//清屏函数  Lcd_TetrisShowWind();  cnt=rand()%20;  if(cnt==0)cnt=1;cnt2=rand()%20;if(cnt2==0)cnt2=1;Lcd_Drawshape(LCD_WIDTH-96+35,80,cnt2,BLACK,0);/*俄罗斯方块示例图*///  for(i=1;i<=19;i++)//  {//if(i==1)color=Drawshape_color[0];//else if(i>=2 && i<=3)color=Drawshape_color[1];//else if(i>=4 && i<=7)color=Drawshape_color[2];//else if(i>=8 && i<=15)color=Drawshape_color[3];//else if(i>=16 && i<=19)color=Drawshape_color[4];//    Lcd_Drawshape(x0,y0,i,color,0);//绘制图形//    x0+=50;//    if(x0>=260)//    {//      x0=50;//      y0+=50;//    }//  }  while(1)  { key=Key_Getval();    if(key==3)//暂停    {      stat=!stat;    }else if((key==1) && stat)//切换方向    {      i=0;if(cnt==1)color=Drawshape_color[0];else if(cnt>=2 && cnt<=3)color=Drawshape_color[1];else if(cnt>=4 && cnt<=7)color=Drawshape_color[2];else if(cnt>=8 && cnt<=15)color=Drawshape_color[3];else if(cnt>=16 && cnt<=19)color=Drawshape_color[4];      cnt=Lcd_Changshape(x0,y0,cnt,color);    }    else if((key==2) && stat)//右    {      if(Lcd_Shape_GetStat(x0+shape_widht[cnt-1]*10,y0)==0)      {if(cnt==1)color=Drawshape_color[0];else if(cnt>=2 && cnt<=3)color=Drawshape_color[1];else if(cnt>=4 && cnt<=7)color=Drawshape_color[2];else if(cnt>=8 && cnt<=15)color=Drawshape_color[3];else if(cnt>=16 && cnt<=19)color=Drawshape_color[4]; x0=Lcd_RightMove(x0,y0,cnt,color);      }    }    else if((key==4) && stat)//左    {      if(x0>=10)      { if(Lcd_Shape_GetStat(x0-10,y0)==0){if(cnt==1)color=Drawshape_color[0];else if(cnt>=2 && cnt<=3)color=Drawshape_color[1];else if(cnt>=4 && cnt<=7)color=Drawshape_color[2];else if(cnt>=8 && cnt<=15)color=Drawshape_color[3];else if(cnt>=16 && cnt<=19)color=Drawshape_color[4];   x0=Lcd_LeftMove(x0,y0,cnt,color);}      }    }    if(i>=100 && stat)    {      i=0;if(cnt==1)color=Drawshape_color[0];else if(cnt>=2 && cnt<=3)color=Drawshape_color[1];else if(cnt>=4 && cnt<=7)color=Drawshape_color[2];else if(cnt>=8 && cnt<=15)color=Drawshape_color[3];else if(cnt>=16 && cnt<=19)color=Drawshape_color[4];      y0=Lcd_DownMove(x0,y0,cnt,color);//向下      if(Lcd_Shape_GetLowerBoundary(x0,y0,cnt))//      {res=Lcd_GetMark(buff);if(res==0xff){mark=0;res=0;LCD_Display_Str(LCD_WIDTH/2-9*12,230,24,(u8 *)"GAME OVER",RED);LCD_Display_Str(LCD_WIDTH/2-9*12-20,265,16,(u8 *)"请按任意键重新开始!",RED);while(1){key=Key_Getval();if(key){Lcd_Clearshape();goto AA;}}}mark+=res;if(mark2!=mark){mark2=mark;snprintf((char *)buff,sizeof(buff),"%02d",mark2);LCD_Display_Str(LCD_WIDTH-94,230,24,(u8 *)"",WHITE);//显示字符串LCD_Display_Str(LCD_WIDTH-94+96/2-strlen((char *)buff)*12,230,24,buff,RED);//显示字符串}// printf("得分:%d\r\n",mark); x0=112,y0=0;Lcd_Drawshape(LCD_WIDTH-96+35,80,cnt2,WHITE,0);cnt=cnt2;cnt2=rand()%20;if(cnt2==0)cnt2=1;Lcd_Drawshape(LCD_WIDTH-96+35,80,cnt2,BLACK,0);      }    }     Delay_Ms(1);    i++;  }}

5.完整工程

完整工程示例:https://download.csdn.net/download/weixin_44453694/84079602

Job256网站商业源码