500行代码实现贪吃蛇(2)

简介: 500行代码实现贪吃蛇(2)


3. 贪吃蛇的具体实现

  1. 首先,我们要让整个程序适应本地化
int main()
{
  //修改适配本地中文环境
  setlocale(LC_ALL, "");
  return 0;
}
  1. 蛇身节点的创建
//蛇身结点的定义
typedef struct SnakeNode
{
  int x; 
  int y;
  struct SnakeNode* next;
}SnakeNode, * pSnakeNode;
//typedef struct SnakeNode* pSnakeNode;//上面的写法和这个写法是一个效果
  1. 再定义一个结构体来维护整个贪吃蛇游戏
//游戏的状态
enum GAME_STATUS
{
  OK = 1,//正常运行
  ESC,//按了ESC键退出,正常退出
  KILL_BY_WALL,//撞墙
  KILL_BY_SELF//撞到自身
};
//蛇行走的方向
enum DIRECTION
{
  UP = 1,
  DOWN,
  LEFT,
  RIGHT
};
//贪吃蛇
typedef struct Snake
{
  pSnakeNode pSnake;//维护整条蛇的指针,是指向蛇头
  pSnakeNode pFood;//指向食物的指针
  int Score;//当前累积的分数
  int FoodWeight;//一个食物的分数
  int SleepTime;//蛇休眠的时间,休眠的时间越短,蛇的速度越快,休眠的时间越长,蛇的速度越慢
  enum GAME_STATUS status;//当前的状态
  enum DIRECTION dir;//蛇当前走的方向
}Snake, * pSnake;
  1. 游戏开始的函数

GameStart:

void GameStart(pSnake ps)
{
  //设置控制台的信息,窗口大小,窗口名
  system("mode con cols=100 lines=30");
  system("title 贪吃蛇");
  //隐藏光标
  HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
  CONSOLE_CURSOR_INFO CursorInfo;
  GetConsoleCursorInfo(handle, &CursorInfo);//获取控制台光标信息
  CursorInfo.bVisible = false;
  SetConsoleCursorInfo(handle, &CursorInfo);
  
  //打印欢迎信息
  WelcomeToGame();
  //绘制地图
  CreateMap();
  
  //初始化蛇
  InitSnake(ps);
  
  //创建食物
  CreateFood(ps);
}

打印欢迎信息:

void SetPos(int x, int y)
{
  //获得设备句柄
  HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
  //根据句柄设置光标的位置
  COORD pos = { x, y };
  SetConsoleCursorPosition(handle, pos);
}
void WelcomeToGame()
{
  //欢迎信息
  SetPos(35, 10);
  printf("欢迎来到贪吃蛇小游戏\n");
  SetPos(38, 20);
  system("pause");
  system("cls");
  //功能介绍信息
  SetPos(15, 10);
  printf("用 ↑ . ↓ . ← . → 来控制蛇的移动,F3是加速,F4是减速\n");
  SetPos(15, 11);
  printf("加速能得到更高的分数");
  SetPos(38, 20);
  system("pause");
  system("cls");
}

绘制地图:

#define WALL L'□'
void CreateMap()
{
  int i = 0;
  //上
  SetPos(0, 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);
  }
}

初始化蛇:

注意: 蛇的每个节点的x坐标必须是2的倍数,否则可能会出现蛇的⼀个节点有一半出现在墙体中,另外⼀半在墙外的现象,坐标不好对齐。

#define BODY L'●'
//蛇默认的起始坐标
#define POS_X 24
#define POS_Y 5
void InitSnake(pSnake ps)
{
  //创建5个蛇身的结点
  pSnakeNode cur = NULL;
  int i = 0;
  for (i = 0; i < 5; i++)
  {
    cur = (pSnakeNode)malloc(sizeof(SnakeNode));
    
    if (NULL == cur)
    {
      perror("InitSnake():malloc()");
      return;
    }
    cur->x = POS_X + 2 * i;
    cur->y = POS_Y;
    cur->next = NULL;
    //头插法
    if (NULL == ps->pSnake)
    {
      ps->pSnake = cur;
    }
    else
    {
      cur->next = ps->pSnake;
      ps->pSnake = cur;
    }
  }
  //打印蛇身
  while (cur)
  {
    SetPos(cur->x, cur->y);
    wprintf(L"%lc", BODY);
    cur = cur->next;
  }
  //贪吃蛇的其他信息初始化
  ps->dir = RIGHT;
  ps->FoodWeight = 10;
  ps->pFood = NULL;
  ps->Score = 0;
  ps->SleepTime = 200;
  ps->status = OK;
}

