C语言简单实现贪吃蛇

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>

#define U 1
#define D 2
#define L 3
#define R 4       //蛇的状态,U:上 ;D:下;L:左 R:右

#define width 100
#define height 30

typedef struct BLOCK
{
    int x;
    int y;
    struct BLOCK *next;
}Block;

Block *snakeHead; //蛇头指针
Block *p;//遍历蛇身的指针
Block *food; //食物指针 
int speed = 200;

void drawBlock(int x,int y);
void eraseBlock(int x,int y);
void createWindow();
void createMap();
void createSnake();
void createFood();
void moveSnake();
void endGame();

int main()
{
    createWindow();
    createMap();
    createSnake();
    createFood();
    moveSnake();
    return 0;
}

void drawBlock(int x,int y)  //画方块 
{
    HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
    COORD coord;
    coord.X = x;
    coord.Y = y;
    SetConsoleCursorPosition(handle, coord); //设置控制台光标的位置

    //CONSOLE_CURSOR_INFO curInfo; //定义光标信息的结构体变量
    //curInfo.dwSize = 1;  //如果没赋值的话,隐藏光标无效
    //curInfo.bVisible = FALSE; //将光标设置为不可见
    //SetConsoleCursorInfo(handle, &curInfo); //设置光标信息

    printf("□");//一个方块占两个位置  //● ■ ▲ ★ ▁  ▁ 
}

void eraseBlock(int x,int y)  //擦除方块 
{
    HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
    COORD coord;
    coord.X = x;
    coord.Y = y;
    SetConsoleCursorPosition(handle, coord); //设置控制台光标的位置
    printf(" ");//一个方块占两个位置
}

void createWindow()
{
    char s[30];
    sprintf(s,"mode con cols=%d lines=%d",width,height);
    //system("mode con cols=100 lines=30"); //创建窗口
    system(s);
    system("title 贪食蛇游戏"); //设置窗口标题

    system("color b");
}


void createMap()
{
    int i;
    for(i=0;i<width-2;i+=2) 
    {
        drawBlock(i,0);  //画上墙 
        drawBlock(i,height-1); //画下墙 
    }

    for(i=0;i<height-1;i++)
    {
        drawBlock(0,i);//画左墙 
        drawBlock(width-2,i);//画右墙 
    }
}

void createSnake()
{
    snakeHead = (Block *)malloc(sizeof(Block));
    snakeHead->x = 44;
    snakeHead->y = 15;
    snakeHead->next = NULL;

    drawBlock(snakeHead->x,snakeHead->y);

    p = snakeHead;
    int i;
    for(i=1;i<5;i++)
    {
        Block *body = (Block *)malloc(sizeof(Block));
        body->x = p->x + 2;
        body->y = p->y;
        body->next = NULL;

        drawBlock(body->x,body->y);

        p->next = body;
        p = body;
    }
}

void createFood()
{
    int x;
    int y;
    while(1){
        //srand((unsigned)time(NULL));//为了防止每次产生的随机数相同,种子设置为time
        srand(time(0));
        x = (rand() % (width/2-2)) * 2 + 2;//设置x为偶数
        y = rand() % (height-2) + 1;

        //食物不能与蛇身重合
        bool inSnake = false;
        p=snakeHead;
        while(p->next != NULL) //遍历循环
        {
           if(p->x == x && p->y == y)
           {
               inSnake = true;
               break;
           }
           p = p->next;
        }

        if(inSnake == false){
            break;
        }
    }

    food = (Block *)malloc(sizeof(Block));
    food->x = x;
    food->y = y;
    food->next = NULL;
    drawBlock(x,y);
}


void moveSnake()
{
    int state = L;
    int x = snakeHead->x;
    int y = snakeHead->y;

    while(1){
        Sleep(speed);

        if(state == U){
            y =y-1;
        }else if(state == D){
            y =y+1;
        }else if(state == R){
            x = x+2;
        }else if(state == L){
            x = x-2;
        }

        if(x==food->x && y==food->y){ //遇到食物
            food->next = snakeHead;
            snakeHead = food; //吃掉食物

            createFood();//再建一个食物

        }else{   //没有遇到食物  创建新的蛇头  接入蛇身 抹除蛇尾 实现移动
            Block *newHead = (Block *)malloc(sizeof(Block));
            newHead->x = x;
            newHead->y = y;
            newHead->next = snakeHead;
            drawBlock(newHead->x,newHead->y);

            p = snakeHead;
            while(p->next->next != NULL){  //指针指向倒数第二节
                p=p->next;
            }
            eraseBlock(p->next->x,p->next->y); //抹除蛇尾
            free(p->next);
            p->next = NULL;

            snakeHead=newHead;
        }

        // >>>>>>>>>>判定游戏结束
        bool gameOver = false;

        //撞墙
        if(snakeHead->x == 0 || snakeHead->x == width-2 ||snakeHead->y == 0||snakeHead->y ==height-1){
            gameOver = true;
        }

        //碰到自己
        p=snakeHead->next;
        while(p->next != NULL){
            if(p->x == snakeHead->x && p->y == snakeHead->y){
                gameOver = true;
                break;
            }
            p=p->next;
        }

        if(gameOver){
            endGame();
            break;
        }
        //<<<<<<<<<<<判定游戏结束


        //>>>>>>>>>>>响应键盘控制
        if(GetAsyncKeyState(VK_UP) && state != D){
            state = U;
        }else if(GetAsyncKeyState(VK_DOWN) && state != U){
            state = D;
        }else if(GetAsyncKeyState(VK_RIGHT) && state != L){
            state = R;
        }else if(GetAsyncKeyState(VK_LEFT) && state != R){
            state = L;
        }
        //<<<<<<<<<<<响应键盘控制
    }
}


void endGame()
{
    system("cls"); //清屏
    HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
    COORD coord;
    coord.X = 30;
    coord.Y = 10;
    SetConsoleCursorPosition(handle, coord); //设置控制台光标的位置
    printf("Game Over!\n");
    //system("pause");
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值