贪吃蛇小游戏

简介: 贪吃蛇小游戏

本游戏的实现需要用到链表,结构体,win32API,枚举等相关知识。

头文件代码

#pragma once

#include<locale.h>
#include<stdlib.h>
#include<Windows.h>
#include<stdbool.h>
#include<stdio.h>
#include<time.h>

#define WALL L'□'
#define BODY L'●'
#define FOOD L'★'
#define POS_X 24
#define POS_Y 5
#define KEY_PRESS(VK) ((GetAsyncKeyState(VK)&0x1)?1:0)

enum DIRECTION
{
   
    UP = 1,
    DOWN,
    LEFT,
    RIGHT
};

enum GAME_STATUS
{
   
    OK,//正常运行
    END_NORMAL,//按ESC退出
    KILL_BY_WALL,
    KILL_BY_SELF
};

//蛇结点的描述
typedef struct SnakeNode
{
   
    //坐标
    int x;
    int y;
    struct SnakeNode* next;
}SnakeNode,*pSnakeNode;

//蛇的结构
typedef struct Snake
{
   
    pSnakeNode _pSnake;//指向蛇头结点的指针
    pSnakeNode _pFood;//指向食物结点的指针
    int _Score;//蛇累计的总分
    int _FoodWeight;//一个食物的分数
    int _SleepTime;//每走一步休息的时间,时间越短,速度越快,时间越长,速度越慢    
    enum DIRECTION _Dir;//描述蛇的方向
    enum GAME_STATUS _Status;//游戏的状态:正常,退出,撞墙,吃到自己
}Snake,*pSnake;

//游戏开始--完成游戏的初始化动作
void GameStart(pSnake ps);

//定位坐标
void SetPos(short x, short y);

//游戏开始的欢迎界面
void WelcomeToGame(); 

//打印地图
void CreatMap();

//初始化蛇
void InitSnake(pSnake ps);

//创建食物
void CreatFood(pSnake ps);

//游戏的正常运行
void GameRun(pSnake ps);

// 打印帮助信息
void PrintHelpInfo();

//游戏暂停和恢复
void Pause();

//蛇的移动
void SnakeMove(pSnake ps);

//判断蛇头到达的坐标是否是食物
int NextIsFood(pSnake ps, pSnakeNode pnext);

//吃掉食物
void EatFood(pSnake ps, pSnakeNode pnext);

//不吃食物
void NoFood(pSnake ps, pSnakeNode pnext);

//蛇是否撞墙
void KillByWall(pSnake ps);

//蛇是否自杀
void KillBySelf(pSnake ps);

//游戏结束后的善后处理
void GameEnd(pSnake ps);

函数实现代码


#include "snake.h"

//设置光标的坐标
void SetPos(short x, short y)
{
   
    COORD pos = {
    x, y };
    HANDLE hOutput = NULL;
    //获取标准输出的句柄(用来标识不同设备的数值)
    hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    //设置标准输出上光标的位置为pos
    SetConsoleCursorPosition(hOutput, pos);
}

void WelComeToGame()
{
   
    //定位光标
    SetPos(40, 14);
    printf("欢迎来到贪吃蛇小游戏");
    SetPos(40, 25);
    system("pause");//pause是暂停
    system("cls");
    SetPos(20, 14);
    printf("使用 ↑ . ↓ . ← . → . 分别控制蛇的移动, F3是加速,F4是减速");
    SetPos(40, 25);
    system("pause");
    system("cls");
}

void CreateMap()
{
   
    //上
    SetPos(0, 0);
    int i = 0;
    for (i = 0; i <= 56; i += 2)
    {
   
        wprintf(L"%lc", WALL);
    }
    //下
    SetPos(0, 26);
    for (i = 0; i <= 56; i += 2)
    {
   
        wprintf(L"%lc", WALL);
    }
    //左
    for (i = 1; i <= 25; i++)
    {
   
        SetPos(0, i);
        wprintf(L"%lc", WALL);
    }
    //右
    for (i = 1; i <= 25; i++)
    {
   
        SetPos(56, i);
        wprintf(L"%lc", WALL);
    }
}

void InitSnake(pSnake ps)
{
   
    pSnakeNode cur = NULL;
    int i = 0;
    for (i = 0; i < 5; i++)
    {
   
        cur = (pSnakeNode)malloc(sizeof(SnakeNode));
        if (cur == NULL)
        {
   
            perror("InitSnake()::malloc()");
            return;
        }
        cur->x = POS_X + 2 * i;
        cur->y = POS_Y;
        cur->next = NULL;

        //头插法
        if (ps->_pSnake == NULL)
        {
   
            ps->_pSnake = cur;
        }
        else
        {
   
            cur->next = ps->_pSnake;
            ps->_pSnake = cur;
        }
    }

    //打印蛇身
    cur = ps->_pSnake;
    while (cur)
    {
   
        SetPos(cur->x, cur->y);
        wprintf(L"%lc", BODY);
        cur = cur->next;
    }

    ps->_Status = OK;
    ps->_Score = 0;
    ps->_pFood = NULL;
    ps->_SleepTime = 200;
    ps->_FoodWeight = 10;
    ps->_Dir = RIGHT;
}

