贪吃蛇实验

更新时间:2023-10-30 01:15:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

实验:贪吃蛇

一、实验目的

1.运用所学过的单片机知识,编写简单的贪吃蛇游戏; 2.学会单片机大部分功能的运用。 二、实验原理 1. TFT 彩屏工作原理

TFT(Thin Film Transistor)LCD 即薄膜场效应晶体管LCD,是有源矩阵类型液晶显示器(AM-LCD)中的一种。和TN 技术不同的是,TFT 的显示采用“背透式”照射方式——假想的光源路径不是像TN 液晶那样从上至下,而是从下向上。这样的作法是在液晶的背部设置特殊光管,光源照射时通过下偏光板向上透出。由于上下夹层的电极改成FET 电极和共通电极,在FET 电极导通时,液晶分子的表现也会发生改变,可以通过遮光和透光来达到显示的目的,响应时间大大提高到80ms 左右。因其具有比TN LCD 更高的对比度和更丰富的色彩,荧屏更新频率也更快,故TFT 俗称“真彩”。

LCD 是由二层玻璃基板夹住液晶组成的,形成一个平行板电容器,通过嵌入在下玻璃基板上的TFT 对这个电容器和内置的存储电容充电,维持每幅图像所需要的电压直到下一幅画面更新。液晶的彩色都是透明的必须给LCD 衬以白色的背光板上才能将五颜六色表达出来,而要使白色的背光板有反射就需要在四周加上白色灯光。因此在TFT LCD 的底部都组合了灯具,如CCFL 或LED。

2.矩阵按钮

矩阵按键又称为行列式按键,他是用4 条I/O 线作为行线,4 条I/O 线作为列线组成的按键,在行线和列线的每一个交叉点上,设置一个按键。如图所示,

按键识别原理:

在某一时刻只让一条列线处于低电平,其余列线均处于高电平,则当这一列有键按下时,该键所在的行电平将会由高电平变为低电平,可判定该列相应的行

有键按下。当第0 列处于低电平时,逐行查找是否有行线变低,若有,则第0 列与该行的交叉点按键按下;若无,则表示第0 列无键按下,再让下一列处在低电平,依此循环,这种方式称为键盘扫描。

3.贪吃蛇操作原理

贪吃蛇本身是由好几个点连成的一条线段,只要通过延时函数使线段在时间前后往指定的方向进一步就行了,即将所有线段上的点往指定方向移动一段,就会出现贪吃蛇的基本运动。贪吃蛇的方向可以通过设置几个指定的按钮来控制。

贪吃蛇吃的食物那个点可以由随机函数rand()产生一个随机数组,再每次显示一个数组里的点就可以达到预计的随机点。

最后再通过判断边界,输赢条件,使程序更加完善,界面美观。 三、实验代码。

#include #include #include #include #include #include #include\ #include\ #include\ #include\ #include\ #include\ #include\ #include\ #include\ #include\ #include\ #include\ #include\ #include\ #include\

#include\ #include\ #include\ #include\

#include\

// Provide a definition for M_PI, if it was not provided by math.h. #ifndef M_PI

#define M_PI 3.14159265358979323846F #endif

uint16_t sc; //长度

unsignedint k=0,start=0,s=3000; //k按键数,start开始键 unsignedint sum=0;//吃到的食物数量

//********************************************************************* uint32_t g_ui32SysClock;

staticvolatileunsignedlong g_ulTickCount; #define SERIES_LENGTH 240

typedefstruct _snack {

uint32_tx; uint32_ty; }ssnack;

staticssnack snack[40],a[50];//a为随机数 staticssnack food;//食物

voidTFTLCD_DrawLine(ssnack sk1,ssnack sk2,uint32_t color) // 画蛇线段 {

uint32_t i=0,PointNum = 0; if(sk1.x==sk2.x) //沿Y方向画线 {PointNum = abs(sk1.y-sk2.y); if(sk1.y<=sk2.y) {

for(i=0;i

TFTLCD_DrawPoint(sk1.x,sk1.y+i,color);

} } Else

{

for(i=0;i

} }

{

TFTLCD_DrawPoint(sk1.x,sk2.y+i,color); }

elseif (sk1.y==sk2.y)//沿X方向画线 {PointNum = abs(sk1.x-sk2.x); if(sk1.x<=sk2.x) { } else { } } } void

