C语言实现贪吃蛇

 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屏,全部代码在同名资源有提供下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值