欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136
標題:
51單片機16x16點陣俄羅斯方塊程序 帶詳細注釋
[打印本頁]
作者:
想進步要學習
時間:
2020-1-21 20:10
標題:
51單片機16x16點陣俄羅斯方塊程序 帶詳細注釋
一年前做的小玩意了,硬件丟失了,程序還在,以前都是寫在一個文件內(nèi),翻出來分成幾個文件,程序注釋寫的很詳細,希望對初入單片機的師兄有所幫助
1.png
(264.72 KB, 下載次數(shù): 79)
下載附件
2020-1-21 20:09 上傳
單片機源程序如下:
//=========================================================================================================================================
//軟件功能:俄羅斯方塊
//硬件描述:最小系統(tǒng)+4x(8x8點陣)+ (1x(HC154)+3x(74HC14D)) + 1x(HC595)
//程序描述:74595.c中有串進并出程序
// delay.c中有延遲函數(shù)
// dispaly.c中有開始畫面顯示函數(shù)、點陣顯示函數(shù)、數(shù)碼管顯示函數(shù)
// random.c中有隨機圖案緩存函數(shù)
// anjian.c中按鍵函數(shù)、圖案觸底函數(shù)、消行函數(shù)、旋轉(zhuǎn)圖案數(shù)據(jù)改變函數(shù)、顯示清除函數(shù)
// timinit.c中中斷初始化函數(shù)
//功能概括描述:16x16點陣用于顯示、5個按鍵有旋轉(zhuǎn)按鍵、上、下、左、右按鍵、數(shù)碼管用于顯示得分
// 上按鍵用于開始游戲鍵、下按鍵用于圖案加速下落鍵、左、右按鍵用于圖案左右移動
// 有圖案觸底判斷、圖案左右碰壁判斷、消行判斷
//=========================================================================================================================================
#include "reg52.h" //52頭文件
#include "stdlib.h" //隨機函數(shù)rand()調(diào)用頭文件
#include "74595.h" //74HC595使用所需
#include "delay.h"
#include "display.h"
#include "random.h"
#include "anjian.h"
#include "timinit.h"
#define uchar unsigned char
#define uint unsigned int
sbit KS=P3^4; //下鍵
//sbit BEEP=P2^7; //蜂鳴器
uchar code DUANMA[11]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; //數(shù)碼管顯示0~9,0xff不顯示;
uint code KAITOU[3][8]={{0x3c10,0x2820,0x3bfc,0x2480,0x2520,0x3bfc,0x2020,0x20a8}, //陳發(fā)兩字;
{0x2124,0x2020,0x2060,0x2020,0x0000,0x0000,0x0210,0x0428},
{0x0844,0x1080,0x3ffc,0x03f0,0x04a0,0x0840,0x10a0,0x2110}};
uint HUANCUN[16],CUN[16],XZA[4],KKK; //顯示數(shù)組HUANCUN[16],存儲隨機圖案數(shù)組CUN[16]
uchar q,n,k,m=1,x=0,t=0,JILV=1,a=0,ZUOJIA=7,G=7,XUANZUAN=0,R=0; //ZUOJIA對應16*16的豎,左到右編號為0~15
//=========================================================================================================================================
void main() //主函數(shù)
{
init(); //初始化
KT(); //開頭顯示啟動游戲界面
while(1)
{
a=rand()%6; //隨機數(shù)0~5
XIANSI(); //點陣顯示函數(shù)
if(TR0==0){ //判斷定時器是否關著
SMG(); //數(shù)碼管顯示函數(shù)
if(KEY==0){ //如果開始鍵按下
QC_HC(); //清除緩存顯示函數(shù)
KKK=0; //分數(shù)清零
TR0=1; //啟動定時器
}
}
}
}
//=========================================================================================================================================
//變量說明:t:用于計時,配合向下按鍵的判斷,來決定圖案的下落速度
// CBN:圖案下落速度變量
// x,m,JILV:初始狀態(tài)m=JILV=1,x=0(x是HUANCUN[]里的數(shù)據(jù)編號,從0開始)
//程序描述:先忽略按鍵部分,理順開始按鍵(KEY)按下后的整個流程
// 判斷定時時間CBN與t的值是否相等,到時間先判斷圖案還能不能下落,既觸底(m=JILV),如果沒觸底清除當前圖案,顯示下落一行后的圖案
// 初始狀態(tài)是m=JILV=1,會先運行一次XH();和AJ_PD();
// 添加按鍵功能,首先調(diào)用按鍵函數(shù)ANJIAN();
// 如果按鍵有變化那么ZUOJIA和XUANZUAN都將發(fā)生改變,此時不管t為何值都要執(zhí)行相應程序
// 根據(jù)ZUOJIA的改變來變動CUN[]的圖案數(shù)據(jù)
// 如果CUN[]改變,要從新調(diào)用AJ_PD();求JILV的值
// 如果旋轉(zhuǎn)按鍵狀態(tài)XUANZUAN改變,變動CUN[]里的數(shù)據(jù),判斷此時的圖案會不會與原來的“積木”重疊,如果重疊,CUN[]變回原來的數(shù)據(jù),AJ_PD();重新調(diào)用
//=========================================================================================================================================
void timer() interrupt 1
{
static uchar CBN; //定義變量CBN用于控制圖案下落的速度
TH0=(65536-5000)/256; //定時器初始化
TL0=(65536-5000)%256;
t++; //計時(t)累加
ANJIAN(); //調(diào)用按鍵子程序
if(KS==0){ //判斷向下按鍵(KS)有沒有按
if(t>30)t=0; //如果計時(t)大于30,t清零重新開始計時
CBN=20; //減短圖案下落的時間
}else
CBN=80; //圖案平時下落速度
/*----------------------------------------------------------------------------------------------------------------------------------------*/
if((t==CBN)||(ZUOJIA!=G)||(XUANZUAN!=R)){ //計時(t)到了所設定的時間“或”左右和旋轉(zhuǎn)按鍵三鍵中的一個按了一下
if(m==JILV){ //如果圖案下落到預先掃描的指定行
x=0; //各種變量初始化
m=1;
G=7;
R=0;
JILV=1;
ZUOJIA=7;
XUANZUAN=0;
XIAOHAN(); //調(diào)用消行子程序
/*---------------------------------------------------------------------------------*/
if(HUANCUN[0]!=0x0000){ //點陣頂部是否亮起,如果亮起表示該結(jié)束了
QC_HC(); //清除緩存
HUANCUN[2]=0x0ff0; //結(jié)束顯示笑臉圖案
HUANCUN[3]=0x1008;
HUANCUN[4]=0x2424;
HUANCUN[5]=0x2a54;
HUANCUN[6]=0x2004;
HUANCUN[7]=0x2004;
HUANCUN[8]=0x2004;
HUANCUN[9]=0x2004;
HUANCUN[10]=0x2244;
HUANCUN[11]=0x2184;
HUANCUN[12]=0x1008;
HUANCUN[13]=0x0ff0;
TR0=0; //定時器關閉
return; //跳出中斷
}
/*---------------------------------------------------------------------------------*/
XH(); //圖案對應數(shù)組
AJ_PD(); //從上至下行掃描得到指定行變量(JILV)
}else{ //如果圖案還在下落
m--; //變量(m)控制圖案數(shù)組與緩存數(shù)組的數(shù)據(jù)運算
x=m-1; //緩存變量(x)返回上個圖案值
for(n=0;n<m;n++){
HUANCUN[x]&=(~CUN[n]); //上個圖案清除
x--;
}
x=m; //緩存變量(x)加一為下個圖案顯示做準備
m++;
}
/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
if(ZUOJIA!=G){ //如果左右鍵狀態(tài)發(fā)生一次改變
for(n=0;n<16;n++){
if(ZUOJIA>G){ //如果是右鍵發(fā)生的變動
CUN[n]>>=1;
}else
CUN[n]<<=1;
}
AJ_PD(); //重新掃描求JILV
x--;
m--;
G=ZUOJIA;
}
if(XUANZUAN!=R){ //旋轉(zhuǎn)鍵狀態(tài)改變一次
x--;
m--;
XH(); //調(diào)用XH()子程序,為了顯示旋轉(zhuǎn)后的圖案,注意:這時圖案是在正中間,即ZUOJIA=7的位置
HPP(); //調(diào)用旋轉(zhuǎn)子程序
for(n=0;n<m;n++){
if(CUN[n]!=0){
if((HUANCUN[x]&CUN[n])!=0){ //如果旋轉(zhuǎn)后的圖案會和已存在圖案重合
if(XUANZUAN==0)XUANZUAN=4; //4種旋轉(zhuǎn)圖案對應狀態(tài)值改回未變圖案前的狀態(tài)
else XUANZUAN--;
for(n=0;n<4;n++){ //圖案也要變回去
CUN[n]=XZA[n];
}
break;
}
}
x--;
}
AJ_PD(); //調(diào)用掃描子程序,求新的JILV
x=m-1;
R=XUANZUAN; //把旋轉(zhuǎn)圖案狀態(tài)值賦值給變量R,只有旋轉(zhuǎn)按鈕再次按下,才會再進來
}
/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
for(n=0;n<m;n++){
HUANCUN[x]|=CUN[n]; //把將要顯示的圖案對應的數(shù)組送入緩存數(shù)組
x--;
}
m++;
t=0; //計時變量清零
}
}
//=========================================================================================================================================
復制代碼
#include "anjian.h"
//=========================================================================================================================================
extern uchar XUANZUAN,ZUOJIA,JILV,m,n,x,k,G;
extern uint HUANCUN[16],CUN[16],XZA[4],KKK;
//=========================================================================================================================================
//程序描述:判斷右鍵(YOU)按下否?
// 先把圖案對應豎位置的狀態(tài)變量ZUOJIA改變,再判斷圖案可不可以移動,如果不可以ZUOJIA改回來
// m,x確實有點繞
// 左鍵同上
// 旋轉(zhuǎn)按鍵按下,改變圖案狀態(tài)變量XUANZUAN,保存當前圖案CUN[]到XZA[]
//=========================================================================================================================================
void ANJIAN() //按鍵子程序
{
static uchar i=1,s=1,j=1; //定義三個靜態(tài)變量i,s,j表示右,左,旋轉(zhuǎn)按鍵的狀態(tài)值
if(YOU!=s){ //如果右鍵狀態(tài)值發(fā)生改變
if(s!=0){ //判斷狀態(tài)值是否為0,如果不是,說明右鍵按下了
ZUOJIA++; //圖案未動,圖案對應豎的狀態(tài)值先加一
m--; //x,m數(shù)組間交換變化所定義的變量
x=m-1;
for(n=0;n<m;n++){
if(CUN[n]!=0){ //如果CUN[n]為0,就不用浪費時間判斷什么了
if(((HUANCUN[x]&((CUN[n]|(CUN[n]/2))-CUN[n]))!=0)||((CUN[n]&0x0001)!=0)){ //CUN[n]/2右移一位
m++; //CUN[n]|(CUN[n]/2)右移一位后和之前的數(shù)或,(CUN[n]|(CUN[n]/2))-CUN[n]或了的數(shù)再減去最開始的數(shù),就是右移后的圖案
ZUOJIA--; //HUANCUN[x]&((CUN[n]|(CUN[n]/2))-CUN[n])!=0上面的數(shù)再和顯示數(shù)組里的數(shù)與,判斷運算后的數(shù)是否為0
s=YOU; //上面的運算就是判斷”圖案向右移動是否會碰到已經(jīng)存在的圖案“
return; //(CUN[n]&0x0001)!=0這句判斷圖案有沒有碰到右邊的邊界
} //m++;ZUOJIA--;進入if說明圖案不能變,那么前面改變的值都要改回來,s=YOU;既然程序要跳出來了,按鍵的狀態(tài)值也要改變的,防止又進來了
}
x--;
}
x=m;
m++;
}
s=YOU;
}
if(ZUO!=i){ //左鍵類同右鍵
if(i!=0){
ZUOJIA--;
m--;
x=m-1;
for(n=0;n<m;n++){
if(CUN[n]!=0){
if(((HUANCUN[x]&((CUN[n]|(CUN[n]<<1))-CUN[n]))!=0)||(CUN[n]>=0x8000)){
m++;
ZUOJIA++;
i=ZUO;
return;
}
}
x--;
}
x=n;
m++;
}
i=ZUO;
}
if(XZ!=j){ //旋轉(zhuǎn)按鍵
if(j!=0){
XUANZUAN=(XUANZUAN+1)%4; //如果旋轉(zhuǎn)按鍵按下了,這里4種圖案是按逆時針變化
for(n=0;n<4;n++){
XZA[n]=CUN[n]; //圖案先保存在數(shù)組XZA[]中
}
}
j=XZ;
}
}
//=========================================================================================================================================
//思維說明:在XH()程序中知道圖案細分成15種,目的是要寫一個程序讓這15種圖案下落后碰到下面的"積木"停下來(記下這一行的編號存在變量JILV里)
//程序描述:圖案保存在數(shù)組CUN[]中,CUN[0]是圖案的底部,CUN[1]是圖案中部,CUN[2]是圖案上部,CUN[3]可以不作考慮
// 16x16點陣有16行,以圖案當前在點陣處在的位置開始與點陣已經(jīng)存在“積木”做運算,判斷再下落是否會重疊
// 首先,判斷CUN[0]是否觸底了,即,(HUANCUN[n]&CUN[0])!=0
// 其次,判斷CUN[1]是否觸底了,(CUN[1]|CUN[0])-CUN[0]這是取CUN[1]和CUN[0]在垂直方向上沒有重合的部分
// 最后,判斷CUN[2]是否觸底了,這種情況只有一種圖案會發(fā)生
// 總結(jié),一種圖案出現(xiàn)改變也好,都要調(diào)用這個函數(shù)找出觸底位置
// 當n>1后,運行一次for就判斷一個圖案分成3段的觸底情況
//=========================================================================================================================================
void AJ_PD() //從上至下行掃描得到指定行變量(JILV)子程序
{
for(n=m-1;n<16;n++){ //掃描緩存數(shù)組
if((HUANCUN[n]&CUN[0])!=0) break; //如果圖案底層觸底,跳出掃描
else
if((n>0)&&((HUANCUN[n-1]&((CUN[1]|CUN[0])-CUN[0]))!=0)) break; //否則,圖案底層上面層觸底,跳出掃描
if((n>1)&&((HUANCUN[n-2]&((CUN[2]|CUN[1])-CUN[1]))!=0)) break; //圖案底層上面層的上面層觸底,跳出掃描
}
JILV=n+1; //記錄JILV
}
//=========================================================================================================================================
//我看到一個教程里說不要在for(i=0;i<6;i++)里面改變變量(i)的值,但我不知道會出什么問題
//程序描述:從點陣的最下行向上開始判斷
//=========================================================================================================================================
void XIAOHAN()
{ //消行子程序
uint i;
uchar u;
i=KKK;
for(n=16;n>0;n--){ //掃描16行
if(HUANCUN[n-1]==0xffff){ //如果某行全亮
for(u=n;u>1;u--){
HUANCUN[u-1]=HUANCUN[u-2]; //上面一行覆蓋下面一行
}
HUANCUN[0]=0x0000;
n++;
KKK++;
} //最上面一行清零
} //16行全掃描后,結(jié)束子程序
if(KKK==(i+2))KKK+=2; //如果同時消除2行加4分
else
if(KKK==(i+3))KKK+=6; //如果同時消除3行加9分
else
if(KKK==(i+4))KKK+=12; //如果同時消除4行加16分
else
if(KKK>(i+4))KKK+=20; //如果同時消除5行加25分
}
//=========================================================================================================================================
//思維說明:XH();中CUN[]只存改變后的圖案,位置是在ZUOJIA=7,現(xiàn)在要寫段程序根據(jù)ZUOJIA的值改變CUN[]的數(shù)據(jù),即左右移動后的圖案數(shù)據(jù)CUN[]
//程序描述:比如當ZUOJIA=6時,CUN[]前4位數(shù)據(jù)(圖案只用到前4位)都左移1位
// 如果圖案碰到了邊界,重新調(diào)用XH();函數(shù)一次,CUN[]數(shù)據(jù)移動到能移動的最遠位置
//=========================================================================================================================================
void HPP() //旋轉(zhuǎn)子程序一部分
{
if(ZUOJIA<=7){ //如果圖案在點陣的左半邊
for(k=0;k<(7-ZUOJIA);k++){ //7-ZUOJIA表示圖案需要移動的位數(shù)
for(n=0;n<4;n++){ //圖案左移一位
CUN[n]<<=1;
if(CUN[n]>=0x8000){ //在該圖案左移的過程中,判斷有沒有碰到點陣左邊的邊界
XH(); //調(diào)用XH()子程序,該圖案在ZUOJIA=7的位置;
for(n=0;n<4;n++){ //該圖案左移k+1個位,因為是k=0圖案開始一位位左移,所以是k+1
CUN[n]<<=k+1;
}
ZUOJIA=6-k; //圖案對應豎變量也要跟著變化,6-k即7-(k+1)
G=6-k; //圖案的豎位置變了,左右按鍵的狀態(tài)變量也要隨之改變
return; //跳出子程序
}
}
}
}else{ //否則圖案在點陣右半邊
for(k=0;k<(ZUOJIA-7);k++){ //以下類同上面
for(n=0;n<4;n++){
CUN[n]>>=1;
if((CUN[n]&0x0001)!=0){
XH();
for(n=0;n<4;n++){
CUN[n]>>=k+1;
}
ZUOJIA=8+k;
G=8+k;
return;
}
}
}
}
}
//=========================================================================================================================================
void QC_HC() //緩存(顯示)數(shù)組清零
{
for(n=0;n<16;n++){
HUANCUN[n]=0x0000;
}
}
//=========================================================================================================================================
復制代碼
所有資料51hei提供下載:
俄羅斯方塊.rar
(73.91 KB, 下載次數(shù): 51)
2020-1-21 20:10 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
作者:
jz573079513
時間:
2020-1-27 20:37
新年快樂~
歡迎光臨 (http://www.raoushi.com/bbs/)
Powered by Discuz! X3.1