贪吃蛇小游戏

时间:2021-07-15 23:52:39

贪吃蛇小游戏

#include<stdio.h>
#include<Windows.h>
#include<stdlib.h>
#include<time.h>
#define W_S_F "■"                       //地图&&蛇&&食物 占两个字符位置
#define MapLength 50                    //地图长度
#define MapHeigth 35                    //地图高度
#define U 1                             //上
#define D 2                             //下
#define L 3                             //左
#define R 4                             //右


typedef struct LNode                    //蛇节点
{
    int x,y;                            //蛇以地图左下角为原点的每个节点坐标(x,y)
    struct LNode *next;
}LNode, *Snake;     
typedef struct position                 //坐标
{
    int x, y;
}PosValue, Food;    

int sleeptime = 200;                    //运行间隔时间
int endstate;                           //游戏结束状态
int score;                              //游戏得分
Snake Shead;                            //蛇头节点
Food  food;                             //食物坐标
void Position(int x, int y);            //光标定位函数
void CreatMap(int Length, int Heigth);  //创建地图
void Welcome();                         //游戏欢迎界面
void StartGame();                       //开始游戏
void CircleGame();                      //循环游戏 游戏按键检测函数
void EndGame();                         //结束游戏
void InitSnake();                       //初始化蛇
PosValue ChangePosition(int x,int y);   //相对坐标转绝对坐标
void CreatFood();                       //随机生成食物
void SnakeMove(int state);              //蛇移动
void Pause();                           //暂停
int CrossWall();                        //撞墙检测
int CrossItself();                      //咬到自己检测

int main()
{
    StartGame();
    CircleGame();
    EndGame();
    system("pause");
    return 0;
}
void StartGame()
{
    score = 0;
    endstate = 0;
    Welcome();
    CreatMap(MapLength, MapHeigth);
    InitSnake();
    CreatFood();
    Position(1, 40);
}
void CircleGame()
{
    int state=0;
    while (1)
    {
        if (GetAsyncKeyState(VK_UP)&&state!=D)          state = U;
        else if (GetAsyncKeyState(VK_DOWN)&&state!=U)   state = D;
        else if (GetAsyncKeyState(VK_LEFT)&&state!=R)   state = L;
        else if (GetAsyncKeyState(VK_RIGHT)&&state!=L)  state = R;
        else if (GetAsyncKeyState(VK_SPACE))            Pause();
        else if (GetAsyncKeyState(VK_ESCAPE))           { endstate = 1; EndGame(); }
        Sleep(sleeptime);
        SnakeMove(state);
    }
}