void CreateFood(pSnake ps)
{
   
    int x = 0;
    int y = 0;
again:
    do
    {
   
        x = rand() % 53 + 2;
        y = rand() % 25 + 1;
    } while (x % 2 != 0);//x坐标必须是2的倍数

    //坐标不能和蛇的身体冲突
    pSnakeNode cur = ps->_pSnake;
    while (cur)
    {
   
        //比较坐标
        if (cur->x == x && cur->y == y)
        {
   
            goto again;
        }
        cur = cur->next;
    }

    pSnakeNode pFood = (pSnakeNode)malloc(sizeof(SnakeNode));
    if (pFood == NULL)
    {
   
        perror("CreateFood()::malloc()");
        return;
    }
    pFood->x = x;
    pFood->y = y;
    ps->_pFood = pFood;

    //打印食物
    SetPos(x, y);
    wprintf(L"%lc", FOOD);
}

void GameStart(pSnake ps)
{
   
    //控制台窗口的设置
    system("mode con cols=100 lines=30");
    system("title 贪吃蛇");

    //光标影藏掉
    HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    //影藏光标操作
    CONSOLE_CURSOR_INFO CursorInfo;
    GetConsoleCursorInfo(hOutput, &CursorInfo);//获取控制台光标信息
    CursorInfo.bVisible = false; //隐藏控制台光标
    SetConsoleCursorInfo(hOutput, &CursorInfo);//设置控制台光标状态

    //打印欢迎界面
    WelComeToGame();
    //创建地图
    CreateMap();
    //初始化贪食蛇
    InitSnake(ps);
    //创建食物
    CreateFood(ps);
}

void PrintHelpInfo()
{
   
    SetPos(64, 15);
    printf("1.不能撞墙,不能咬到自己");
    SetPos(64, 16);
    printf("2.使用 ↑.↓.←.→ 分别控制蛇的移动");
    SetPos(64, 17);
    printf("3.F3加速,F4减速");
    SetPos(64, 18);
    printf("4.ESC-退出, 空格-暂停游戏");
}

void Pause()
{
   
    while (1)
    {
   
        Sleep(100);
        if (KEY_PRESS(VK_SPACE))
        {
   
            break;
        }
    }
}

int NextIsFood(pSnake ps, pSnakeNode pnext)
{
   
    if (ps->_pFood->x == pnext->x && ps->_pFood->y == pnext->y)
    {
   
        return 1;
    }
    else
    {
   
        return 0;
    }
}

//吃掉食物
void EatFood(pSnake ps, pSnakeNode pnext)
{
   
    //头插
    pnext->next = ps->_pSnake;
    ps->_pSnake = pnext;

    //打印蛇
    pSnakeNode cur = ps->_pSnake;
    while (cur)
    {
   
        SetPos(cur->x, cur->y);
        wprintf(L"%lc", BODY);
        cur = cur->next;
    }

    free(ps->_pFood);
    ps->_Score += ps->_FoodWeight;

    CreateFood(ps);//新创建食物
}

//不吃食物
void NoFood(pSnake ps, pSnakeNode pnext)
{
   
    //头插
    pnext->next = ps->_pSnake;
    ps->_pSnake = pnext;

    //打印蛇身
    pSnakeNode cur = ps->_pSnake;
    while (cur->next->next)
    {
   
        SetPos(cur->x, cur->y);
        wprintf(L"%lc", BODY);
        cur = cur->next;
    }
    SetPos(cur->next->x, cur->next->y);
    printf("  ");
    free(cur->next);
    cur->next = NULL;
}

//蛇是否撞墙
void KillByWall(pSnake ps)
{
   
    if (ps->_pSnake->x == 0 ||
        ps->_pSnake->x == 56 ||
        ps->_pSnake->y == 0 ||
        ps->_pSnake->y == 26)
        ps->_Status = KILL_BY_WALL;
}

//蛇是否自杀
void KillBySelf(pSnake ps)
{
   
    pSnakeNode cur = ps->_pSnake->next;
    while (cur)
    {
   
        if (ps->_pSnake->x == cur->x && ps->_pSnake->y == cur->y)
        {
   
            ps->_Status = KILL_BY_SELF;
        }
        cur = cur->next;
    }
}


void SnakeMove(pSnake ps)
{
   
    pSnakeNode pNext = (pSnakeNode)malloc(sizeof(SnakeNode));
    if (pNext == NULL)
    {
   
        perror("SnakeMove()::malloc()");
        return;
    }
    pNext->next = NULL;

    switch (ps->_Dir)
    {
   
    case UP:
        pNext->x = ps->_pSnake->x;
        pNext->y = ps->_pSnake->y - 1;
        break;
    case DOWN:
        pNext->x = ps->_pSnake->x;
        pNext->y = ps->_pSnake->y + 1;
        break;
    case LEFT:
        pNext->x = ps->_pSnake->x - 2;
        pNext->y = ps->_pSnake->y;
        break;
    case RIGHT:
        pNext->x = ps->_pSnake->x + 2;
        pNext->y = ps->_pSnake->y;
        break;
    }

    //判断蛇头到达的坐标处是否是食物
    if (NextIsFood(ps, pNext))
    {
   
        //吃掉食物
        EatFood(ps, pNext);
    }
    else
    {
   
        //不吃食物
        NoFood(ps, pNext);
    }

    //蛇是否撞墙
    KillByWall(ps);

    //蛇是否自杀
    KillBySelf(ps);
}


