C51单片机12864液晶带按键制作俄罗斯方块C源码.docx
- 文档编号:30272712
- 上传时间:2023-08-13
- 格式:DOCX
- 页数:29
- 大小:20.65KB
C51单片机12864液晶带按键制作俄罗斯方块C源码.docx
《C51单片机12864液晶带按键制作俄罗斯方块C源码.docx》由会员分享,可在线阅读,更多相关《C51单片机12864液晶带按键制作俄罗斯方块C源码.docx(29页珍藏版)》请在冰豆网上搜索。
C51单片机12864液晶带按键制作俄罗斯方块C源码
************说明******************************
此程序包含一个俄罗斯方块.c文件和一个12864.h文件
********************俄罗斯方块.c文件**************************
#include"reg51.h"
#include"12864.h"
#defineucharunsignedchar
#defineuintunsignedint
staticunsignedlongSeed=1;
#defineA48271L
#defineM2147483647L
#defineQ(M/A)
#defineR(M%A)
sbitK1=P3^4;
sbitK2=P3^5;
sbitK3=P3^6;
sbitK4=P3^7;
unsignedintidatanum[19+2]={
0xfff,//第1行,最下面
0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,
0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,//第2行到第20行共19行
0xfff//第21行,最上面
};//定义共21行,其中num[0]为下墙壁行,num[20]为上墙壁行,每行12格,最左一格为左墙壁列,最右一格为右墙壁列
unsignedcharcodeBlock[28][2]={
/*
*口口口口口口
*口口口口
*口口口口口口
*/
{0x88,0xc0},{0xe8,0x00},{0x62,0x20},{0x02,0xe0},
/*
*口口口口口口
*口口口口
*口口口口口口
*/
{0x22,0x60},{0x08,0xe0},{0xc8,0x80},{0xe2,0x00},
/*
*口
*口口口口
*口口口
*/
{0x8c,0x40},{0x6c,0x00},{0x8c,0x40},{0x6c,0x00},
/*
*口口口
*口口口口
*口
*/
{0x4c,0x80},{0xc6,0x00},{0x4c,0x80},{0xc6,0x00},
/*
*口口
*口口口口口口口口
*口口口口口口
*/
{0x04,0xe0},{0x8c,0x80},{0xe4,0x00},{0x26,0x20},
/*口
*口
*口口口口口
*口
*/
{0x44,0x44},{0x0f,0x00},{0x44,0x44},{0x0f,0x00},
/*
*口口
*口口
*/
{0x06,0x60},{0x06,0x60},{0x06,0x60},{0x06,0x60}
};
#definePASSSCORE20
structJimu
{
unsignedintdat;
charx;
unsignedchary;
unsignedchartype;
unsignedcharchange;
}Sign[3];//积木结构体
unsignedcharSysFlag=0;
#defineNEWSIGNFLAG0
#defineDEADFLAG1
#definePAUSEFLAG2
unsignedcharScore=0;
unsignedcharLevel=1;
unsignedcharDelayCnt=5;
/*********************************************************/
#defineN25
/************************************
伪随机数发生器
*************************************/
doubleRandom(void)
{
longTmpSeed;
TmpSeed=A*(Seed%Q)-R*(Seed/Q);
if(TmpSeed>=0)
Seed=TmpSeed;
else
Seed=TmpSeed+M;
return(double)Seed/M;
}
/**************************************
为伪随机数发生器播种
***************************************/
voidInitRandom(unsignedlongInitVal)
{
Seed=InitVal;
}
//延时子程序
voidDelay(unsignedintt)
{
unsignedinti,j;
for(i=0;i for(j=0;j<10;j++); } /********************************* 初始化MPU **********************************/ voidInitCpu(void) { TMOD=0x0; TH0=0; TL0=0; TR0=1; ET0=1; EX1=1; EA=1; TCON|=0x04; } /**************************** welcome游戏选择界面 /**********************/ voidwelcome() { Lcd_WriteStr(0,0,"欢迎来玩"); Lcd_WriteStr(0,1,"俄罗斯方块"); Lcd_WriteStr(0,2,"设置按K1"); Lcd_WriteStr(0,2,"开玩按K2"); } /*************俄罗斯方块部分 /****************************** 画墙壁,初始化界面 *******************************/ voidDrawBoard(void) { unsignedcharn; for(n=0;n<12;n++) { Lcd_Rectangle(3*n,0,3*n+2,2,1); Lcd_Rectangle(3*n,60,3*n+2,62,1); } for(n=0;n<20;n++) { Lcd_Rectangle(0,3*n,2,3*n+2,1); Lcd_Rectangle(33,3*n,35,3*n+2,1); } Lcd_WriteStr(4,0,"经典游戏"); Lcd_WriteStr(3,2,"Score: "); Lcd_WriteStr(3,3,"Level: "); } /*********************************** 游戏结束处理 ************************************/ voidGameOver(void) { if((SysFlag&(1< =0) Lcd_WriteStr(3,1,"YouFail"); else Lcd_WriteStr(3,1,"YouPass"); } unsignedintcodeMaskTab[16]={ 0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080, 0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000 }; /********************************** 根据积木图标左下坐标X,Y来画出积木图标 ***********************************/ voidDrawSign(structJimuTemp,unsignedcharDrawMode) { unsignedcharm,n; for(m=0;m<4;m++) for(n=0;n<4;n++) { if((Temp.dat&MaskTab[4*m+n])! =0) Lcd_Rectangle(Temp.x+n*3,Temp.y-2-3*m,Temp.x+n*3+2,Temp.y-3*m,DrawMode); } } /******************************** 将积木图标值融入num数据中 也即把积木图标固定,无法再下降 *********************************/ FixSign(void) { unsignedcharm,n; for(m=0;m<4;m++)//行循环 for(n=0;n<4;n++)//列循环 { if((Sign[0].dat&MaskTab[4*m+n])! =0) { num[20-(Sign[0].y-2)/3+m]|=MaskTab[11-Sign[0].x/3-n]; } } } /******************************** 判断积木图标中方块是否与障碍方块重合 *********************************/ unsignedcharCheckIf(void) { unsignedcharm,n; for(m=0;m<4;m++)//行循环 for(n=0;n<4;n++)//列循环 { if((Sign[1].dat&MaskTab[4*m+n])! =0) { if((num[20-(Sign[1].y-2)/3+m]&MaskTab[11-Sign[1].x/3-n])! =0) return0; } } return1; } /******************************** 判断积木图标是否可以继续下降一格 ********************************/ unsignedcharCheckIfDown(void) { Sign[1]=Sign[0];// Sign[1].y+=3;//假设下降一格 returnCheckIf(); } /******************************** 判断积木图标是否可以向左移动 *********************************/ unsignedcharCheckIfLeft(void) { Sign[1]=Sign[0]; Sign[1].x-=3; returnCheckIf(); } /******************************** 判断积木图标是否可以向右移动 *********************************/ unsignedcharCheckIfRight(void) { Sign[1]=Sign[0]; Sign[1].x+=3; returnCheckIf(); } /******************************** 判断是否可以旋转 *********************************/ unsignedcharCheckIfRoll(void) { unsignedchari; unsignedintTemp; Sign[1]=Sign[0]; if(++Sign[1].change>3) Sign[1].change=0; i=Sign[1].type*4+Sign[1].change; Temp=(unsignedint)Block[i][0]<<8; Temp=Temp|Block[i][1]; Sign[1].dat=Temp; returnCheckIf(); } /******************************** 寻找满格的行并做消除处理 最多寻找4个满行并做消除 *********************************/ voidDelFull(void) { unsignedcharm,n; unsignedcharTemp; unsignedcharFlag=0; Temp=(Sign[0].y-2)/3; if(Temp>=20)//防止越过了下边界 Temp=1; else Temp=20-Temp; for(n=Temp+3;n>=Temp;n--)//积木图标的最顶行开始寻找满行比较有利于运算 { if(num[n]==0xfff) { Flag=1; for(m=n+1;m<=19;m++) { num[m-1]=num[m]; } num[m]=0x801; Score++;//每找到一个满行,则分数加1 } } if(Flag)//为加速而设置并判断的标志,有已固定的积木有满格消行变化则重画积木界面 { for(m=Temp;m<=19;m++)//为加速,不必要重第一行重画起,只需要从积木图标最下行开始往上的重画 for(n=1;n<=10;n++) { if((num[m]&MaskTab[n])==0) { if(Lcd_ReadPixel(30-(n-1)*3,57-(m-1)*3)! =0)//为加速而做的读象素操作 { Lcd_Rectangle(30-(n-1)*3,57-(m-1)*3,30-(n-1)*3+2,57-(m-1)*3+2,0); } } else { if(Lcd_ReadPixel(30-(n-1)*3,57-(m-1)*3)==0)//为加速而做的读象素操作 { Lcd_Rectangle(30-(n-1)*3,57-(m-1)*3,30-(n-1)*3+2,57-(m-1)*3+2,1); } } } } } /******************************* 随机产生一个积木图标放到预产生区域并显示出来 ********************************/ voidCreatSign(void) { unsignedcharn; unsignedintTemp; DrawSign(Sign[2],0);//先清除 n=Random()*28; Temp=(unsignedint)Block[n][0]<<8; Temp=Temp|Block[n][1]; Sign[2].dat=Temp; Sign[2].x=45; Sign[2].y=4*3+2; Sign[2].type=n/4; Sign[2].change=n%4; DrawSign(Sign[2],1);//后画出 } voidPrintScore(void) { unsignedcharStr[3]; Str[0]=(Score/10)|0x30; Str[1]=(Score%10)|0x30; Str[2]=0; Lcd_WriteStr(6,2,Str); } voidPrintLevel(void) { unsignedcharStr[3]; Str[0]=(Level/10)|0x30; Str[1]=(Level%10)|0x30; Str[2]=0; Lcd_WriteStr(6,3,Str); } /******************************** 游戏的具体过程,也是俄罗斯方块算法的关键部分 *********************************/ voidGamePlay(void) { unsignedcharm,n; unsignedintTemp; SysFlag|=1< InitRandom(TL0); Lcd_WriteStr(3,1,"Playing"); PrintScore(); PrintLevel(); CreatSign(); while (1) { if((SysFlag&(1< { SysFlag&=~(1< Sign[0]=Sign[2]; CreatSign(); Sign[0].x=12; Sign[0].y=14; for(m=0;m<4;m++)//行循环 { for(n=0;n<4;n++)//列循环 { if((Sign[0].dat&MaskTab[15-m*4-n])==0) break; } if(n==4) Sign[0].y-=3; }//将积木图标出现置顶 for(m=0;m<4;m++)//行循环 for(n=0;n<4;n++)//列循环 { if((Sign[0].dat&MaskTab[4*m+n])! =0) { if((num[20-(Sign[0].y-2)/3+m]&MaskTab[11-Sign[0].x/3-n])! =0) SysFlag|=1< } } if((SysFlag&(1< =0) break;//如果产生新的积木图标中的方块与已固定好的方块重合,则死亡。 游戏结束 DrawSign(Sign[0],1); } if((CheckIfLeft())&&(K3==0))//左 { DrawSign(Sign[0],0); Sign[0].x-=3; DrawSign(Sign[0],1); } if((CheckIfRight())&&(K4==0))//右 { DrawSign(Sign[0],0); Sign[0].x+=3; DrawSign(Sign[0],1); } if((CheckIfDown())&&(K2==0))//下 { DrawSign(Sign[0],0); Sign[0].y+=3; DrawSign(Sign[0],1); } if((CheckIfRoll())&&(K1==0))//翻转 { DrawSign(Sign[0],0); if(++Sign[0].change>3) Sign[0].change=0; m=Sign[0].type*4+Sign[0].change; Temp=(unsignedint)Block[m][0]<<8; Temp=Temp|Block[m][1]; Sign[0].dat=Temp; DrawSign(Sign[0],1); } if((SysFlag&(1< =0) continue; Delay(500); if(++DelayCnt>=2*(11-Level)) { DelayCnt=0; if(CheckIfDown())//判断是否能继续下降一格 { DrawSign(Sign[0],0); Sign[0].y+=3; DrawSign(Sign[0],1); } else { FixSign(); DelFull(); PrintScore(); if(Score>=PASSSCORE) { SysFlag&=~(1< break;//跳出玩游戏过程 } SysFlag|=1< } } } } voidMain() { InitCpu();//初始化CPU Lcd_Reset();//初始化LCD屏 Lcd_Clear(0);//清屏 Lcd_Reset();//初始化LCD屏 Lcd_Clear(0);//清屏 DrawBoard();//画界面 GamePlay();//玩游戏 GameOver();//游戏结束 Lcd_Reset();//初始化LCD屏 Lcd_Clear(0);//清屏 } ********************12864.h文件*************************** ****************************************************** #include sbitRS=P2^0;//并行的指令/数据选择信号,H数据,L命令 sbitRW=P2^1;//并行读写选择信号,H读,L写 sbitE=P2^2;//并行使能端,H有效,L无效 sbitPSB=P2^3;//并/串接口选择,H并,L串 sbitRET=P2^4;//复位,L有效 #defineLcdDataP0 unsignedcharLcd_CheckBusy(void) { unsignedcharBusy; LcdData=0xff; RS=0; RW=1; E=1; _nop_(); Busy=LcdData&0x80; E=0; returnBusy; } /
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- C51 单片机 12864 液晶 按键 制作 俄罗斯方块 源码