标题:
单片机俄罗斯方块源码 通过LCD12864实现
[打印本页]
作者:
Richardwg
时间:
2018-4-26 17:37
标题:
单片机俄罗斯方块源码 通过LCD12864实现
俄罗斯方块通过LCD12864实现,全部源码,超清晰注释.
0.jpg
(40.86 KB, 下载次数: 25)
下载附件
2018-4-26 18:32 上传
单片机源程序如下:
/*******************************************************
* 文件名称:Tetris.c
* 单 片 机:STC89C52RC
* 简 述:使用LCD12864显示的俄罗斯方块程序
* 功 能:计分,下一个方块预览,欢迎结束界面,长按连续左右移,暂停(按键Left+Turn)
* 作 者:刘琦
* 完成日期:2015年4月21日
* IO口设定:按键
sbit key_sr_left=P3^7;
sbit key_sr_turn=P3^6;
sbit key_sr_right=P3^5;
sbit key_sr_down=P3^4;
LCD12864
sbit RS_Port=P1^0;
sbit RW_Port=P1^1;
sbit E_Port=P2^5;
sbit PSB_Port=P1^2;
sbit RST_Port=P1^4;
数码管锁存器
sbit dula=P2^6;
sbit wela=P2^7;
*******************************************************/
/*****************************头文件区*****************************************************/
#include<reg52.h>
//#include"STC15F2K60S2.h"
#include"task_key.h"
#include"task_activation.h"
#include"12864b.h"
#include"TaskBlock.h"
#include"Block.h"
/*****************************宏定义区*****************************************************/
//需要判断是否刷新的任务总数
//1KeyLeft,2KeyTurn,3KeyRight,4KeyDown,5TaskGoingDown,6KeyPause
#define NUM_TASK_FLAG 7
//需要定时刷新的任务总数
//1TaskGoingDown,2KeyService
#define NUM_TASK_REFRESH 3
//刷新频率
#define TIME_PER_SEC 200 //每次进入中断的频率,200Hz
#define TIME_CLOCK 11059200 //晶振频率
#define TIME_KEY_SERVICE_50HZ TIME_PER_SEC/50 //按键服务频率,0.02s
#define TIME_TASKGOINGDOWN_2HZ TIME_PER_SEC/2 //下落频率,0.5s
/******************************子函数声明区***********************************************/
void initial_myself(void);
void initial_peripheral(void);
void delay100ms(void);
/******************************全局变量定义区***********************************************/
unsigned char uc_state=1;//状态标示:1欢迎界面,2等待开始界面,3下落界面,4死亡界面,5暂停界面
enum Block{S1,S2,Z1,Z2,L1,L2,L3,L4,J1,J2,J3,J4,I1,I2,O1,T_1,T_2,T_3,T_4}enumBlock;//方块编号
unsigned char ucBlockNow=0;//当前方块
unsigned char ucBlockNext=0;//下一个方块
unsigned char ucFlagScreenChange=1;//界面变更标志,界面更改时置1,激活task_activation
unsigned char ucCoordinate[2];//方块的旋转点坐标,横H,竖S
unsigned char xdata ucxMap[10][20];//整张屏幕的标记地图,用来记录未消除方块位置,有方块则为1
unsigned char ucxBlockPosition[4][2];//方块的4个小方块坐标,[0][0],[0][1]为旋转点坐标H,S
unsigned int uc_delay_task_cnt[NUM_TASK_REFRESH];//任务刷新延迟
unsigned char uc_flag_taskrefresh[NUM_TASK_FLAG];//任务刷新标志
unsigned long int ucScore=0;//得分
/******************************主函数开始***********************************************/
void main(void)
{
unsigned char i=0;
initial_myself();
delay100ms();
initial_peripheral();
while(1)
{
if(ucFlagScreenChange==1)//界面变更标志为1时,进行任务激活,防止一直刷新界面
{
task_activation(uc_state);
ucFlagScreenChange=0;
}
if(uc_delay_task_cnt[2]==0)//20HZ频率刷新key_service
{
task_key_service();
ET0=0;//在中断中也有可能变化的变量在更改前时先关闭中断
uc_delay_task_cnt[2]=TIME_KEY_SERVICE_50HZ;//延迟重置
ET0=1;
}
if(uc_flag_taskrefresh[5]&&uc_delay_task_cnt[1]==0)//需要时,2HZ频率刷新TaskGoingDown
{
if(!TaskGoingDown())//下落失败
{
//将当前方块位置写入Map
for(i=0;i<4;i++)
{
ucxMap[ ucxBlockPosition[i][0] ][ ucxBlockPosition[i][1] ]=1;
}
//调用消除方块函数
TaskClear();
}
ET0=0;//在中断中也有可能变化的变量在更改前时先关闭中断
uc_delay_task_cnt[1]=TIME_TASKGOINGDOWN_2HZ;//延迟重置
ET0=1;
}
}
}
//中断函数
void timer0(void) interrupt 1
{
unsigned char i;
TR0=0;
TH0=255-TIME_CLOCK/TIME_PER_SEC/12/256;
TL0=255-TIME_CLOCK/TIME_PER_SEC/12%256;
//task_delay[]减到0时,相应的函数准备就绪
for(i=0;i<NUM_TASK_REFRESH;i++)
{
if(uc_delay_task_cnt[i]!=0)//延迟不为0时才减
{uc_delay_task_cnt[i]--;};
}
task_key_scan();//按键扫描函数,放在中断中,保证准时扫描
TR0=1;
}
//初始化区
void initial_myself(void)//第一区 初始化单片机
{
unsigned char i;
for(i=0;i<NUM_TASK_REFRESH;i++)uc_delay_task_cnt[i]=0;//初始化让所有任务就绪
TMOD=0X21; //定时器0为16位不自动重装,用来定时;定时器1为8位自动重装,用来产生随机数
TH0=255-TIME_CLOCK/TIME_PER_SEC/12/256;
TL0=255-TIME_CLOCK/TIME_PER_SEC/12%256;
TH1=0;
TL1=0;
}
void initial_peripheral(void) //第二区 初始化外围
{
Lcd_Init();//初始化12864
EA=1; //开总中断
ET0=1; //允许定时器0中断,定时器1无需开启中断
TR0=1; //启动定时器0
TR1=1; //启动定时器1
}
void delay100ms(void) //@11.0592MHz
{
unsigned char i, j, k;
;
;
i = 5;
j = 52;
k = 195;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
复制代码
/*******************************************************
* 文件名称:TaskBlock.c
* 单 片 机:STC89C52RC
* 简 述:方块子程序,包含,下落,出新,消除,检测
* 作 者:刘琦
* 完成日期:2015年4月21日
*******************************************************/
#include<reg52.h>
#include"Tetris.h"
#include"Block.h"
#include"tetris.h"
#include"Score.h"
/*******************************************************
* 函 数 名:TaskCheck(void)
* 功能描述:检测
* 函数说明:检测左右移,下落,出新,旋转
* 输入参数:无
* 返 回 值:成功失败标示,ucReturn
*******************************************************/
unsigned char TaskCheck(void)
{
unsigned char ucReturn=0;
unsigned char i=0;
//加入检测部分,包括边界检测,碰撞检测
//边界检测
for(i=0;i<4;i++)
{
if(ucxBlockPosition[i][0]>=0&&ucxBlockPosition[i][0]<=9 //检测左右
&&ucxBlockPosition[i][1]>=0&&ucxBlockPosition[i][1]<=19) //检测上下
{
ucReturn=1;
}
else
{
ucReturn=0;
return ucReturn;//如果边界检测失败,就不进行下面检测,直接返回失败
}
}
//碰撞检测
for(i=0;i<4;i++)
{
if(ucxMap[ ucxBlockPosition[i][0] ][ ucxBlockPosition[i][1] ]!=0)//与地图标记位置进行比较
{
ucReturn=0;
return ucReturn;
}
}
return ucReturn;
}
/*******************************************************
* 函 数 名:unsigned char TaskGoingDown(void)
* 功能描述:方块下落
* 函数说明:
* 输入参数:无
* 返 回 值:ucResult,1无碰撞,0碰撞
*******************************************************/
unsigned char TaskGoingDown(void)
{
unsigned char ucCheck=0;
unsigned char ucResult=0;
ucCoordinate[1]++; //旋转点坐标,竖S+1
WriteBlockCoordinate(); //将其他三个小方块坐标写入数组
ucCheck=TaskCheck(); //检测碰撞
if(ucCheck) //无碰撞
{
ucCoordinate[1]--; //坐标复位
ChangeBlock(0); //在老位置消除方块,只刷新有改变的位置,加快显示速度
ucCoordinate[1]++; //坐标+1
ChangeBlock(1); //在新位置画方块
ucResult=1;
}
else //有碰撞,则不变
{
ucCoordinate[1]--;
WriteBlockCoordinate();
ucResult=0;
}
return ucResult;
}
/*******************************************************
* 函 数 名:unsigned char TaskComingNew(void)
* 功能描述:方块出新
* 函数说明:
* 输入参数:无
* 返 回 值:ucResult,1成功,0失败
*******************************************************/
unsigned char TaskComingNew(void)
{
unsigned char ucCheck=0;
unsigned char ucResult=0;
//写入当前方块的相关信息
switch(ucBlockNow)
{
case 0:
enumBlock=S1;
ucCoordinate[0]=4;
ucCoordinate[1]=0;
break;
case 1:
enumBlock=Z1;
ucCoordinate[0]=4;
ucCoordinate[1]=0;
break;
case 2:
enumBlock=L1;
ucCoordinate[0]=4;
ucCoordinate[1]=1;
break;
case 3:
enumBlock=J1;
ucCoordinate[0]=4;
ucCoordinate[1]=1;
break;
case 4:
enumBlock=I1;
ucCoordinate[0]=5;
ucCoordinate[1]=0;
break;
case 5:
enumBlock=O1;
ucCoordinate[0]=5;
ucCoordinate[1]=0;
break;
case 6:
enumBlock=T_1;
ucCoordinate[0]=4;
ucCoordinate[1]=0;
break;
default:
break;
}
//检测碰撞
WriteBlockCoordinate();
ucCheck=TaskCheck();
if(ucCheck) //成功
{
ChangeSmallBlock(0); //将预览的方块清除
ucBlockNext=TL1%7; //产生随机数,作为预览方块
ChangeBlock(1); //画新的方块
ChangeSmallBlock(1); //画新的预览方块
ucBlockNow=ucBlockNext;
ucResult=1;
}
else
{
ucResult=0;
}
return ucResult;
}
/*******************************************************
* 函 数 名:void TaskClear(void)
* 功能描述:消除满行
* 函数说明:消除满行,并出新
* 输入参数:无
* 返 回 值:无
*******************************************************/
void TaskClear(void)
{
char i=0,j=0,n=0;
unsigned char m=0;
unsigned char k=0;
unsigned char flag_man=1,flag_kong=1,flag_clear=0;//满行、空行、待清除标志
unsigned char man[4],count=0; //满行位置数组,满行数量
unsigned char kong=20; //空行位置
unsigned char oldkong=20; //用来储存旧的空行位置
unsigned char ucResult=0;
//标记出来满行及第一个空行
for(i=19;i>=0;i--)
{
for(j=9;j>=0;j--)
{
if(ucxMap[j][i]==0)
{
flag_man=0;
}
else
{
flag_kong=0;
}
}
if(flag_man==1)
{
flag_clear=1;//激活消除标记
man[k]=i;//标记满行
count++;
k++;
}
else if(flag_kong==1)
{
kong=i;
break;//检测到第一个空行,就退出循环
}
flag_man=1;//将满行标志复位
flag_kong=1;
}
//计分
switch(count)
{
case 0:
ucScore=ucScore+100;
break;
case 1:
ucScore=ucScore+200;
break;
case 2:
ucScore=ucScore+400;
break;
case 3:
ucScore=ucScore+700;
break;
case 4:
ucScore=ucScore+1100;
break;
default:
break;
}
oldkong=kong;
//消除满行
if(flag_clear==1)
{
while(count!=0)//至少有一个满行,才进行消除
{
//逐行下移
for(m=0;m<man[count-1]-kong-1;m++)
{
for(n=9;n>=0;n--)
……………………
…………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
俄罗斯方块全部源码.zip
(147.88 KB, 下载次数: 73)
2018-4-26 17:36 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
fparabola
时间:
2018-7-2 16:17
谢谢分享
作者:
fparabola
时间:
2018-7-2 16:17
可以移植到iap15上吗
作者:
蝶舞狂雷
时间:
2019-5-27 21:27
谢谢楼主的分享
作者:
shenparty
时间:
2019-6-27 15:40
感谢分享
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1