|
今天給51黑電子論壇的壇友共享一個(gè)好東東,使用51單片機(jī)實(shí)現(xiàn)的俄羅斯方塊游戲, 能虛擬串口控制,實(shí)用性還是比較高的,下面是仿真原理圖,大家可以下載附件后直接用proteus打開。
0.png (25.86 KB, 下載次數(shù): 84)
下載附件
2016-9-27 17:50 上傳
0.png (45.53 KB, 下載次數(shù): 128)
下載附件
2016-9-27 17:50 上傳
0.png (66.86 KB, 下載次數(shù): 113)
下載附件
2016-9-27 17:51 上傳
所有資料包含仿真工程文件和源碼下載:
俄羅斯方塊游戲.rar
(422.54 KB, 下載次數(shù): 14)
2016-9-27 17:53 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
俄羅斯方塊源程序:
- //--------------------------------------------------------------------------//
- // 源程序大公開 //
- // (c) Copyright 2001-2025 xuwenjun //
- // All Rights Reserved //
- // V1.00 //
- //--------------------------------------------------------------------------//
- //標(biāo) 題: 俄羅斯方塊程序 ? //
- //文件名: xwj_fk.c //
- //版 本: V1.00 //
- //修改人: 徐文軍 E-mail:xuwenjun@21cn.com //
- //日 期: 05-13 //
- //描 述: 俄羅斯方塊程序 ? //
- //聲 明: //
- // 以下代碼僅免費(fèi)提供給學(xué)習(xí)用途,但引用或修改后必須在文件中聲明出處. //
- // 如用于商業(yè)用途請(qǐng)與作者聯(lián)系. E-mail:xuwenjun@21cn.com //
- // 有問題請(qǐng)mailto xuwenjun@21cn.com 歡迎與我交流! //
- //--------------------------------------------------------------------------//
- //老版本: 無 老版本文件名: //
- //創(chuàng)建人: 徐文軍 E-mail:xuwenjun@21cn.com //
- //日 期: 05-13 //
- //描 述: //
- // 1、功能完整,直接使用 //
- // 2、模塊獨(dú)立性強(qiáng),移植方便,外部?jī)Hinit和move函數(shù),修改顯示和輸入即可 //
- // 3、對(duì)減少內(nèi)存占用、盡量減少屏幕操作進(jìn)行適當(dāng)優(yōu)化 //
- // 4、新方塊生成高度隨機(jī),絕對(duì)無規(guī)律 //
- // 5、仿真環(huán)境為Keil7.5+Proteus6.5,可以聯(lián)機(jī)也可脫機(jī)運(yùn)行 //
- // CODE SIZE = 1845 ---- //
- // CONSTANT SIZE = 326 ---- //
- // DATA SIZE = 16 19 //
- // IDATA SIZE = 50 ---- //
- // BIT SIZE = 1 1 //
- //--------------------------------------------------------------------------//
- #include <stdlib.h>
- #include "xwj_lcd16.h" // 字符液晶控制函數(shù)聲明 //
- #include "xwj_lcd6963.h" // T6963C 公用函數(shù)
- #include "xwj_hlkey.h" // P1口行列式鍵盤 //
- #include "xwj_serial.h" //串口函數(shù)集
- #include "change.h" //數(shù)制轉(zhuǎn)換
- #include "xwj_fk.h" //俄羅斯方塊程序
- #define ulong unsigned long
- #define uint unsigned int
- #define uchar unsigned char
- extern void delay(unsigned int x);
- //----------------俄羅斯方塊內(nèi)部函數(shù)----------------------------------------//
- void fk_dot(uchar x,uchar y); //顯示1個(gè)方塊點(diǎn)
- void fk_cldot(uchar x,uchar y); //清除1個(gè)方塊點(diǎn)
- void fk_show(void); //顯示分?jǐn)?shù)
- void fk_reffk(void); //刷新方塊
- void fk_refnew(void); //刷新預(yù)覽方塊
- void fk_refline(yy); //刷新1行背景
- bit fk_chk(void); //沖突檢查
- void fk_new(void); //產(chǎn)生新方塊
- void fk_add(void); //方塊合并
- /*
- //-----------------俄羅斯方塊公用函數(shù)--------------------------------------//
- void fk_init(void); //方塊初始化
- void fk_move(unsigned char mode); //移動(dòng)方塊
- */
- //-------------------------------------------------------------------------//
- #define FULLMAP 0x0fff /*掩碼*/
- #define LINEGUAN 20 /*20行過一關(guān)*/
- #define NEWX 15 /*預(yù)覽方塊X位置*/
- #define NEWY 12 /*預(yù)覽方塊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; //總行數(shù)
- uchar speed; //速度
- uchar moven; //速度相關(guān)計(jì)數(shù)器
- uchar automapn; //隨機(jī)方塊的行數(shù)
- bit fk_run; //俄羅斯方坑蝸吩誦?
-
- uchar code fk_mod[][4][4]={ //方塊模型號(hào),4個(gè)方向,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]={
- "不錯(cuò)! ","真棒! ","好極啦!","太棒了!",
- };
- //--------------------------------------------------------------------------//
- void fk_dot(uchar x,uchar y) //顯示1個(gè)方塊點(diǎn)
- {
- printat(x*3+1, 241-(y-4)*12,"■");
- }
- //--------------------------------------------------------------------------//
- void fk_cldot(uchar x,uchar y) //清除1個(gè)方塊點(diǎn)
- {
- // printat(x*3+1, 241-(y-4)*12,"□");
- printat(x*3+1, 241-(y-4)*12,"┘");
- }
- //--------------------------------------------------------------------------//
- void fk_show(void) //顯示分?jǐn)?shù)
- {
- printat(50, 12,chnint(score,1));
- printat(60, 12,"00");
- printat(40, 12,"得分:");
- printat(54,36,chnint(line,1));
- printat(40, 36,"行數(shù):");
- printat(54,60,chnchar(speed,1));
- printat(40,60,"速度:");
- printat(54,84,chnchar(automapn,1));
- printat(40,84,"關(guān)數(shù):");
- }
- //--------------------------------------------------------------------------//
- void fk_reffk(void) //刷新方塊
- {
- uchar i,j;
- uchar temp;
- //----------------------------------------------//清除原來的方塊
- for (i=0;i<4;i++)
- {
- temp=(fk_mod[fk_type][fk_oldr][i]);
- for (j=fk_oldx;j<fk_oldx+4;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][i]);
- for (j=fk_x;j<fk_x+4;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) //刷新預(yù)覽方塊
- {
- uchar i,j;
- uchar temp;
- //----------------------------------------------//預(yù)覽方塊
- for (i=0;i<4;i++)
- {
- temp=(fk_mod[fk_newtype][fk_newr][i]);
- for (j=NEWX;j<NEWX+4;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][i])<<fk_x)+(fk_map[fk_y+i])) != (((fk_mod[fk_type][fk_r][i])<<fk_x)|(fk_map[fk_y+i])) )
- neq=1;
- }
- return(neq);
- }
- //--------------------------------------------------------------------------//
- void fk_new(void) //產(chǎn)生新方塊
- {
- 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(); //刷新預(yù)覽方塊
- 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][i])<<fk_x;
- full <<= 1;
- 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<LINEMAX+4+fullline;i++) //上面行下移
- {
- if ((i < LINEMAX+4)&&(fk_map[i-fullline]!=fk_map[i]))
- {
- fk_map[i-fullline]=fk_map[i];
- 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; //更新分?jǐn)?shù)、行數(shù)
- score += (1<<fullline)-1;
- printat(46,180,strmap[fullline-1]); //夸獎(jiǎng)
- fk_show(); //顯示分?jǐn)?shù)
- fk_new(); //產(chǎn)生新方塊
- }
- else
- {
- if (fk_y > LINEMAX-10) //在最高位置碰撞且不能消行則游戲結(jié)束
- printat(46,180,"加油啊!"); //加油啊
- if (fk_y > LINEMAX-6) //在最高位置碰撞且不能消行則游戲結(jié)束
- printat(46,180,"糟糕了!"); //糟糕了
- if (fk_y==LINEMAX) //在最高位置碰撞且不能消行則游戲結(jié)束
- fk_run=0; //方塊初始化
- else
- fk_new(); //產(chǎn)生新方塊
- }
- }
- //--------------------------------------------------------------------------//
- void fk_init(void) //方塊初始化
- {
- uchar i;
- fk_run = 0;
- moven=0;
- Lcd6963Cls();
- Lcd6963Rec(0,0,152,255);
- Lcd6963ChHz(0); //切換到16X16點(diǎn)陣
- printat(2, 16,"歡迎光臨文君閣");
- printat(2, 48,"請(qǐng)按鍵選擇:");
- printat(2, 80,"-----------------");
- printat(2, 96,"7左旋 8右旋 9右旋");
- printat(2, 112,"4左移 5右旋 6右移");
- printat(2, 128,"4速度 5開始 6關(guān)數(shù)");
- printat(2, 144,"1左移 2下移 3右移");
- printat(2, 160,"-----------------");
- Lcd6963ChHz(1); //切換到12X12點(diǎn)陣
- printat(46,180,"歡迎使用");
- fk_show(); //顯示分?jǐn)?shù)
- while (~fk_run)
- {
- fk_move(); //等待設(shè)置速度關(guān)數(shù)開始
- delay(10);
- }
- for (i=0;i<4;i++)
- {
- fk_map[i]=0xffff; //背景映象
- } delay(3000);
- for (i=4;i<LINEMAX+4;i++)
- {
- if (i<(automapn+4))
- fk_map[i]=rand()-1|~FULLMAP; //背景映象
- else
- fk_map[i]=~FULLMAP; //背景映象
- fk_refline(i); //刷新1行背景
- }
- fk_show(); //顯示分?jǐn)?shù)
- // fk_new(); //產(chǎn)生新方塊
- }
- //--------------------------------------------------------------------------//
- void fk_move(void) //移動(dòng)方塊
- {
- unsigned char temp;
- if(KeyTest()) //檢查有無按鍵
- {
- putinbuf(KeyGetCode()); //按鍵碼輸入接收緩沖區(qū)
- }
- if (checkin())
- {
- temp=getbyte();
- if (temp!=0) Lcd16WrCharhh(12,0,temp);
- if (temp!=0) Lcd16WrChar(15,0,temp);
- putchar(temp);
- }
- else
- temp=0xff; //無鍵設(shè)為無效鍵用于下移方塊
- 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++; //有沖突取消操作,執(zhí)行碰撞組合
- fk_add(); //方塊合并 //產(chǎn)生新方塊
- }
- }
- else //方塊到底也執(zhí)行碰撞組合
- {
- fk_add(); //方塊合并
- }
- }
- else //初始化時(shí)
- {
- fk_new(); //產(chǎn)生新方塊
- }
- break;
- case 0: //下移到底
- while((fk_y>0)&&~(fk_chk())) //一直下移直到?jīng)_突
- {
- fk_y--;
- }
- moven=1;
- fk_y++; //恢復(fù)到未沖突位置
- break;
- case 3: //右移
- case 6: //右移
- if (fk_run) //游戲中右移
- {
- if(fk_x<12)
- {
- fk_x++;
- if(fk_chk())
- fk_x--;//有沖突取消操作
- }
- }
- else //初始化時(shí)
- {
- automapn++;
- automapn &= 0x0f;
- fk_show(); //顯示分?jǐn)?shù)
- }
- break;
- case 1: //左移
- case 4: //移
- if (fk_run) //游戲中左移
- {
- if(fk_x>0)
- {
- fk_x--;
- if(fk_chk())
- fk_x++;//有沖突取消操作
- }
- }
- else //初始化時(shí)
- {
- speed++;
- speed &= 0x07;
- fk_show(); //顯示分?jǐn)?shù)
- }
- break;
- case 9: //右轉(zhuǎn)
- case 8: //右轉(zhuǎn)
- case 5: //右轉(zhuǎn)
- if (fk_run) //游戲中右轉(zhuǎn)
- {
- fk_r++;
- if(fk_chk())
- fk_r--; //有沖突取消操作
- fk_r &= 0x03;
- }
- else //初始化時(shí)
- {
- fk_run = 1;
- }
- break;
- case 7: //左轉(zhuǎn)
- if (fk_run) //游戲中右轉(zhuǎn)
- {
- fk_r--;
- if(fk_chk())
- fk_r++; //有沖突取消操作
- fk_r &= 0x03;
- }
- else //初始化時(shí)
- {
- fk_run = 1;
- }
- break;
- }
- if((fk_run)&& ((fk_x!=fk_oldx)||(fk_y!=fk_oldy)||(fk_r!=fk_oldr)) )
- {
- fk_reffk(); //刷新顯示
- }
- rand();
- }
- /*
- // ---------------------------------------------- // 32字節(jié)
- void delay(uint x)
- {
- uint i,j;
- for (i=0; i<x;i++) {
- for (j=0;j<102; j++) ;
- }
- }
- //--------------------------------------------------------------------------//
- void main(void) // 測(cè)試用
- {
- serial_init();
- Lcd6963Init(); //Lcd6963復(fù)位
- Lcd16Reset(); //Lcd16復(fù)位
- Serial_main(); // 串口測(cè)試用主函數(shù)
- Lcd16main(); //Lcd16臨時(shí)測(cè)試主程序
- Lcd6963main(); //Lcd6963測(cè)試用
- fk_init(); //方塊初始化
- while(1)
- {
- if (~fk_run)
- fk_init(); //方塊初始化
- fk_move(); //移動(dòng)方塊
- delay(10);
- }
- }
- */
復(fù)制代碼
|
|