1.上一讲的代码
#include <reg52.h>
sbit ADDR2 = P1^2;
sbit ADDR1 = P1^1;
sbit ADDR0 = P1^0;
sbit ENLED = P1^4;
sbit ADDR3 = P1^3;
sbit BEEP = P1^6;
sbit KEY13 = P2^4;
sbit KEY14 = P2^5;
sbit KEY15 = P2^6;
#define TIMES 300 //此例程的主循环里循环一次所要花费的时间比以往的例程要多,所以按键的times判断需要减少到300,不然还是500的话需要我们长按住一段时间才会响应功能代码
unsigned char code LedChar[16]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E};//数码管状态值初始化
unsigned char LedBuff[6]={0xFF, 0xFF, 0xBF, 0xBF, 0xFF, 0xFF};//初始化数码管显示缓存区
unsigned char man=30,woman=30;//初始化男人和女人的钱
void UPDATE_LED()//更新数码管显示缓存区
{
LedBuff[5]=LedChar[man/10];
LedBuff[4]=LedChar[man%10];
LedBuff[1]=LedChar[woman/10];
LedBuff[0]=LedChar[woman%10];
}
void SEG_task()//数码管显示函数
{
static unsigned char i=0;
P0=0xFF;//端口状态全部熄灭数码管里的LED达到刷新作用
switch(i)
{
case 0:
ADDR2 = 0;ADDR1 = 0;ADDR0 = 0;P0=LedBuff[0];i++;break;
case 1:
ADDR2 = 0;ADDR1 = 0;ADDR0 = 1;P0=LedBuff[1];i++;break;
case 2:
ADDR2 = 0;ADDR1 = 1;ADDR0 = 0;P0=LedBuff[2];i++;break;
case 3:
ADDR2 = 0;ADDR1 = 1;ADDR0 = 1;P0=LedBuff[3];i++;break;
case 4:
ADDR2 = 1;ADDR1 = 0;ADDR0 = 0;P0=LedBuff[4];i++;break;
case 5:
ADDR2 = 1;ADDR1 = 0;ADDR0 = 1;P0=LedBuff[5];i=0;break;
}
}
void KEY13_task()
{
static unsigned char key_up=1;
static unsigned int times=0; //用来记录进入过按键判断语句的次数
if(key_up==0)
{
times++;
if(times>=TIMES&&KEY13==1)
{
times=0;
man+=3; //男人的钱加3块
woman-=3; //女人的钱减3块
UPDATE_LED();//更新数码管显示缓存区
}
}
key_up=KEY13;
}
void KEY14_task()
{
static unsigned char key_up=1;
static unsigned int times=0; //用来记录进入过按键判断语句的次数
if(key_up==0)
{
times++;
if(times>=TIMES&&KEY14==1)
{
times=0;
man+=1; //男人的钱加1块
woman-=1; //女人的钱减1块
UPDATE_LED();//更新数码管显示缓存区
}
}
key_up=KEY14;
}
void KEY15_task()
{
static unsigned char key_up=1;
static unsigned int times=0; //用来记录进入过按键判断语句的次数
if(key_up==0)
{
times++;
if(times>=TIMES&&KEY15==1)
{
times=0;
man-=2; //男人的钱减2块
woman+=2; //女人的钱加2块
UPDATE_LED();//更新数码管显示缓存区
}
}
key_up=KEY15;
}
void BEEP_ON(unsigned char x)
{
unsigned int i,time;
for(time=0;time<2000;time++)//“time<2000”决定鸣叫的时间
{
if(x==1)BEEP=!BEEP;
else BEEP=0;
for(i=0;i<30;i++);
}
}
void main()
{
unsigned int i,x;//做循环和延时用
ADDR3 = 1;//使能三八译码器
ENLED = 0;//
P2 = 0xFE;//让K13,K14,K15能具备有被拉低的条件先
UPDATE_LED();//更新数码管显示缓存区
while(1)
{
SEG_task(); //数码管显示函数
KEY13_task();//K13按键的任务
KEY14_task();//K14按键的任务
KEY15_task();//K15按键的任务
if(man>=45 || woman>=45)//只要其中一方的钱到达45块及以上就结束游戏,程序进入死循环
{
if(man>=45){LedBuff[1]=0xFF; LedBuff[0]=0xFF;}//不再显示女人的钱
else {LedBuff[5]=0xFF; LedBuff[4]=0xFF;} //不再显示男人的钱
while(1)
{
P0=0xFF; //熄灭所有数码管
BEEP_ON(1); //蜂鸣器鸣叫一段时间
for(i=0;i<300;i++) //让数码管显示一段时间
{
SEG_task();
for(x=0;x<200;x++);//加此延时是为了让数码管显示亮一点,不然仅让“SEG_task();”循环,显示就会暗一些
}
}
}
}
}“man+=3;”就是“man= man+3;”的简化书写。
2.感言
我们现在是模块化编程了,在了解了美女与男人的游戏题目后,阅读主函数都清晰明朗很多。
这个题目的要求就像是全国电子设计竞赛一样,需要我们一步一步地完成每个模块功能,包括以后做产品项目,模块化编程是为了灵活运用和增加可读性,以后在做其他项目时遇到相似的要求我们拿来主义即可,维护起来也方便,但大家都需要习惯写很详细的注释才行。
在本讲代码的基础上其实也可以简单地改写成一个篮球简易计分器的功能,如果大家能自己实现的出来,以后去打球拿块开发板去计分也可骗骗一些不懂的同学,认为这是很高大上的玩意。
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程