完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
转一个工程
给大家共享一个好东东,使用51单片机实现的俄罗斯方块游戏, 能虚拟串口控制,实用性还是比较高的,下面是仿真原理图,大家可以下载附件后直接用proteus打开。 //--------------------------------------------------------------------------// // 源程序大公开 // // (c) Copyright 2001-2025 xuwenjun // // All Rights Reserved // // V1.00 // //--------------------------------------------------------------------------// //标 题: 俄罗斯方块程序 ? // //文件名: xwj_fk.c // //版 本: V1.00 // //修改人: 徐文军 E-mail:xuwenjun@21cn.com // //日 期: 05-13 // //描 述: 俄罗斯方块程序 ? // //声 明: // // 以下代码仅免费提供给学习用途,但引用或修改后必须在文件中声明出处. // // 如用于商业用途请与作者联系. E-mail:xuwenjun@21cn.com // // 有问题请mailto xuwenjun@21cn.com 欢迎与我交流! // //--------------------------------------------------------------------------// //老版本: 无 老版本文件名: // //创建人: 徐文军 E-mail:xuwenjun@21cn.com // //日 期: 05-13 // //描 述: // // 1、功能完整,直接使用 // // 2、模块独立性强,移植方便,外部仅init和move函数,修改显示和输入即可 // // 3、对减少内存占用、尽量减少屏幕操作进行适当优化 // // 4、新方块生成高度随机,绝对无规律 // // 5、仿真环境为Keil7.5+Proteus6.5,可以联机也可脱机运行 // // CODE SIZE = 1845 ---- // // CONSTANT SIZE = 326 ---- // // DATA SIZE = 16 19 // // IDATA SIZE = 50 ---- // // BIT SIZE = 1 1 // //--------------------------------------------------------------------------// #include #include "xwj_lcd16.h" // 字符液晶控制函数声明 // #include "xwj_lcd6963.h" // T6963C 公用函数 #include "xwj_hlkey.h" // P1口行列式键盘 // #include "xwj_serial.h" //串口函数集 #include "change.h" //数制转换 #include "xwj_fk.h" //俄罗斯方块程序 #define ulong unsigned long #define uint unsigned int #define uchar unsigned char extern void delay(unsigned int x); //----------------俄罗斯方块内部函数----------------------------------------// void fk_dot(uchar x,uchar y); //显示1个方块点 void fk_cldot(uchar x,uchar y); //清除1个方块点 void fk_show(void); //显示分数 void fk_reffk(void); //刷新方块 void fk_refnew(void); //刷新预览方块 void fk_refline(yy); //刷新1行背景 bit fk_chk(void); //冲突检查 void fk_new(void); //产生新方块 void fk_add(void); //方块合并 /* //-----------------俄罗斯方块公用函数--------------------------------------// void fk_init(void); //方块初始化 void fk_move(unsigned char mode); //移动方块 */ //-------------------------------------------------------------------------// #define FULLMAP 0x0fff /*掩码*/ #define LINEGUAN 20 /*20行过一关*/ #define NEWX 15 /*预览方块X位置*/ #define NEWY 12 /*预览方块Y位置*/ #define LINEMAX 21 /*屏幕最高21行*/ uint idata fk_map[LINEMAX+4]; //背景映象 uchar fk_x,fk_y,fk_r; //方块左右、高度、方向 uchar fk_type; //方块形状 uchar fk_oldx,fk_oldy,fk_oldr; //方块上次左右、高度、方向 uchar fk_newtype,fk_newr; //新方块形状、方向 uint score; //总分 uint line; //总行数 uchar speed; //速度 uchar moven; //速度相关计数器 uchar automapn; //随机方块的行数 bit fk_run; //俄罗斯方坑蜗吩诵? uchar code fk_mod[][4][4]={ //方块模型号,4个方向,4行 0,0,7,2,0,1,3,1,0,0,2,7,0,2,3,2, //_|_ 0,0,6,3,0,1,3,2,0,0,6,3,0,1,3,2, //_|~ 0,0,3,6,0,2,3,1,0,0,3,6,0,2,3,1, //~|_ 0,0,7,4,0,3,1,1,0,0,1,7,0,2,2,3, //|__ 0,0,7,1,0,1,1,3,0,0,4,7,0,3,2,2, //__| 0,0,0,15,1,1,1,1,0,0,0,15,1,1,1,1, //____ 0,0,3,3,0,0,3,3,0,0,3,3,0,0,3,3, //田字 }; uchar code strmap[4][9]={ "不错! ","真棒! ","好极啦!","太棒了!", }; //--------------------------------------------------------------------------// void fk_dot(uchar x,uchar y) //显示1个方块点 { printat(x*3+1, 241-(y-4)*12,"■"); } //--------------------------------------------------------------------------// void fk_cldot(uchar x,uchar y) //清除1个方块点 { // printat(x*3+1, 241-(y-4)*12,"□"); printat(x*3+1, 241-(y-4)*12,"┘"); } //--------------------------------------------------------------------------// void fk_show(void) //显示分数 { printat(50, 12,chnint(score,1)); printat(60, 12,"00"); printat(40, 12,"得分:"); printat(54,36,chnint(line,1)); printat(40, 36,"行数:"); printat(54,60,chnchar(speed,1)); printat(40,60,"速度:"); printat(54,84,chnchar(automapn,1)); printat(40,84,"关数:"); } //--------------------------------------------------------------------------// void fk_reffk(void) //刷新方块 { uchar i,j; uchar temp; //----------------------------------------------//清除原来的方块 for (i=0;i<4;i++) { temp=(fk_mod[fk_type][fk_oldr]); for (j=fk_oldx;j if(temp&0x01) { fk_cldot(j,fk_oldy+i); } temp>>=1; } } //----------------------------------------------//显示新的方块 for (i=0;i<4;i++) { temp=(fk_mod[fk_type][fk_r]); for (j=fk_x;j if(temp&0x01) { fk_dot(j,fk_y+i); } temp>>=1; } } fk_oldx=fk_x;fk_oldy=fk_y;fk_oldr=fk_r; //保存新方块位置 } //--------------------------------------------------------------------------// void fk_refnew(void) //刷新预览方块 { uchar i,j; uchar temp; //----------------------------------------------//预览方块 for (i=0;i<4;i++) { temp=(fk_mod[fk_newtype][fk_newr]); for (j=NEWX;j if(temp&0x01) { fk_dot(j,NEWY+i); } else { fk_cldot(j,NEWY+i); } temp>>=1; } } } //--------------------------------------------------------------------------// void fk_refline(yy) //刷新1行背景 { uchar i; uint temp; if (yy>=4) { temp=fk_map[yy]; for (i=0;i<12;i++) { if ((temp&0x01) !=0) fk_dot(i,yy); else fk_cldot(i,yy); temp >>= 1; } } } //--------------------------------------------------------------------------// bit fk_chk(void) //冲突检查 { uchar i; bit neq=0; for (i=0;i<4;i++) { if ( (((fk_mod[fk_type][fk_r])< } return(neq); } //--------------------------------------------------------------------------// void fk_new(void) //产生新方块 { srand(rand()+fk_x+fk_y+fk_r); fk_oldx=fk_x=5; fk_oldy=fk_y=LINEMAX; fk_type = fk_newtype; fk_oldr=fk_newr; fk_newtype = rand()%7; fk_newr=rand()%4; fk_refnew(); //刷新预览方块 if (fk_run) fk_reffk(); //刷新显示 } //--------------------------------------------------------------------------// void fk_add(void) //方块合并 { uchar i,j; uchar full=0x00; uchar fulltemp; uchar fullline=0x00; for (i=0;i<4;i++) //方块合并 { fk_map[fk_y+i] |= (fk_mod[fk_type][fk_r])< if ((fk_y+i >= 4) && (fk_map[fk_y+i] == 0xffff)) //满行 { full |= 0x01; } } if (full != 0) //有满行 { for (j=0;j<3;j++) //消行闪烁3次 { delay(300); fulltemp=full; for (i=0;i<4;i++) //4行 { if ((fulltemp&0x08) != 0) { fk_map[fk_y+i] ^= FULLMAP; } fk_refline(fk_y+i); fulltemp <<= 1; } } fulltemp=full; for (i=fk_y;i if ((i < LINEMAX+4)&&(fk_map[i-fullline]!=fk_map)) { fk_map[i-fullline]=fk_map; fk_refline(i-fullline); } if ((i >= LINEMAX+4)&&(fk_map[i-fullline]!=~FULLMAP)) { fk_map[i-fullline]=~FULLMAP; //背景映象 fk_refline(i-fullline); } if ((fulltemp&0x08) != 0) { fullline++; } fulltemp <<= 1; } if (((line+fullline)/LINEGUAN) != (line/LINEGUAN))//每20行速度+1 speed ++; line += fullline; //更新分数、行数 score += (1< fk_show(); //显示分数 fk_new(); //产生新方块 } else { if (fk_y > LINEMAX-10) //在最高位置碰撞且不能消行则游戏结束 printat(46,180,"加油啊!"); //加油啊 if (fk_y > LINEMAX-6) //在最高位置碰撞且不能消行则游戏结束 printat(46,180,"糟糕了!"); //糟糕了 if (fk_y==LINEMAX) //在最高位置碰撞且不能消行则游戏结束 fk_run=0; //方块初始化 else fk_new(); //产生新方块 } } //--------------------------------------------------------------------------// void fk_init(void) //方块初始化 { uchar i; fk_run = 0; moven=0; Lcd6963Cls(); Lcd6963Rec(0,0,152,255); Lcd6963ChHz(0); //切换到16X16点阵 printat(2, 16,"欢迎光临文君阁"); printat(2, 48,"请按键选择:"); printat(2, 80,"-----------------"); printat(2, 96,"7左旋 8右旋 9右旋"); printat(2, 112,"4左移 5右旋 6右移"); printat(2, 128,"4速度 5开始 6关数"); printat(2, 144,"1左移 2下移 3右移"); printat(2, 160,"-----------------"); Lcd6963ChHz(1); //切换到12X12点阵 printat(46,180,"欢迎使用"); fk_show(); //显示分数 while (~fk_run) { fk_move(); //等待设置速度关数开始 delay(10); } for (i=0;i<4;i++) { fk_map=0xffff; //背景映象 } delay(3000); for (i=4;i if (i<(automapn+4)) fk_map=rand()-1|~FULLMAP; //背景映象 else fk_map=~FULLMAP; //背景映象 fk_refline(i); //刷新1行背景 } fk_show(); //显示分数 // fk_new(); //产生新方块 } //--------------------------------------------------------------------------// void fk_move(void) //移动方块 { unsigned char temp; if(KeyTest()) //检查有无按键 { putinbuf(KeyGetCode()); //按键码输入接收缓冲区 } if (checkin()) { temp=getbyte(); if (temp!=0) Lcd16WrCharhh(12,0,temp); if (temp!=0) Lcd16WrChar(15,0,temp); putchar(temp); } else temp=0xff; //无键设为无效键用于下移方块 temp -= '0'; switch(temp) { default: if (--moven) //游戏难度 break; else { moven=(252>>speed)+2; } case 2: //下移 if (fk_run) //游戏中下移 { if(fk_y>0) { fk_y--; if(fk_chk()) { fk_y++; //有冲突取消操作,执行碰撞组合 fk_add(); //方块合并 //产生新方块 } } else //方块到底也执行碰撞组合 { fk_add(); //方块合并 } } else //初始化时 { fk_new(); //产生新方块 } break; case 0: //下移到底 while((fk_y>0)&&~(fk_chk())) //一直下移直到冲突 { fk_y--; } moven=1; fk_y++; //恢复到未冲突位置 break; case 3: //右移 case 6: //右移 if (fk_run) //游戏中右移 { if(fk_x<12) { fk_x++; if(fk_chk()) fk_x--;//有冲突取消操作 } } else //初始化时 { automapn++; automapn &= 0x0f; fk_show(); //显示分数 } break; case 1: //左移 case 4: //移 if (fk_run) //游戏中左移 { if(fk_x>0) { fk_x--; if(fk_chk()) fk_x++;//有冲突取消操作 } } else //初始化时 { speed++; speed &= 0x07; fk_show(); //显示分数 } break; case 9: //右转 case 8: //右转 case 5: //右转 if (fk_run) //游戏中右转 { fk_r++; if(fk_chk()) fk_r--; //有冲突取消操作 fk_r &= 0x03; } else //初始化时 { fk_run = 1; } break; case 7: //左转 if (fk_run) //游戏中右转 { fk_r--; if(fk_chk()) fk_r++; //有冲突取消操作 fk_r &= 0x03; } else //初始化时 { fk_run = 1; } break; } if((fk_run)&& ((fk_x!=fk_oldx)||(fk_y!=fk_oldy)||(fk_r!=fk_oldr)) ) { fk_reffk(); //刷新显示 } rand(); } /* // ---------------------------------------------- // 32字节 void delay(uint x) { uint i,j; for (i=0; i } } //--------------------------------------------------------------------------// void main(void) // 测试用 { serial_init(); Lcd6963Init(); //Lcd6963复位 Lcd16Reset(); //Lcd16复位 Serial_main(); // 串口测试用主函数 Lcd16main(); //Lcd16临时测试主程序 Lcd6963main(); //Lcd6963测试用 fk_init(); //方块初始化 while(1) { if (~fk_run) fk_init(); //方块初始化 fk_move(); //移动方块 delay(10); } } */
|
|
相关推荐
|
|
厉害
|
|
|
|
|
|
嵌入式学习-飞凌嵌入式ElfBoard ELF 1板卡-LCD显示图片编程示例之介绍mmap
551 浏览 0 评论
《DNESP32S3使用指南-IDF版_V1.6》第二章 常用的C语言知识点
910 浏览 0 评论
【RA-Eco-RA2E1-48PIN-V1.0开发板试用】(第三篇)ADC采集+PWM输出
575 浏览 0 评论
《DNK210使用指南 -CanMV版 V1.0》第四十五章 人脸识别实验
572 浏览 0 评论
1221 浏览 0 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
11769 浏览 31 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-23 18:33 , Processed in 0.765587 second(s), Total 82, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号