SnackInit(void) //对蛇进行初始化 {

uint32_t i; snack[0].x=50; snack[0].y=50; for(i=1;i<=5;i++) {

snack[i].x=50; snack[i].y=50+10*i;

TFTLCD_DrawLine(snack[i-1],snack[i],GREEN); for(i=0;i

{

TFTLCD_DrawPoint(sk2.x+i,sk2.y,color); }

for(i=0;i

TFTLCD_DrawPoint(sk1.x+i,sk2.y,color);

}

TFTLCD_DrawHorizontalLine(0,240,340,GREEN); } void

SnackDown(void) // 往下走 { uint32_t n;

TFTLCD_DrawLine(snack[1],snack[0],BLACK); SysCtlDelay(500*(20000000/s));//2 for(n=0;n

snack[n]=snack[n+1]; }

snack[sc].y=snack[sc].y+10;

TFTLCD_DrawLine(snack[sc-1],snack[sc],GREEN); SysCtlDelay(500*(20000000/s));//2 } void

SnackRight(void)//往右走 { uint32_t n,j; j=sc-1;

TFTLCD_DrawLine(snack[1],snack[0],BLACK); SysCtlDelay(500*(20000000/s));//2 for(n=0;n<=j;n++) {

snack[n]=snack[n+1]; }

snack[sc].x=snack[sc].x+10;

TFTLCD_DrawLine(snack[j],snack[sc],GREEN); SysCtlDelay(500*(20000000/s));//2 } void

SnackLeft(void) //往左走 { uint32_t n,j; j=sc-1;

TFTLCD_DrawLine(snack[1],snack[0],BLACK); SysCtlDelay(500*(20000000/s));//2 for(n=0;n<=j;n++) {

snack[n]=snack[n+1]; }

snack[sc].x=snack[sc].x-10;

TFTLCD_DrawLine(snack[j],snack[sc],GREEN); SysCtlDelay(500*(20000000/s));//2 } void

SnackUp(void)//往上走 { uint32_t n,j; j=sc-1;

TFTLCD_DrawLine(snack[1],snack[0],BLACK); SysCtlDelay(500*(20000000/s));//2 for(n=0;n<=j;n++) {

snack[n]=snack[n+1]; }

snack[sc].y=snack[sc].y-10;

TFTLCD_DrawLine(snack[j],snack[sc],GREEN); SysCtlDelay(500*(20000000/s));//2 }

//*****************************************************************************

#define TICKS_PER_SECOND 40

#define FSECONDS_PER_TICK (1.0F / (float)TICKS_PER_SECOND)

//*****************************************************************************

void

SysTickIntHandler(void) {

g_ulTickCount++; if(g_ulTickCount>=320)

g_ulTickCount = 0; }

//*****************************************************************************

void

ConfigureUART(void) { //

// Enable the GPIO Peripheral used by the UART. SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); //

// Enable UART0

SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0); //

// Configure GPIO Pins for UART mode. GPIOPinConfigure(GPIO_PA0_U0RX); GPIOPinConfigure(GPIO_PA1_U0TX);

GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); //

// Initialize the UART for console I/O. UARTStdioConfig(0, 115400, g_ui32SysClock); }

volatileuint32_t ui32Loop; volatileuint32_t key; voiddelay() {

int ui32Loop0;

for(ui32Loop0=0;ui32Loop0<1000;ui32Loop0++) //delay {;} }

intidentify_key()// 按钮的控制 { key=0;

GPIO_PORTD_AHB_DATA_R = 0x00; GPIO_PORTH_AHB_DATA_R = 0x0c;

GPIO_PORTM_DATA_R = 0x08;

for(ui32Loop=0;ui32Loop<1000;ui32Loop++) //delay { }

if((GPIO_PORTN_DATA_R&0x08)==0x00) { }

GPIO_PORTD_AHB_DATA_R = 0x02; GPIO_PORTH_AHB_DATA_R = 0x04; GPIO_PORTM_DATA_R = 0x08;

for(ui32Loop=0;ui32Loop<1000;ui32Loop++) { }

if((GPIO_PORTP_DATA_R&0x04)==0x00)//&&(GPIO_PORTP_DATA_R==0x04)

{ }

delay();

if((GPIO_PORTP_DATA_R&0x04)==0x00) { }

key=2; return 0;

;

delay();

if((GPIO_PORTN_DATA_R&0x08)==0x00) { }

key=5; return 0; ;

else

if((GPIO_PORTN_DATA_R&0x08)==0x00) {

}

delay();

if((GPIO_PORTN_DATA_R&0x08)==0x00) { }

key=6; return 0;

else

if((GPIO_PORTN_DATA_R&0x04)==0x00) { }

delay();

if((GPIO_PORTN_DATA_R&0x04)==0x00) { }

key=10; return 0;

GPIO_PORTD_AHB_DATA_R = 0x02; GPIO_PORTH_AHB_DATA_R = 0x08; GPIO_PORTM_DATA_R = 0x08;

for(ui32Loop=0;ui32Loop<1000;ui32Loop++) { }

if((GPIO_PORTN_DATA_R&0x08)==0x00)

}

