贪吃蛇代码

//头文件

#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 CreateMap();

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

//创建食物
void CreateFood(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);

define _CRT_SECURE_NO_WARNINGS 1

#include "snakec.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-退出, 空格-暂停游戏");

    SetPos(64, 20);
    printf("比特就业课@版权");
}

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 1

#include "snakec.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);
}
{
	//设置程序适应本地环境
	setlocale(LC_ALL, "");
	srand((unsigned int)time(NULL));

	test();
	return 0;
}

运行如下 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值