void EndGame()
{
    system("cls");
    Position(10, 9);
    if (endstate == 1) { printf("您已经结束游戏"); }
    else if (endstate == 2) { printf("对不起,您撞到墙了。游戏结束"); }
    else if (endstate == 3) { printf("对不起,您咬到自己了。游戏结束"); }
    Position(10, 10);
    printf("您的得分是%d", score);
    Position(10, 11);
    system("pause");
    exit(0);
}
void SnakeMove(int state)
{
    Snake Q, P, Sbody;
    PosValue p, tail;
    tail.x = 1;
    tail.y = 1;
    Q = Shead;
    if (state != 0)
    {
        while (Q->next!=NULL)
        {
            P = Q;
            Q = Q->next;
        }
        tail.x = Q->x;
        tail.y = Q->y;  //记录尾巴坐标
        P->next = NULL; 
        Q->next = Shead;//把尾巴节点转换为头节点
        Shead = Q;
        Shead->x = Shead->next->x;
        Shead->y = Shead->next->y;
        if (state == U) Shead->y++;
        if (state == D) Shead->y--;
        if (state == L) Shead->x--;
        if (state == R) Shead->x++;     //设置头节点坐标
        if (Shead->x == food.x&&Shead->y == food.y) //吃到食物
        {
            Q = Shead;
            P = Q->next;
            Sbody = (LNode *)malloc(sizeof(LNode));
            if (P->x == Q->x)
            {
                Sbody->x = Q->x;
                if (Q->y > P->y)
                    Sbody->y = Q->y + 1;
                else
                    Sbody->y = Q->y - 1;
            }
            else if(P->y==Q->y)
            {
                Sbody->y = Q->y;
                if (Q->x > P->x)
                    Sbody->x = Q->x + 1;
                else
                    Sbody->x = Q->x - 1;
            }
            Sbody->next = Q;    //添加节点
            Shead = Sbody;
            CreatFood();
            score++;
        }

    }
    while (Q != NULL)
    {
        p = ChangePosition(Q->x, Q->y);
        Position(p.x, p.y);
        printf(W_S_F);
        Q = Q->next;
    }
    p= ChangePosition(tail.x, tail.y);
    Position(p.x, p.y);
    printf(" ");
    Position(103, 1);
    printf("得分=%d", score);
    if (CrossWall())
    {
        endstate = 2;
        EndGame();
    }
    if (CrossItself())
    {
        endstate = 3;
        EndGame();
    }

}
void Welcome()
{
    system("mode con cols=150 lines=45");
    Position(10, 10);
    printf("Welcome to the snake game\n");
    Position(1, 15);
    Sleep(1000);
    system("cls");
}
PosValue ChangePosition(int x, int y)
{
    PosValue p;
    p.x = 2*x+1;
    p.y = MapHeigth-y;
    return p;
}
void InitSnake()
{
    int i;
    Snake Sbody,Q;
    PosValue p;
    Shead = (LNode *)malloc(sizeof(LNode));
    Shead->x = 1;
    Shead->y = 10;
    Shead->next = NULL;
    i = 5;
    while (i--)
    {
        Sbody = (LNode *)malloc(sizeof(LNode));
        Sbody->next = Shead->next;
        Sbody->x = Shead->x;
        Sbody->y = Shead->y;
        Shead->x++;
        Shead->next = Sbody;
    }
    Q = Shead;
    while (Q != NULL)
    {
        p = ChangePosition(Q->x, Q->y);
        Position(p.x, p.y);
        printf(W_S_F);
        Q = Q->next;
    }
}
void Position(int x, int y)
{
    COORD pos;
    HANDLE hOutput;
    pos.X = x;
    pos.Y = y;
    hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleCursorPosition(hOutput, pos);
}
void CreatMap(int Length, int Heigth)
{
    int i;
    for (i = 1; i <= Length*2; i += 2)
    {
        Position(i, 1);
        printf(W_S_F);
        Position(i, Heigth);
        printf(W_S_F);
    }
    for (i = 1; i <= Heigth; i++)
    {
        Position(1, i);
        printf(W_S_F);
        Position(Length * 2-1, i);
        printf(W_S_F);
    }
    Position(103, 10);
    printf("请用↑↓← →控制蛇的移动");
    Position(103, 11);
    printf("空格暂停");
    Position(103, 12);
    printf("ESC结束游戏");
    Position(115,35);
    printf("-----LC");

}
void CreatFood()
{
    int f;
    srand((unsigned)time(NULL));
    Snake Q;
    Q = Shead;
    PosValue p;
    while (1)
    {
        f = 1;
        food.x = rand() % (MapLength - 2) + 1;
        food.y = rand() % (MapHeigth - 2) + 1;

        p = ChangePosition(food.x, food.y);
        while (Q)
        {
            if (Q->x == p.x&&Q->y == p.y)
            {
                break;
                f = 0;
            }
            Q = Q->next;
        }
        if (f == 1)
            break;
    }
    Position(p.x, p.y);
    printf(W_S_F);

}
void Pause()
{
    while (1)
    {
        Sleep(100);
        if (GetAsyncKeyState(VK_SPACE))
            break;
    }
}
int CrossWall()
{
    Snake Q;
    Q = Shead;
    if (Q->x == 0 || Q->x == MapLength-1)
        return 1;
    if (Q->y == 0 || Q->y == MapHeigth - 1)
        return 1;
    return 0;
}
int CrossItself()
{
    Snake Q,P;
    Q = Shead;
    P = Shead->next;
    while (P)
    {
        if (Q->x == P->x&&Q->y == P->y)
            return 1;
        else
            P = P->next;
    }
    return 0;
}

有个bug 因为吃到食物之后是在蛇头加一个节点 所以当食物出现在墙的临近位置且控制蛇以垂直墙的方向去吃食物时 就不可避免的撞墙。