创建食物:

关于食物,就是在墙体内随机生成⼀个坐标(x坐标必须是2的倍数),坐标不能和蛇的身体重合,然后打印★。

#define FOOD L'★'
void CreateFood(pSnake ps)
{
  int x = 0;
  int y = 0;
again:
  do
  {
    x = rand() % 53 + 2;
    y = rand() % 24 + 1;
  } while (x % 2 != 0);
  //坐标和蛇的身体的每个节点的坐标比较
  pSnakeNode cur = ps->pSnake;
  while (cur)
  {
    if (x == cur->x && y == cur->y)
    {
      goto again;
    }
    cur = cur->next;
  }
  //创建食物
  pSnakeNode pFood = (pSnakeNode)malloc(sizeof(SnakeNode));
  
  if (NULL == pFood)
  {
    perror("CreatFood():malloc()");
    return;
  }
  pFood->x = x;
  pFood->y = y;
  pFood->next = NULL;
  ps->pFood = pFood;
  SetPos(x, y);
  wprintf(L"%lc", FOOD);
}
int main()
{
  srand((unsigned int)time(NULL));
  
  return 0;
}
  1. 游戏运行的函数

打印帮助信息:

void PrintHelpInfo()
{
  SetPos(62, 15);
  printf("1.不能穿墙,不能咬到自己");
  SetPos(62, 16);
  printf("2.用 ↑.↓.←.→ 来控制蛇的移动");
  SetPos(62, 17);
  printf("3.F3是加速,F4是减速");
  SetPos(62, 18);
  printf("4.ESC:退出游戏 space:暂停游戏");
}

GameRun:

#define KEY_PRESS(VK) ((GetAsyncKeyState(VK) & 0x1) ? 1 : 0)
void GameRun(pSnake ps)
{
  //打印帮助信息
  PrintHelpInfo();
  
  if (KEY_PRESS(VK_UP) || KEY_PRESS(VK_DOWN) ||
    KEY_PRESS(VK_LEFT) || KEY_PRESS(VK_RIGHT) ||
    KEY_PRESS(VK_ESCAPE) || KEY_PRESS(VK_SPACE) ||
    KEY_PRESS(VK_F3) || KEY_PRESS(VK_F4))
  {
    ;//消除之前 按任意键继续 的影响,比如我按了空格然后进入了游戏,这里不检测,那么下面的代码会检测到我按过空格,游戏一开始就会暂停
  }
  do
  {
    //当前的分数情况
    SetPos(62, 10);
    printf("总分:%5d\n", ps->Score);
    SetPos(62, 11);
    printf("食物的分值:%02d\n", ps->FoodWeight);
    //检测按键
    //上、下、左、右、ESC、空格、F3、F4
    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 = ESC;
      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->FoodWeight > 2)
      {
        ps->SleepTime += 30;
        ps->FoodWeight -= 2;
      }
    }
    //走一步
    SnakeMove(ps);
    //睡眠一下
    Sleep(ps->SleepTime);
  } while (OK == ps->status);
}

pause:

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

SnakeMove:

void SnakeMove(pSnake ps)
{
  pSnakeNode pNext = (pSnakeNode)malloc(sizeof(SnakeNode));
  
  if (NULL == pNext)
  {
    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
  {
    //不是食物就正常走一步
    NotEatFood(ps, pNext);
  }
  //检测撞墙
  KillByWall(ps);
  //检测撞到自己
  KillBySelf(ps);
}

NextIsFood:

int NextIsFood(pSnake ps, pSnakeNode pNext)
{
  if (ps->pFood->x == pNext->x && ps->pFood->y == pNext->y)
  {
    return 1;//下一个坐标处是食物
  }
  else
  {
    return 0;
  }
}

EatFood:

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;
  }
  ps->Score += ps->FoodWeight;
  //释放旧的食物
  free(ps->pFood);
  ps->pFood = NULL;
  //新建食物
  CreateFood(ps);
}

NotEatFood:

void NotEatFood(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->x, cur->y);
  wprintf(L"%lc", BODY);
  //将尾节点的位置打印成空白字符
  SetPos(cur->next->x, cur->next->y);
  printf("  ");
  free(cur->next);
  cur->next = NULL;
}

