STM32|STM32之俄罗斯方块

STM32之俄罗斯方块 1.硬件平台

  • STM32开发板
  • 3.5寸LCD屏(16位并口8080时序)
  • 字库存储W25Q64(SPI)
  • 4个按键
2.示例效果 STM32|STM32之俄罗斯方块
文章图片


STM32|STM32之俄罗斯方块
文章图片



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

【STM32|STM32之俄罗斯方块】?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 9 const 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 9 const 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=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

    推荐阅读