1. 程式人生 > >簡易版貪吃蛇

簡易版貪吃蛇

廢話不多說,直接上程式碼:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<conio.h>
#include<windows.h>

#define WIDE 42
#define HEIGHT 22
#define up 2
#define down 8
#define left 4
#define right 6//絕對方向 上下左右(相對蛇的方向為 前後左右)

int map[HEIGHT][WIDE];//地圖
typedef struct Snake {//蛇的節點
    int x;
    int y;
    struct Snake *next;
    struct Snake *back;
}snake;
int Front = right;//當前蛇的方向
int hasFood = 0;//是否有食物


void InitSanke(snake *sHead);//初始化蛇
void Init(snake *sHead);//初始化地圖
void Draw(snake *sHead);//繪製函式
void CreateFood();//產生食物
void Move(snake *sHead);//移動
void TurnMove(snake* sHead);//轉向
int AddLength(snake *sHead, snake *s);//增加長度


int main()
{
    snake *sHead = NULL, *s = NULL;
    sHead = (snake*)malloc(sizeof(snake));
    sHead->x = 10;
    sHead->y = 20;
    sHead->next = NULL;
    sHead->back = NULL;
    Init(sHead);
    CreateFood();
    Draw(sHead);
    while (1)
    {
        system("cls");//Windows下的清屏函式
        Move(sHead);
        TurnMove(sHead);
        if (AddLength(sHead, s) == 0)
            break;
        CreateFood();
        Draw(sHead);
        Sleep(500);//睡眠
    }
    return 0;
}


void InitSanke(snake *sHead)//初始化蛇  三個節點
{
    snake *p, *q = NULL;
    int i;
    p = sHead;
    for (i = 0; i < 3; i++)
    {
        q = (snake*)malloc(sizeof(snake));
        q->x = 10;
        q->y = 20 - i - 1;
        q->next = NULL;
        q->back = NULL;
        p->next = q;
        q->back = p;
        p = p->next;
    }
}
void Init(snake *sHead)//初始化地圖
{
    int i, j, x = 10, y = 20;
    for (i = 0; i < HEIGHT; i++)
        for (j = 0; j < WIDE; j++)
            map[i][j] = 0;
    for (i = 0; i < HEIGHT; i++)
    {
        map[i][0] = 1;
        map[i][WIDE - 1] = 1;
    }
    for (i = 0; i < WIDE; i++)
    {
        map[0][i] = 1;
        map[HEIGHT - 1][i] = 1;
    }
    InitSanke(sHead);
}


void Draw(snake *sHead)//畫地圖
{
    int i, j;
    snake *s = sHead;
    while (s != NULL)
    {
        map[s->x][s->y] = 1;
        s = s->next;
    }
    for (i = 0; i<HEIGHT; i++)
    {
        for (j = 0; j<WIDE; j++)
        {
            if (map[i][j] == 0)
                printf(" ");//0表示什麼都沒有
            if (map[i][j] == 1)
                printf("*");//1表示蛇的節點和牆壁
            if (map[i][j] == 2)
                printf("+");//2表示食物
        }
        printf("\n");
    }
    for (i = 1; i<HEIGHT - 1; i++)
        for (j = 1; j<WIDE - 1; j++)
        {
            if (map[i][j] != 2)//消除上一幅除過食物和牆壁以外的所有東西
                map[i][j] = 0;
        }
}


void CreateFood()//產生食物
{
    int x, y;
    srand((unsigned)(time(NULL)));
    x = rand() % 20 + 1;
    y = rand() % 40 + 1;
    if (hasFood == 0)
    {
        map[x][y] = 2;
        hasFood = 1;
    }
}


void Move(snake *sHead)//簡單的移動
{
    snake *p = sHead;
    while (p->next != NULL)
        p = p->next;
    switch (Front)
    {
    case up:
        while (p->back != NULL)
        {
            p->x = p->back->x;
            p->y = p->back->y;
            p = p->back;
        }
        p->x--;
        break;
    case down:
        while (p->back != NULL)
        {
            p->x = p->back->x;
            p->y = p->back->y;
            p = p->back;
        }
        p->x++;
        break;
    case left:
        while (p->back != NULL)
        {
            p->x = p->back->x;
            p->y = p->back->y;
            p = p->back;
        }
        p->y--;
        break;
    case right:
        while (p->back != NULL)
        {
            p->x = p->back->x;
            p->y = p->back->y;
            p = p->back;
        }
        p->y++;
        break;
    default:printf("error");
    }
}


void TurnMove(snake* sHead)//轉向
{
    char ch;
    while (_kbhit())
    {
        ch = _getche();
        switch (ch)
        {
        case '2':
            if (Front == left) { sHead->x++; sHead->y++; }
            if (Front == right) { sHead->x++; sHead->y--; }
            if (Front == left || Front == right)
                Front = down;
            break;
        case '8':
            if (Front == left) { sHead->x--; sHead->y++; }
            if (Front == right) { sHead->x--; sHead->y--; }
            if (Front == left || Front == right)
                Front = up;
            break;
        case '4':
            if (Front == up) { sHead->x++; sHead->y--; }
            if (Front == down) { sHead->x--; sHead->y--; }
            if (Front == up || Front == down)
                Front = left;
            break;
        case '6':
            if (Front == up) { sHead->x++; sHead->y++; }
            if (Front == down) { sHead->x--; sHead->y++; }
            if (Front == up || Front == down)
                Front = right;
            break;
        }
    }
}


int AddLength(snake *sHead, snake *s)//增加長度 同時判斷是否撞到牆或者自己
{
    snake *p;
    int x = sHead->x - sHead->next->x;
    int y = sHead->y - sHead->next->y;//通過頭節點和第二節點的差值判斷當前方向 
    p = sHead;
    while (p->next != NULL)
        p = p->next;
    s = (snake*)malloc(sizeof(snake));
    if (map[sHead->x][sHead->y] == 2)//吃到食物
    {
        s->x = (p->x - p->back->x) + p->x;
        s->y = (p->y - p->back->y) + p->y;
        p->next = s;
        s->back = p;
        s->next = NULL;
        hasFood = 0;
        map[sHead->x + x][sHead->y + y] = 0;
        return 1;
    }
    else if (map[sHead->x][sHead->y] == 1)//撞到牆或者自己
        return 0;
    else
        return -1;
}

注意這是在vs2017下的程式,如果在CodeBlocks中有些函式需要修改,例如_kbhit()改為kbhit()。

AddLength函式順便進行了碰撞檢測,並且通過頭節點和第二節點X,Y座標的差值判斷dang。    

需要注意的是繪製相對於後臺資料計算晚一步,所以在進行碰撞檢測時直接檢測頭部所在的位置的值而不是下一個位置的值。

這算是很簡單的貪吃蛇了,可以幫助沒有基礎的人瞭解遊戲迴圈的過程,當然也有很多厲害的大神的程式碼可以去參考。