KillByWall:

void KillByWall(pSnake ps)
{
  if (0 == ps->pSnake->x ||
    56 == ps->pSnake->x ||
    0 == ps->pSnake->y ||
    26 == ps->pSnake->y)
  {
    ps->status = KILL_BY_WALL;
  }
}

KillBySelf:

void KillBySelf(pSnake ps)
{
  pSnakeNode cur = ps->pSnake->next;//从第二个节点开始
  while (cur)
  {
    if (cur->x == ps->pSnake->x && cur->y == ps->pSnake->y)
    {
      ps->status = KILL_BY_SELF;
      return;
    }
    cur = cur->next;
  }
}
  1. 游戏的善后工作
void GameEnd(pSnake ps)
{
  SetPos(15, 12);
  switch (ps->status)
  {
  case ESC:
    printf("主动退出游戏,正常退出\n");
    break;
  case KILL_BY_WALL:
    printf("很遗憾,撞墙了,游戏结束\n");
    break;
  case KILL_BY_SELF:
    printf("很遗憾,咬到自己了,游戏结束\n");
    break;
  }
  //释放贪吃蛇的链表资源
  pSnakeNode cur = ps->pSnake;
  pSnakeNode del = NULL;
  while (cur)
  {
    del = cur;
    cur = cur->next;
    free(del);
    del = NULL;
  }
  free(ps->pFood);
  ps->pFood = NULL;
  ps  = NULL;
}
int main()
{
  SetPos(0, 26);//让整个程序结束后的提示放到界面的最下面
  return 0;
}
  1. 让游戏循环起来
void test()
{
  int ch = 0;
  do
  {
    //创建贪吃蛇
    Snake snake = { 0 };
    GameStart(&snake);//游戏开始前的初始化
    GameRun(&snake);//玩游戏的过程
    GameEnd(&snake);//善后的工作
    SetPos(20, 15);
    printf("再来一局吗?(Y/N):");
    ch = getchar();
    getchar();//清理\n
  } while ('Y' == ch || 'y' == ch);
}

完整代码:

//snake.h
#include <locale.h>
#include <stdlib.h>
#include <windows.h>
#include <stdbool.h>
#include <stdio.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 GAME_STATUS
{
  OK = 1,//正常运行
  ESC,//按了ESC键退出,正常退出
  KILL_BY_WALL,//撞墙
  KILL_BY_SELF//撞到自身
};
//蛇行走的方向
enum DIRECTION
{
  UP = 1,
  DOWN,
  LEFT,
  RIGHT
};
//蛇身结点的定义
typedef struct SnakeNode
{
  int x; 
  int y;
  struct SnakeNode* next;
}SnakeNode, * pSnakeNode;
//typedef struct SnakeNode* pSnakeNode;//上面的写法和这个写法是一个效果
//贪吃蛇
typedef struct Snake
{
  pSnakeNode pSnake;//维护整条蛇的指针,是指向蛇头
  pSnakeNode pFood;//指向食物的指针
  int Score;//当前累积的分数
  int FoodWeight;//一个食物的分数
  int SleepTime;//蛇休眠的时间,休眠的时间越短,蛇的速度越快,休眠的时间越长,蛇的速度越慢
  enum GAME_STATUS status;//当前的状态
  enum DIRECTION dir;//蛇当前走的方向
}Snake, * pSnake;
//游戏开始前的准备
void GameStart(pSnake ps);
//游戏运行的整个逻辑
void GameRun(pSnake ps);
//游戏结束的资源释放
void GameEnd(pSnake ps);
//定位控制台光标位置
void SetPos(int x, int y);
//snake.c
#include "snake.h"
void SetPos(int x, int y)
{
  //获得设备句柄
  HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
  //根据句柄设置光标的位置
  COORD pos = { x, y };
  SetConsoleCursorPosition(handle, pos);
}
void WelcomeToGame()
{
  //欢迎信息
  SetPos(35, 10);
  printf("欢迎来到贪吃蛇小游戏\n");
  SetPos(38, 20);
  system("pause");
  system("cls");
  //功能介绍信息
  SetPos(15, 10);
  printf("用 ↑ . ↓ . ← . → 来控制蛇的移动,F3是加速,F4是减速\n");
  SetPos(15, 11);
  printf("加速能得到更高的分数");
  SetPos(38, 20);
  system("pause");
  system("cls");
}
void CreateMap()
{
  int i = 0;
  //上
  SetPos(0, 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)
{
  //创建5个蛇身的结点
  pSnakeNode cur = NULL;
  int i = 0;
  for (i = 0; i < 5; i++)
  {
    cur = (pSnakeNode)malloc(sizeof(SnakeNode));
    
    if (NULL == cur)
    {
      perror("InitSnake():malloc()");
      return;
    }
    cur->x = POS_X + 2 * i;
    cur->y = POS_Y;
    cur->next = NULL;
    //头插法
    if (NULL == ps->pSnake)
    {
      ps->pSnake = cur;
    }
    else
    {
      cur->next = ps->pSnake;
      ps->pSnake = cur;
    }
  }
  //打印蛇身
  while (cur)
  {
    SetPos(cur->x, cur->y);
    wprintf(L"%lc", BODY);
    cur = cur->next;
  }
  //贪吃蛇的其他信息初始化
  ps->dir = RIGHT;
  ps->FoodWeight = 10;
  ps->pFood = NULL;
  ps->Score = 0;
  ps->SleepTime = 200;
  ps->status = OK;
}
void CreateFood(pSnake ps)
{
  int x = 0;
  int y = 0;
again:
  do
  {
    x = rand() % 53 + 2;
    y = rand() % 24 + 1;
  } while (x % 2 != 0);
  //坐标和蛇的身体的每个节点的坐标比较
  pSnakeNode cur = ps->pSnake;
  while (cur)
  {
    if (x == cur->x && y == cur->y)
    {
      goto again;
    }
    cur = cur->next;
  }
  //创建食物
  pSnakeNode pFood = (pSnakeNode)malloc(sizeof(SnakeNode));
  
  if (NULL == pFood)
  {
    perror("CreatFood():malloc()");
    return;
  }
  pFood->x = x;
  pFood->y = y;
  pFood->next = NULL;
  ps->pFood = pFood;
  SetPos(x, y);
  wprintf(L"%lc", FOOD);
}
void GameStart(pSnake ps)
{
  //设置控制台的信息,窗口大小,窗口名
  system("mode con cols=100 lines=30");
  system("title 贪吃蛇");
  //隐藏光标
  HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
  CONSOLE_CURSOR_INFO CursorInfo;
  GetConsoleCursorInfo(handle, &CursorInfo);//获取控制台光标信息
  CursorInfo.bVisible = false;
  SetConsoleCursorInfo(handle, &CursorInfo);
  
  //打印欢迎信息
  WelcomeToGame();
  //绘制地图
  CreateMap();
  
  //初始化蛇
  InitSnake(ps);
  
  //创建食物
  CreateFood(ps);
}
void PrintHelpInfo()
{
  SetPos(62, 15);
  printf("1.不能穿墙,不能咬到自己");
  SetPos(62, 16);
  printf("2.用 ↑.↓.←.→ 来控制蛇的移动");
  SetPos(62, 17);
  printf("3.F3是加速,F4是减速");
  SetPos(62, 18);
  printf("4.ESC:退出游戏 space:暂停游戏");
}
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;
  }
  ps->Score += ps->FoodWeight;
  //释放旧的食物
  free(ps->pFood);
  ps->pFood = NULL;
  //新建食物
  CreateFood(ps);
}
void NotEatFood(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->x, cur->y);
  wprintf(L"%lc", BODY);
  //将尾节点的位置打印成空白字符
  SetPos(cur->next->x, cur->next->y);
  printf("  ");
  free(cur->next);
  cur->next = NULL;
}
void KillByWall(pSnake ps)
{
  if (0 == ps->pSnake->x ||
    56 == ps->pSnake->x ||
    0 == ps->pSnake->y ||
    26 == ps->pSnake->y)
  {
    ps->status = KILL_BY_WALL;
  }
}
void KillBySelf(pSnake ps)
{
  pSnakeNode cur = ps->pSnake->next;//从第二个节点开始
  while (cur)
  {
    if (cur->x == ps->pSnake->x && cur->y == ps->pSnake->y)
    {
      ps->status = KILL_BY_SELF;
      return;
    }
    cur = cur->next;
  }
}
void SnakeMove(pSnake ps)
{
  pSnakeNode pNext = (pSnakeNode)malloc(sizeof(SnakeNode));
  
  if (NULL == pNext)
  {
    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
  {
    //不是食物就正常走一步
    NotEatFood(ps, pNext);
  }
  //检测撞墙
  KillByWall(ps);
  //检测撞到自己
  KillBySelf(ps);
}
void GameRun(pSnake ps)
{
  //打印帮助信息
  PrintHelpInfo();
  
  if (KEY_PRESS(VK_UP) || KEY_PRESS(VK_DOWN) ||
    KEY_PRESS(VK_LEFT) || KEY_PRESS(VK_RIGHT) ||
    KEY_PRESS(VK_ESCAPE) || KEY_PRESS(VK_SPACE) ||
    KEY_PRESS(VK_F3) || KEY_PRESS(VK_F4))
  {
    ;//消除之前 按任意键继续 的影响,比如我按了空格然后进入了游戏,这里不检测,那么下面的代码会检测到我按过空格,游戏一开始就会暂停
  }
  do
  {
    //当前的分数情况
    SetPos(62, 10);
    printf("总分:%5d\n", ps->Score);
    SetPos(62, 11);
    printf("食物的分值:%02d\n", ps->FoodWeight);
    //检测按键
    //上、下、左、右、ESC、空格、F3、F4
    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 = ESC;
      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->FoodWeight > 2)
      {
        ps->SleepTime += 30;
        ps->FoodWeight -= 2;
      }
    }
    //走一步
    SnakeMove(ps);
    //睡眠一下
    Sleep(ps->SleepTime);
  } while (OK == ps->status);
}
void GameEnd(pSnake ps)
{
  SetPos(15, 12);
  switch (ps->status)
  {
  case ESC:
    printf("主动退出游戏,正常退出\n");
    break;
  case KILL_BY_WALL:
    printf("很遗憾,撞墙了,游戏结束\n");
    break;
  case KILL_BY_SELF:
    printf("很遗憾,咬到自己了,游戏结束\n");
    break;
  }
  //释放贪吃蛇的链表资源
  pSnakeNode cur = ps->pSnake;
  pSnakeNode del = NULL;
  while (cur)
  {
    del = cur;
    cur = cur->next;
    free(del);
    del = NULL;
  }
  free(ps->pFood);
  ps->pFood = NULL;
  ps  = NULL;
}
//test.c
#include "snake.h"
void test()
{
  int ch = 0;
  do
  {
    //创建贪吃蛇
    Snake snake = { 0 };
    GameStart(&snake);//游戏开始前的初始化
    GameRun(&snake);//玩游戏的过程
    GameEnd(&snake);//善后的工作
    SetPos(20, 15);
    printf("再来一局吗?(Y/N):");
    ch = getchar();
    getchar();//清理\n
  } while ('Y' == ch || 'y' == ch);
}
int main()
{
  //修改适配本地中文环境
  setlocale(LC_ALL, "");
  srand((unsigned int)time(NULL));
  test();//贪吃蛇游戏的测试
  SetPos(0, 26);
  return 0;
}