void GameRun(pSnake ps)
{
   
    PrintHelpInfo();
    do
    {
   
        SetPos(64, 10);
        printf("得分:%05d", ps->_Score);
        SetPos(64, 11);
        printf("每个食物的分数:%2d", ps->_FoodWeight);

        if (KEY_PRESS(VK_UP) && ps->_Dir != DOWN)
        {
   
            ps->_Dir = UP;
        }
        else if (KEY_PRESS(VK_DOWN) && ps->_Dir != UP)
        {
   
            ps->_Dir = DOWN;
        }
        else if (KEY_PRESS(VK_LEFT) && ps->_Dir != RIGHT)
        {
   
            ps->_Dir = LEFT;
        }
        else if (KEY_PRESS(VK_RIGHT) && ps->_Dir != LEFT)
        {
   
            ps->_Dir = RIGHT;
        }
        else if (KEY_PRESS(VK_ESCAPE))
        {
   
            ps->_Status = END_NORMAL;
            break;
        }
        else if (KEY_PRESS(VK_SPACE))
        {
   
            Pause();
        }
        else if (KEY_PRESS(VK_F3))//加速
        {
   
            if (ps->_SleepTime >= 80)
            {
   
                ps->_SleepTime -= 30;
                ps->_FoodWeight += 2;
            }
        }
        else if (KEY_PRESS(VK_F4))//减速
        {
   
            if (ps->_SleepTime < 320)
            {
   
                ps->_SleepTime += 30;
                ps->_FoodWeight -= 2;
            }
        }

        Sleep(ps->_SleepTime);
        SnakeMove(ps);
    } while (ps->_Status == OK);
}

void GameEnd(pSnake ps)
{
   
    SetPos(20, 12);
    switch (ps->_Status)
    {
   
    case END_NORMAL:
        printf("您主动退出游戏\n");
        break;
    case KILL_BY_SELF:
        printf("自杀了,游戏结束\n");
        break;
    case KILL_BY_WALL:
        printf("撞墙了,游戏结束\n");
        break;
    }
    //释放蛇身的结点
    pSnakeNode cur = ps->_pSnake;
    while (cur)
    {
   
        pSnakeNode del = cur;
        cur = cur->next;
        free(del);
    }
    ps->_pSnake = NULL;

}

测试时代码


#define _CRT_SECURE_NO_WARNINGS_

#include"snake.h"

void test()
{
   
    int ch = 0;
    do
    {
   
        Snake snake = {
    0 };//创建了蛇
        //1.游戏开始--初始化游戏
        GameStart(&snake);
        //2.游戏运行--游戏的正常运行过程
        GameRun(&snake);
        //3.游戏结束--游戏善后(释放资源)
        GameEnd(&snake);
        SetPos(20, 18);
        printf("再来一局吗?(Y/N):");
        ch = getchar();
        getchar();//清理掉'\n'
    } while (ch == 'Y' || ch == 'y');
    SetPos(0, 27);
}

int main()
{
   
    //设置程序适应本地环境
    setlocale(LC_ALL, "");
    srand((unsigned int)time(NULL));
    test();
    return 0;
}
目录
相关文章
|
1月前
|
Java Android开发
大鱼吃小鱼【小游戏】
大鱼吃小鱼【小游戏】
36 0
|
1天前
|
Linux C语言
|
3月前
|
程序员 API C语言
超详细实现【贪吃蛇】(1)
超详细实现【贪吃蛇】(1)
49 2
|
8月前
|
Python
实现一个2048小游戏
要实现一个2048小游戏,你需要使用Python编程语言和图形用户界面(GUI)库。下面是一个使用Tkinter库来创建2048小游戏的基本步骤
282 3
|
10月前
10点小游戏 2021-04-22
10点小游戏 2021-04-22
|
10月前
|
移动开发
H5贪吃蛇小游戏
H5贪吃蛇小游戏
|
11月前
|
算法
2048小游戏(变态版哦)
2048小游戏(变态版哦)
194 0
|
11月前
|
C++
推箱子小游戏(c++实现)
推箱子小游戏(c++实现)
|
12月前
|
C语言
QAQ的小游戏
QAQ的小游戏
|
12月前
做个不一样的小游戏
,我发布了“微信小游戏实战系列”的第一篇文章,也是我的第一个小游戏正式开始制作的时间,之前它只是一个脑袋中的想法,大概类似于这样:我能不能试着做这样的一系列的游戏呢?它们有着经典的玩法,不会过时,仍然有着很多的受众,如果我把一个经典的小游戏做成一个精品的小游戏,是否是有价值的,甚至能产生商业价值?
102 0