delay();

if((GPIO_PORTN_DATA_R&0x08)==0x00) { }

key=7; return 0;

{ ;

return 1; }

void

pingmu(void) //进入游戏时显示等待及操作提醒 { uint32_t mb=0;

TFTLCD_ShowString(30,120,\,WHITE,BLACK); TFTLCD_ShowString(30,160,\,WHITE,BLACK); TFTLCD_ShowString(30,140,\,WHITE,BLACK); for(mb=0;mb<=10;mb++) {

SysCtlDelay(500*(20000000/3000));//2 }

TFTLCD_ShowString(30,160,\,WHITE,BLACK); for(mb=0;mb<=10;mb++) {

SysCtlDelay(500*(20000000/3000));//2 }

TFTLCD_ShowString(30,160,\,WHITE,BLACK); for(mb=0;mb<=10;mb++) {

SysCtlDelay(500*(20000000/3000));//2 }

TFTLCD_ShowString(30,160,\,WHITE,BLACK); for(mb=0;mb<=10;mb++) {

SysCtlDelay(500*(20000000/3000));//2 }

TFTLCD_FillBlock(0, 240, 0, 400, BLACK);

TFTLCD_DrawHorizontalLine(120,150,220,GREEN);//往下的按钮 TFTLCD_DrawHorizontalLine(120,150,250,GREEN); TFTLCD_DrawVerticalLine(220,250,120,GREEN); TFTLCD_DrawVerticalLine(220,250,150,GREEN); TFTLCD_ShowString(125,230,\,WHITE,BLACK);

TFTLCD_DrawHorizontalLine(120,150,170,GREEN);//中间按钮 TFTLCD_DrawHorizontalLine(120,150,200,GREEN); TFTLCD_DrawVerticalLine(170,200,120,GREEN); TFTLCD_DrawVerticalLine(170,200,150,GREEN); TFTLCD_ShowString(125,180,\,WHITE,BLACK);

TFTLCD_DrawHorizontalLine(120,150,120,GREEN);//往上按钮 TFTLCD_DrawHorizontalLine(120,150,150,GREEN); TFTLCD_DrawVerticalLine(120,150,120,GREEN); TFTLCD_DrawVerticalLine(120,150,150,GREEN); TFTLCD_ShowString(125,130,\,WHITE,BLACK);

TFTLCD_DrawHorizontalLine(70,100,170,GREEN);//往左按钮 TFTLCD_DrawHorizontalLine(70,100,200,GREEN); TFTLCD_DrawVerticalLine(170,200,70,GREEN); TFTLCD_DrawVerticalLine(170,200,100,GREEN); TFTLCD_ShowString(75,180,\,WHITE,BLACK);

TFTLCD_DrawHorizontalLine(170,200,170,GREEN);//往右按钮 TFTLCD_DrawHorizontalLine(170,200,200,GREEN); TFTLCD_DrawVerticalLine(170,200,170,GREEN); TFTLCD_DrawVerticalLine(170,200,200,GREEN); TFTLCD_ShowString(175,180,\,WHITE,BLACK);

SysCtlDelay(1000*(20000000/100));//

TFTLCD_FillBlock(0, 240, 0, 400, BLACK); } void

Rand()//产生一个随机数组 {

uint32_t i;

srand((unsigned) time(NULL)); for(i=0;i<50;i++) {

a[i].x=rand()*10 % 200+20;//20~220 a[i].y=rand()*10 % 300+40;//20~340 } }

voidmain() {

sc=5;//蛇长度 uint32_t j,i;

uint32_t num=0;//随机数组的编号 SYSCTL_RCGCGPIO_R |= (

SYSCTL_RCGCGPIO_R13 |

SYSCTL_RCGCGPIO_R12 | SYSCTL_RCGCGPIO_R11 |SYSCTL_RCGCGPIO_R10| SYSCTL_RCGCGPIO_R7 | SYSCTL_RCGCGPIO_R3 );

GPIO_PORTN_DIR_R = 0x03; GPIO_PORTM_DIR_R = 0x28; GPIO_PORTH_AHB_DIR_R = 0x0c; GPIO_PORTP_DIR_R = 0x00; GPIO_PORTD_AHB_DIR_R = 0x02; //GPIO_PORTF_AHB_DIR_R = 0x11; GPIO_PORTL_DIR_R = 0x0f;

GPIO_PORTN_DEN_R = 0x0f; GPIO_PORTM_DEN_R = 0x28; GPIO_PORTH_AHB_DEN_R = 0x0c; GPIO_PORTP_DEN_R = 0x04; GPIO_PORTD_AHB_DEN_R = 0x03; GPIO_PORTL_DEN_R = 0x0f; //uint32_t mb=0;

// The FPU should be enabled because some compilers will use floating- // point registers, even for non-floating-point code. If the FPU is not // enabled this will cause a fault. This also ensures that floating- // point operations could be added to this anumlication and would work // correctly and use the hardware floating-point unit. Finally, lazy // stacking is enabled for interrupt handlers. This allows floating- // point instructions to be used within interrupt handlers, but at the // expense of extra stack usage. FPUEnable();

FPULazyStackingEnable(); // Run from the PLL at 120 MHz.

g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000); //

// Enable interrupts to the processor.

//

IntMasterEnable(); //

// Enable the SysTick Interrupt. //

SysTickIntEnable(); //

// Enable SysTick. //

SysTickEnable(); ConfigureUART(); EPIGPIOinit();

TFT_400x240_OTM4001Ainit(g_ui32SysClock); // Open BackLight.

GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_0); GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, GPIO_PIN_0); pingmu(); IntMasterEnable();

Rand();//根据系统时间产生随机数 //食物点初始化 food.x=50; food.y=200; //蛇初始化 SnackInit(); while(1) {

TFTLCD_DrawPoint(food.x,food.y,WHITE); //在屏幕下方显示吃到的食物的个数

TFTLCD_ShowString(0,350,\,WHITE,BLACK); TFTLCD_ShowData(180,350,sum,WHITE,BLACK); //判断,蛇头不能碰到蛇身 for(i=0;i

if(snack[sc].x==snack[i].x&&snack[sc].y==snack[i].y) {

TFTLCD_FillBlock(1, 240, 0, 400, BLACK);

}

TFTLCD_ShowString(50,150,\,WHITE,BLACK); SysCtlDelay(1000*(20000000/300)); TFTLCD_FillBlock(1, 240, 0, 400, BLACK); SnackInit(); start=0; sc=5; k=0; s=300; sum=0; }