目录
相关文章
三子棋小游戏思路及代码实现的详解
三子棋小游戏思路及代码实现的详解
71 0
|
2月前
贪吃蛇游戏(代码篇)
贪吃蛇游戏(代码篇)
121 0
|
3月前
贪吃蛇例子2
贪吃蛇例子2
42 0
|
6月前
|
程序员 API 定位技术
500行代码实现贪吃蛇(1)
500行代码实现贪吃蛇(1)
61 4
|
6月前
小游戏:三子棋的代码实现
小游戏:三子棋的代码实现
39 3
扫雷的简单实现
扫雷的简单实现
58 0
|
7月前
|
程序员 API C语言
超详细实现【贪吃蛇】(1)
超详细实现【贪吃蛇】(1)
89 2
|
7月前
|
C语言
【C语言】扫雷游戏完整代码实现
【C语言】扫雷游戏完整代码实现
|
7月前
|
开发工具 索引 Python
python实现贪吃蛇游戏
贪吃蛇是我们小时候的一款经典游戏,毕竟在那个Nokia称霸的年代,这款游戏可是经典中的经典啊!而用Python(蛇)玩Snake(贪吃蛇),那再合适不过了。
122 1
python实现贪吃蛇游戏
|
编译器 API C语言
贪吃蛇代码实现与剖析(C语言)(中)
贪吃蛇代码实现与剖析(C语言)
121 0