51單片機項目實戰(zhàn)---貪吃蛇(測試版)
一、元器件
1、AT89C51
本文引用地址:http://m.butianyuan.cn/article/201808/385449.htm關于51單片機就不在嗦了,相信大家都已經(jīng)很熟悉了。
2、8x8點陣
點陣里面就是一些二極管啦,通過縱橫交叉連接,橫8豎8,每個交叉點都接一個二極管。這里給大家找到一個點陣的實物圖
我想大家看到這個圖就應該知道如何去點亮一個點陣了。假如要點亮最左上角那個,那么9號引腳拉高,13號引腳拉低,這樣既可。
二、原理圖
三、項目分析
1、首先定義一個結構體
struct snake{
unsigned char x[20];
unsigned char y[20];
unsigned char length;
unsigned char direction;
}snk;
數(shù)組x,y分別存放每一個點的橫縱坐標,length為蛇的長度,direction為蛇前進的方向
2、坐標系:點陣的左下角為點(0,0),橫縱坐標都是正向增長,P2控制橫坐標;P0控制縱坐標。通過坐標可以找到點陣中點的位置,然后將其點亮
假設現(xiàn)在有第2個點的坐標x[2] = 1, y[2] = 2,那么點亮這個點的方式為
P2 = 0x04; //0000 0100
P0 = 0xfb; //1111 1011
3、按鍵產(chǎn)生外部中斷,在中斷里判斷按下那個方向get_direction(),并且同時設置坐標set_location()
4、定時器每隔1s就應該更新位置,因為蛇要不停的前進。定時器不需要更新方向,因為方向只有按鍵才會改動,定時器用前一步的方向
5、關于點的位置更新方式
1)、向上移動
后面的點去覆蓋前面的點,第一個點用新坐標表示x[0]不變,y[0]+1
2)、向下移動
后面的點去覆蓋前面的點,第一個點用新坐標表示x[0]不變,y[0]-1
3)、向左移動
后面的點去覆蓋前面的點,第一個點用新坐標表示x[0]-1,y[0]不變
4)、向右移動
后面的點去覆蓋前面的點,第一個點用新坐標表示x[0]+1,y[0]不變
6、關于邊界問題:
1)、任何一個點的橫坐標 0 = x[i] 8
2)、任何一個點的縱坐標 0 = y[i] 8
3)、第一個點在移動的時候不能和其他點重復,否則就自己追尾了
7、關于原理圖按鍵的設計
貪吃蛇要求系統(tǒng)能迅速響應按鍵,因此輪詢的方式并不可取,只有靠外部中斷。然而51只有2個外部中斷,我們起碼需要4個方向鍵,這樣就不能一個按鍵配一個外部中斷,通過使用4輸入與門,將所有按鍵狀態(tài)集合在一起,然后送給外部中斷0。我們將4個按鍵都接在與門,只要有一個按下,那么與門的輸出就會產(chǎn)生一個下降沿,從而產(chǎn)生外部中斷。
四、源代碼
main.c
#include snake.h
int error = 0;
int time=0;
void interrupt_init()
{
EA = 0; //關閉總中斷
IT0 = 1; //外部中斷0方式 下降沿
EA = 1; //開啟總中斷
EX0 = 1; //開啟外部中斷
}
void timer_init()
{
EA = 0; //關總中斷
ET0 = 1; //開定時器0中斷
TMOD = 0x02; //定時器0工作方式2
TL0 = 6; //定時250us
TH0 = 6;
EA = 1; //開總中斷
TR0 = 1; //開始定時
}
int main()
{
// unsigned char tempx, tempy;
// unsigned char i,j;
interrupt_init();
timer_init();
snk_init();
while(1)
{
//如果位置錯了就重新初始化蛇
if(error)
snk_init();
//點亮點陣
matrix();
}
}
void inter0() interrupt 0
{
//按鍵產(chǎn)生外部中斷,獲取新的方向
get_direction();
//設置新的位置
error = set_location();
// matrix();
}
void timer0() interrupt 1
{
time++;
//定時器為250us 積累4000次就是1s
if(time == 4000)
{
//每隔1s都需要重新設置位置,讓蛇前進
error = set_location();
time = 0;
}
}
snake.c
點擊(此處)折疊或打開
#include snake.h
//蛇的結構體,x為橫坐標,y為縱坐標,length為蛇的長度,direction為蛇的前進方向
struct snake{
unsigned char x[20];
unsigned char y[20];
unsigned char length;
unsigned char direction;
}snk;
void matrix()
{
unsigned char i;
int count=500;
//關閉所有的點
P2 = 0x00;
P0 = 0xff;
//根據(jù)蛇每一個點的坐標,將對應的點陣點亮
for(i=0; i
{
P2 = 1
P0 = ~(1
}
}
void snk_init()
{
//初始化坐標,總共4個點(3,0) (2,0) (1,0) (1,0)
snk.x[0] = 3;
snk.y[0] = 0;
snk.x[1] = 2;
snk.y[1] = 0;
snk.x[2] = 1;
snk.y[2] = 0;
snk.x[3] = 0;
snk.y[3] = 0;
//初始長度4
snk.length = 4;
//初始移動方向 向右
snk.direction = RIGHT;
//點亮點陣
matrix();
}
void get_direction()
{
//通過按鍵的狀態(tài)獲取方向
if(!up)
snk.direction = UP;
if(!down)
snk.direction = DOWN;
if(!left)
snk.direction = LEFT;
if(!right)
snk.direction = RIGHT;
}
int set_location()
{
unsigned char i;
int err = 0;
if(snk.direction == UP)
{
for(i=snk.length-1; i>0; i--)
{
snk.x[i] = snk.x[i-1];
snk.y[i] = snk.y[i-1];
}
//如果向上運動,第0個點的橫坐標不變,縱坐標加1
snk.x[0] = snk.x[0];
snk.y[0] = snk.y[0] + 1;
}
else if(snk.direction == DOWN)
{
for(i=snk.length-1; i>0; i--)
{
snk.x[i] = snk.x[i-1];
snk.y[i] = snk.y[i-1];
}
//如果向下運動,第0個點的橫坐標不變,縱坐標減1
snk.x[0] = snk.x[0];
snk.y[0] = snk.y[0] - 1;
}
else if(snk.direction == LEFT)
{
for(i=snk.length-1; i>0; i--)
{
snk.x[i] = snk.x[i-1];
snk.y[i] = snk.y[i-1];
}
//如果向左運動,第0個點的橫坐標減1,縱坐標不變
snk.x[0] = snk.x[0] - 1;
snk.y[0] = snk.y[0];
}
else
{
for(i=snk.length-1; i>0; i--)
{
snk.x[i] = snk.x[i-1];
snk.y[i] = snk.y[i-1];
}
//如果向右運動,第0個點的橫坐標加1,縱坐標不變
snk.x[0] = snk.x[0] + 1;
snk.y[0] = snk.y[0];
}
err = is_location_error();
return err;
}
int is_location_error()
{
unsigned char i;
//如果第0個點的坐標和其他任意一個點重復,那么蛇就自己撞自己,出錯
for(i=1; i
{
if((snk.x[0]==snk.x[i]) (snk.y[0]==snk.y[i]))
return 1;
}
//如果蛇的坐標超出范圍,也出錯
if(snk.x[0]>7 || snk.y[0]>7)
return 1;
return 0;
}
snake.h
#include
//定義四個方向按鍵
sbit up = P3^4;
sbit down = P3^5;
sbit left = P3^6;
sbit right = P3^7;
//定義1個游戲級別按鍵
sbit level = P3^0;
//定義一個復位按鍵
sbit reset = P3^1;
//定義4個方向的值
#define RIGHT 0
#define UP 1
#define LEFT 2
#define DOWN 3
void delay_us();
void delay_10us();
void delay_ms();
void delay_10ms();
void delay_100ms();
void delay_s();
int is_location_error();
void matrix();
void snk_init();
void set_direction();
int get_location();
int is_location_error();
『本文轉載自網(wǎng)絡,版權歸原作者所有,如有侵權請聯(lián)系刪除』
評論