if(start!=1) {

//开始游戏提示 }

identify_key(); if(key==6) start=1;

//判断方向,防止反向运行 if(key!=0) {

if((k==5||k==6)&&key==7)

k=5;

TFTLCD_ShowString(60,120,\,WHITE,BLACK); TFTLCD_ShowString(55,160,\,WHITE,BLACK); TFTLCD_ShowString(55,200,\,WHITE,BLACK); identify_key(); if(key==6)

{

TFTLCD_FillBlock(0, 240, 0, 400, BLACK);

SnackInit();

}

else

if(k==7&&key==5)

k=7;

else

}

if(k==2&&key==10)

k=2;

else

if(k==10&&key==2)

k=10;

else

k=key;

if(start==1) {

if(sum>= 10)//吃到十个食物时判定为游戏成功 {

TFTLCD_FillBlock(1, 240, 0, 400, BLACK); //清屏

TFTLCD_ShowString(50,150,\,WHITE,BLACK); SysCtlDelay(1000*(20000000/300));

TFTLCD_FillBlock(1, 240, 0, 400, BLACK); SnackInit(); start=0; sc=5; k=0; s=300; sum=0; }

if(k==5||k==6)//按下N5按钮或开始游戏时向下走 {

SnackDown();

if(snack[sc].x==food.x&&snack[sc].y==food.y)

