贪吃蛇实现

#include<stdio.h>
#include<graphics.h>//easyx库
#include <time.h>
#include<malloc.h>
#define Width  800//游戏画布宽
#define Heigh 800//游戏画布高
#define FOOD_SIZE 10//食物大小
#define SNAKE_SIZE 16//蛇身大小
#define SPEED  4  //速度  数字越大速度越快

/*
1、可以穿墙
2、只有自己咬到自己才能死掉
3、可以自己修改功能

没有找到合适的贪吃蛇贴图,所以没有上贴图用单调的颜色代替的,当然如果自己有的话可以置换成自己喜欢的贴图
用到easyx图形库,如果编译器上没有easyx库请去easyx官网下载自行安装
*/

typedef struct Food
{//食物坐标
    int x, y;
}Food;
typedef struct Body
{//双链表   蛇体
    int x, y;
    int direct;
    struct Body * pnext;
    struct Body* prenext;
} Body;
typedef struct Snake
{//蛇头
    Body *body;
    int length;
} Snake;
enum Direct {//控制的按键
    Up='W',
    Down='S',
    Left='A',
    Right='D'
};
Food food;
//移动设置
void Remove(Snake* S, int direct) {
    int x, y;
    Body* temp = S->body, *pnext =NULL;
    //蛇身移动
    while (!temp->pnext == NULL)//找到蛇尾
        temp = temp->pnext;
    pnext = temp->prenext;
    for (;!pnext==NULL;pnext=pnext->prenext)
    {//先让蛇尾一步步向前移
        temp->x = pnext->x;
        temp->y = pnext->y;
        temp = pnext;
     }
    //蛇头移动
    switch (direct)
    {
       case Up:       
                S->body->y -= SPEED;
                S->body->direct = direct;
           break;
       case Down:
                S->body->y += SPEED;
                S->body->direct = direct;
           break;
       case Left:
                S->body->x -= SPEED;
                S->body->direct = direct;
           break;
       case Right:
                S->body->x += SPEED;
                S->body->direct = direct;
            break;
     }
        //穿墙设置
        S->body->y = (S->body->y+ Heigh) % Heigh;
        S->body->x = (S->body->x + Width) % Width;
        //设置蛇头方向
        direct = S->body->direct;
}
//方向判断
void Direct(Snake* S, int direct)
{
    bool flat = false;
    int directs = S->body->direct;
    //判断方向是否为当前方向的反向,如果为当前方向的反方向就不接受新的方向
    switch (direct)
    {
    case Up:
        if (S->body->direct != Down)
            flat = true;    
        break;
    case Down:
        if (S->body->direct != Up)
            flat = true;
        break;
    case Left:
        if (S->body->direct != Right)
            flat = true;
        break;
    case Right:
        if (S->body->direct != Left)
            flat = true;
        break;
    }
    if (flat)
        directs = direct;
    Remove(S, directs);
}
//判断是否吃到食物或者死了
bool Determine(Snake* S)
{
    Body* temp = NULL;
    Body* temp_Pnext = S->body;
    int x = S->body->x - food.x;
    int y = S->body->y - food.y;
    if (x < 0)
        x = -x;
    if (y < 0)
        y = -y;
    //判断是否吃到食物
    if (x<(FOOD_SIZE+ SNAKE_SIZE) &&y<(FOOD_SIZE+ SNAKE_SIZE))
    {//设置新增长度
        temp = (Body*)malloc(sizeof(Body));
        while (!temp_Pnext->pnext == NULL)
            temp_Pnext = temp_Pnext->pnext;
        temp_Pnext->pnext = temp;
        temp->prenext = temp_Pnext;
        temp->pnext = NULL;
        //设置新增身体
        switch (temp_Pnext->direct)
        {//新增身体坐标
        case Up:
            temp->x = temp_Pnext->x;
            temp->y = temp_Pnext->y + SNAKE_SIZE;
            break;
        case Down:
            temp->x = temp_Pnext->x;
            temp->y = temp_Pnext->y - SNAKE_SIZE;
            break;
        case Left:
            temp->x = temp_Pnext->x + SNAKE_SIZE;
            temp->y = temp_Pnext->y;
            break;
        case Right:
            temp->x = temp_Pnext->x - SNAKE_SIZE;
            temp->y = temp_Pnext->y;
            break;
        }
        temp->x = (temp->x + Width) % Width;
        temp->y = (temp->x + Heigh) % Heigh;
        temp->direct = temp_Pnext->direct;
        S->length++;
        food.x = rand() % Width;
        food.y = rand() % Heigh;
        printf("吃到食物\n");
    }
    //判断是否吃到自身
    temp = S->body->pnext;
    while (!temp == NULL)
    {
        if ((S->body->x == temp->x) && (S->body->y == temp->y))
        {
            printf("一不小心咬到了自己 游戏结束\n");
            return true;
        }
        temp = temp->pnext;
    }
    return false;
}
//绘制图案
void DrawSnake(Snake *S)
{
    Body* temp = S->body->pnext;
    BeginBatchDraw();
    cleardevice();
    setbkcolor(RGB(0xE6, 0xE6, 0xFA));
    printf("开始\n");
    //绘制蛇头
    setfillcolor(RGB(0x00,0x64,0x00));
    solidcircle(S->body->x, S->body->y, SNAKE_SIZE/2);
    //绘制蛇身
    for (; !temp == NULL; temp = temp->pnext)
    {
        setfillcolor(RGB(0x00, 0xEE, 0x76));
        solidcircle(temp->x , temp->y, SNAKE_SIZE/2); 
    }
    printf("结束\n");
    setfillcolor(RGB(0xEE, 0xDD, 0x82));
    solidcircle(food.x, food.y, FOOD_SIZE);
   
}
//接收按键
char Press_Key( )
{
    ExMessage kebody;
    peekmessage(&kebody, EM_KEY | EM_MOUSE);
    if (kebody.message == WM_KEYDOWN)
    {
        if (kebody.vkcode == 'W')
           return Up;
        if (kebody.vkcode == 'S')
            return Down;
        if (kebody.vkcode == 'A')
            return Left;
        if (kebody.vkcode == 'D' )
            return Right;
    }
    return 0;
}
//开始游戏
bool play_Snake(Snake* S)
{
    int direct = 0;
    DrawSnake(S);
    if(!(direct= Press_Key()))
    direct = S->body->direct;
    Direct(S, direct);
    EndBatchDraw();
    Sleep(10);
    if (Determine(S))
        return false;
    return true; 
}
//初始化游戏
Snake* Init_Snake()
{
    srand(time(NULL));
    Snake* S = (Snake*)malloc(sizeof(Snake));
    if (S == NULL)
        return NULL;
    S->body = (Body*)malloc(sizeof(Body));
    S->body->x = 0;
    S->body->y = 0;
    S->body->direct = Right;
    S->body->pnext = NULL;
    S->body->prenext = NULL;
    S->length=1;
    food.x = rand() % 800;
    food.y = rand() % 800;
    return S;
}
//主函数
void main()
{
    initgraph(Width, Heigh);
    Snake* S = Init_Snake();
    while (play_Snake(S))
    { 
        printf("蛇头坐标x:%d  坐标y:%d 长度为:%d\n", S->body->x, S->body->y,S->length);
    }
    system("pause");
    closegraph();
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值