C语言实现贪吃蛇
跟C语言实现电子钟及随机气泡所用的画圆函数及判断触边的原理类似,在此就不再累述了。
贪吃蛇有几个组成部分:
第一:按键的控制,推荐用中断的方式;
第二:蛇,这是难点,首先蛇是分节的,要注意蛇的变化规律,一次只变化一节,
后节依次变化到前节的位置,所以才会出现蛇头碰蛇身的问题,相信大家都玩过。
第三:小球,每次碰到后,小球会出现在框内任一随机的位置。
初次之外,还有边框,这个简单;
蛇的速度,笔者是靠延迟和蛇一次移动的距离配合着来控制的,但是限于目前的水平,笔者蛇一次移动的距离,
至少大于等于一节蛇身的直径,笔者的蛇是用小球所组成的;
蛇每次碰壁或者碰着自己后,要从新开始或者显示GAME OVER什么的都行,再多些的就自由发挥吧。
下面给出程序:
#include "snake_include.h"
/**************************************************************************
***** 函数名: main()
***** 功能: 贪吃蛇
***** 参数: 无
***** 返回值:
***** 创建者: 潘星宇
***** 创建时间: 2012-12-26
***** 最后更新:2012-12-26
****************************************************************************/
int main(void)
{
U32 snake_i; //画蛇计数器
volatile static signed char snake_a = -1; //蛇变化横坐标趋势a
volatile static signed char snake_b = 0; //蛇变化纵坐标趋势b
volatile static U8 snake_type = TYPE1; //蛇变化趋势类型
volatile static U8 snake_type_register = TYPE1; //蛇变化趋势类型寄存器
volatile static U32 snake_number = 3; //蛇数量计数器
volatile static U32 snake_number_register = 3; //储存上一次的蛇数量
U32 end_i; //画边框用计数器
U32 end_j; //画边框用计数器
U32 number_i; //蛇各节数坐标移位寄存器
volatile static U32 x_end = 380; //储存圆心坐标
volatile static U32 y_end = 100;
volatile static U32 x_ball = 100; //小球坐标
volatile static U32 y_ball = 100;
static U32 radius = 5; //半径
static U8 change_flag = 0; //碰到边框标志
struct snakes //用于运动画蛇的结构体
{
U32 x_location;
U32 y_location;
};
volatile static struct snakes snakes_number[1000]; //蛇的的节数的结构体数组,暂定为1000,以目前蛇一节小球的半径及边框的大小,1000足够了
MMU_Init();
LCD_Init(); //LCD初始化
initialize_key(); //初始化按键
INT_initialize (); //初始化中断
while (1)
{
snake_a = -1; //蛇变化横坐标趋势a
snake_b = 0; //蛇变化纵坐标趋势b
snake_type = TYPE1; //蛇变化趋势类型
snake_type_register = TYPE1; //蛇变化趋势类型寄存器
snake_number = 3; //蛇数量计数器
snake_number_register = 3; //储存上一次的蛇数量
x_end = 380; //圆心坐标
y_end = 100;
x_ball = 100; //小球坐标
y_ball = 100;
radius = 5; //半径
change_flag = 0;
snake_ch = 0; //重置蛇变化标志
Brush_Background(0xffff); //绘制背景
for (end_i=0; end_i<=RIGHT_EDGE - LEFT_EDGE; end_i++) //绘制边框
{
PutPixel(LEFT_EDGE+end_i,UP_EDGE,0x0);
PutPixel(LEFT_EDGE+end_i,DOWN_EDGE,0x0);
}
for (end_j=0; end_j<=DOWN_EDGE - UP_EDGE; end_j++) //绘制边框
{
PutPixel(LEFT_EDGE,UP_EDGE+end_j,0x0);
PutPixel(RIGHT_EDGE,UP_EDGE+end_j,0x0);
}
snakes_number[0].x_location = 350; //初始化蛇头三节
snakes_number[0].y_location = 100;
snakes_number[1].x_location = 360;
snakes_number[1].y_location = 100;
snakes_number[2].x_location = 370;
snakes_number[2].y_location = 100;
while (1)
{
MidpointCircle (x_ball, y_ball, radius, 0xf800); //画小球
for (snake_i=0; snake_i<snake_number_register; snake_i++)
{
if (snake_i == 0)
{
MidpointCircle (snakes_number[snake_i].x_location, snakes_number[snake_i].y_location, radius, 0x07e0); //画新蛇第一节
}
else if (snake_i == snake_number_register - 1)
{
MidpointCircle (x_end, y_end, radius, 0xffff); //清除上次最后一节
MidpointCircle (snakes_number[snake_i].x_location, snakes_number[snake_i].y_location, radius, 0x0); //画新蛇最后一节
}
else
{
MidpointCircle (snakes_number[snake_i].x_location, snakes_number[snake_i].y_location, radius, 0x0); //画新蛇其余节
}
if (snake_i > 1)
{
if ((value(snakes_number[0].x_location, snakes_number[snake_i].x_location) < 2*radius) && (value(snakes_number[0].y_location, snakes_number[snake_i].y_location) < 2*radius)) //判断蛇是否碰到了自己,蛇头不可能碰到第二节 //判断蛇是否碰到了自己
{
change_flag = 1;
}
}
}
if ((value(snakes_number[0].x_location, x_ball) <= 2*radius) && (value(snakes_number[0].y_location, y_ball) <= 2*radius)) //如果蛇碰到小球了(要注意防止蛇跟球在同一行或者同一列时还没碰到时的误判)
{
snake_number_register = snake_number;
snake_number++; //蛇身变长
MidpointCircle (x_ball, y_ball, radius, 0xffff); //清小球
x_ball = (x_ball + 100) % (RIGHT_EDGE - LEFT_EDGE); //以下为计算小球下一次变化的位置
if (x_ball <= LEFT_EDGE )
{
x_ball = LEFT_EDGE + 10;
}
y_ball = (y_ball + 50) % (DOWN_EDGE - UP_EDGE);
if (y_ball <= UP_EDGE)
{
y_ball = UP_EDGE + 10;
}
}
if (snake_number > 1000) //蛇身长度大于1000,通关了,可以考虑设置通关画面
{
change_flag = 1;
}
delay (20000000); //延迟使蛇变化不至于太快
if ((snake_ch != 0) && (snake_type != key_value))
{
snake_type_register = snake_type; //储存变化类型
snake_type = key_value; //判断控制键
snake_ch = 0;
}
if ((snake_type == TYPE1) && (snake_type_register != TYPE2)) //TPEY1与2,3与4不能直接变换,也就是说蛇不可以一次变化180°,只能是90°
{
snake_a = -1;
snake_b = 0;
}
else if ((snake_type == TYPE2) && (snake_type_register != TYPE1))
{
snake_a = 1;
snake_b = 0;
}
else if ((snake_type == TYPE3) && (snake_type_register != TYPE4))
{
snake_a = 0;
snake_b = -1;
}
else if ((snake_type == TYPE4) && (snake_type_register != TYPE3))
{
snake_a = 0;
snake_b = 1;
}
x_end = snakes_number[snake_number_register-1].x_location; //储存旧蛇最后一节的坐标
y_end = snakes_number[snake_number_register-1].y_location;
for(number_i=snake_number_register; number_i>1; number_i--) //蛇各节坐标传递,比如蛇长3节,头传给第二节,第二节传给蛇尾,穿两次就行了
{
snakes_number[number_i-1].x_location = snakes_number[number_i-2].x_location;
snakes_number[number_i-1].y_location = snakes_number[number_i-2].y_location;
}
snakes_number[0].x_location = snakes_number[0].x_location + snake_a*2*radius; //蛇的速度就在这里设置
snakes_number[0].y_location = snakes_number[0].y_location + snake_b*2*radius;
if ((snakes_number[0].x_location - radius <= LEFT_EDGE)||(snakes_number[0].x_location + radius >= RIGHT_EDGE) //判断蛇是否触边
||(snakes_number[0].y_location - radius <= UP_EDGE)||(snakes_number[0].y_location + radius >= DOWN_EDGE))
{
change_flag = 1;
}
if (change_flag == 1) //触到边或者自己了
{
break;
}
}
}
}
基于S3C2440A 4.3寸LCD屏,全部代码在同名资源有提供下载