{

j=sc;

sc=sc+1;

snack[sc].x=snack[j].x; snack[sc].y=snack[j].y+10;

TFTLCD_DrawLine(snack[j],snack[sc],GREEN);

food.x=a[num].x; food.y=a[num].y;

TFTLCD_DrawPoint(food.x,food.y,WHITE);

num=num+1; s+=400; sum++;

}

if(snack[sc].x==0||snack[sc].x==240||snack[sc].y==0||snack[sc].y==340)

{

TFTLCD_FillBlock(1, 240, 0, 400, BLACK);

TFTLCD_ShowString(50,150,\,WHITE,BLACK);

SysCtlDelay(1000*(20000000/300));

TFTLCD_FillBlock(1, 240, 0, 400, BLACK);

SnackInit(); start=0; sc=5;

k=0; s=3000; sum=0;

}

}

if(k==10)//按下N10按钮时往右走 {

SnackRight(); //panduan(sc);

if(snack[sc].x==food.x&&snack[sc].y==food.y) {

j=sc;

sc=sc+1;

snack[sc].x=snack[j].x+10; snack[sc].y=snack[j].y;

TFTLCD_DrawLine(snack[j],snack[sc],GREEN);

food.x=a[0].x; food.y=a[0].y; }

TFTLCD_DrawPoint(food.x,food.y,WHITE); num=num+1; s+=400; sum++;

if(snack[sc].x==0||snack[sc].x==240||snack[sc].y==0||snack[sc].y==340)

{

TFTLCD_FillBlock(1, 240, 0, 400, BLACK);

TFTLCD_ShowString(50,150,\,WHITE,BLACK); SysCtlDelay(1000*(20000000/300)); TFTLCD_FillBlock(1, 240, 0, 400, BLACK);

SnackInit(); start=0;

sc=5;

k=0; }

if(k==2)//按下N2按钮时往左走 {

if(snack[sc].x==0||snack[sc].x==240||snack[sc].y==0||snack[sc].y==340)

SnackLeft(); //panduan(sc);

if(snack[sc].x==food.x&&snack[sc].y==food.y)

{

j=sc;

sc=sc+1;

snack[sc].x=snack[j].x-10; snack[sc].y=snack[j].y;

TFTLCD_DrawLine(snack[j],snack[sc],GREEN);

}

num=0; s=3000; sum=0;

food.x=a[num].x; food.y=a[num].y;

TFTLCD_DrawPoint(food.x,food.y,WHITE); num=num+1; s+=400; sum++; }

{

TFTLCD_FillBlock(1, 240, 0, 400, BLACK);

TFTLCD_ShowString(50,150,\,WHITE,BLACK); SysCtlDelay(1000*(20000000/300)); TFTLCD_FillBlock(1, 240, 0, 400, BLACK);

SnackInit(); start=0;

sc=5;

k=0; s=3000; sum=0; }

if(k==7)//按下N7按钮时往上走 {

if(snack[sc].x==0||snack[sc].x==240||snack[sc].y==0||snack[sc].y==340)

{

TFTLCD_FillBlock(1, 240, 0, 400, BLACK); SnackUp(); //panduan(sc);

if(snack[sc].x==food.x&&snack[sc].y==food.y)

{

j=sc;

sc=sc+1;

snack[sc].x=snack[j].x; snack[sc].y=snack[j].y-10;

TFTLCD_DrawLine(snack[j],snack[sc],GREEN);

}

food.x=a[num].x; food.y=a[num].y;

TFTLCD_DrawPoint(food.x,food.y,WHITE); num=num+1; s+=400; sum++; }

TFTLCD_ShowString(50,150,\,WHITE,BLACK);

SysCtlDelay(1000*(20000000/300)); TFTLCD_FillBlock(1, 240, 0, 400, BLACK);

SnackInit(); start=0;

sc=5;

k=0; s=3000; sum=0; }

} }

if(num>=49) // num=0; } }

随机点数组全取完时重制随机数数组。

本文来源:https://www.bwwdw.com/article/jyj2.html

Top