C语言实现控制台贪吃蛇

#include<time.h>
#include"snake.h" 

void gotoxy(int x, int y)
{
    COORD pos;
    pos.X = x * 2;
    pos.Y = y;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);

void initSnake(Snake* s)//初始化蛇
{
    s->x = WIDTH/4+rand()% WIDTH/2;
    s->y = LENGTH / 4 + rand() % LENGTH / 2;
    s->prev = NULL;
    s->next = NULL;

int isSnakeEatItself(Snake* head)//判断游戏是否结束
{
    int gameover = 0;
    if (head->x < 0 || head->x >= WIDTH || head->y < 0 || head->y >= LENGTH)
        return 1;
    Snake* pt = head->next;
    while (pt)
    {
        if (head->x == pt->x && head->y == pt->y)
        {
            gameover = 1;
            break;
        }
        pt = pt->next;
    }
    return gameover;

int isSnakeEatMeetFood(Snake* snake, Food* food)//判断蛇是否吃到食物
{
    if (snake->x == food->x && snake->y == food->y)
        return 1;
    else
        return 0;

Snake* snakeGrow(Snake* head)//蛇身变长
{
    Snake* p = (Snake*)malloc(sizeof(Snake));
    Snake* pt = head;
    while (pt->next)
        pt = pt->next;
    p->prev = pt;
    pt->next = p;
    p->next = NULL;
    return p;

void creatFood(Food* food)//生成食物
{
    food->x = rand() % LENGTH;
    food->y = rand() % WIDTH;
    food->c = 65 + rand() % 26;

//避免食物坐标和蛇身重叠,重新生成食物
int avoidOverlap(Snake* head, Food* food)
{
    int t = 0, flag = 1;
    while (flag)
    {
        if (t > OVERLAP)
            break;
        flag = 0; 
        t++;
        Snake* pt = head;
        while (pt)
        {
            if (isSnakeEatMeetFood(pt, food))
            {
                flag = 1;
                creatFood(food);
                break;
            }
            pt = pt->next;
        }
    }
    return t;

//如果生成食物和蛇身重叠次数超过阈值,则直接按蛇移动方向设置食物位置
void setFoodLocation(Food* food, Snake* head, int numOverlap, char c)
{
    if (numOverlap > OVERLAP)
    {
        if (c == 'd')
        {
            food->x = head->x + 1;
            food->y = head->y;
            if (food->x >= LENGTH)
                food->x -= LENGTH;
        }
        if (c == 'a')
        {
            food->x = head->x - 1;
            food->y = head->y;
            if (food->x <= 0)
                food->x += LENGTH;
        }
        if (c == 'w')
        {
            food->x = head->x;
            food->y = head->y - 1;
            if (food->y <= 0)
                food->y += WIDTH;
        }
        if (c == 's')
        {
            food->x = head->x;
            food->y = head->y + 1;
            if (food->y >= WIDTH)
                food->y -= WIDTH;
        }
    }
}
char setCurKeyButton(char c)//设置当前按键
{
    char c1 = _getch();
    if (c1 == 27)return 'x';
    if (c != 'd' && c1 == 'a')c = c1;
    else if (c != 'a' && c1 == 'd')c = c1;
    else if (c != 'w' && c1 == 's')c = c1;
    else if (c != 's' && c1 == 'w')c = c1;
    return c;

void snakeMove(Snake* head, Snake* rear, char c)//处理蛇的移动
{
    Snake* pt = rear;
    while (pt != head)
    {
        pt->x = pt->prev->x;
        pt->y = pt->prev->y;
        pt = pt->prev;
    }
    if (c == 's') {
        head->y += 1;
        //if (head->y >= WIDTH)
            //head->y -= WIDTH;
    }
    else if (c == 'w') {
        head->y -= 1;
        //if (head->y <= 0)
            //head->y += WIDTH;
    }
    else if (c == 'd') {
        head->x += 1;
        //if (head->x >= LENGTH)
            //head->x -= LENGTH;
    }
    else if (c == 'a') {
        head->x -= 1;
        //if (head->x <= 0)
            //head->x += LENGTH;
    }

void drawWall() {
    system("cls");
    gotoxy(0, 0);
    printf(" ———————————————\n");
    for (int i = 0; i < WIDTH; i++) {
        gotoxy(0, i + 1);
        printf("|");
        for (int j = 0; j < LENGTH; j++) {
            printf("  ");
        }
        printf("|");
    }
    gotoxy(0, WIDTH+1);
    printf(" ———————————————\n");

}

 

void drawPicture(Snake* head, int grow,Food* food,Snake *lastRear)//绘制蛇,食物
{
    //绘制新食物
    gotoxy(food->x, food->y);
    putchar(food->c);
    putchar(food->c);

    if (grow == 0) {
        gotoxy(lastRear->x, lastRear->y);
        printf("  ");
    }
    gotoxy(head->x, head->y);
    printf("■");
    if (head->next != NULL) {
        gotoxy(head->next->x, head->next->y);
        printf("□");
    }
}

 

int color(int c)
{
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c);        //更改文字颜色
    return 0;

int main()
{
    color(12);
    int testNum = 0;
    char c = 'd';
    srand((unsigned)time(NULL));

    Food food = { 5,8,'a' };
    Snake snake, * head, * rear;
    initSnake(&snake);
    head = rear = &snake;
    drawWall();

    Snake* lastRear = (Snake*)malloc(sizeof(Snake));
    int grow = 0;
    while (1)
    {
        grow = 0;

        lastRear->x = rear->x;
        lastRear->y = rear->y;
        
        if (isSnakeEatMeetFood(head, &food)) {
            grow = 1;

            rear = snakeGrow(head);
            creatFood(&food);
            testNum = avoidOverlap(head, &food);
            setFoodLocation(&food, head, testNum, c);
        }

        if (_kbhit())c = setCurKeyButton(c);
        if (c == 'x') {
            puts("Game Over!\n");
            break;
        }
        snakeMove(head, rear, c);
        if (isSnakeEatItself(head)) {
            puts("Game Over!\n");
            break;
        }
    
        drawPicture(head,grow,&food,lastRear);
        Sleep(250);
    }
    gotoxy(10, 10);
    puts("\nThanks,Say you!\n");
    system("pause");
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值