贪吃蛇代码实现与剖析(C语言)(下)

简介: 贪吃蛇代码实现与剖析(C语言)(下)

二.贪吃蛇的游戏流程分析

这是我们贪吃蛇的整个游戏流程的分析

1.游戏窗口的实现

1.界面的初始化

根据我们刚才API部分的学习,我们已经写出了Init函数

可以用来隐藏屏幕光标

然后我们可以把打印宽字符,设置窗口大小,窗口名称的代码在main函数中去写

我们在这里将控制台的大小设置为宽:35行,列:120列

所以我们就可以在main函数当中这样去写

int main()
{
  setlocale(LC_ALL, "");
  system("mode con cols=120 lines=35");
  system("title 贪吃蛇");
  Init();
  return 0;
}

这样就完成了

2.欢迎界面的打印

我们在前面已经实现了SetPos函数

然后我们就可以通过Setpos去定位光标,然后打印欢迎信息

3.窗口布局(地图坐标)

这里要实现的是CreateMap函数

我们在这里实现的是一个27行,58列的棋盘

所以我们就需要去通过SetPos定位光标,然后打印这个墙

其次,为了便于打印,我们宏定义了墙,蛇身,食物的字符

#define WALL L'□'
#define BODY L'●'
#define FOOD L'★'

注意:这里最后打印下面的墙是因为测试时当我们打印完成之后

程序运行结束就会打印:

C:\Users\23119\Desktop\C++_learn_code\cpp_learn_code\Snake_review\Debug\Snake_review.exe (进程 6000)已退出,代码为 0。

按任意键关闭此窗口. . .

如果我们最后打印的不是下面的墙

那样就会出现这种情况:

因为打印完下面的墙之后又打印了左边和右边的墙

导致程序结束时下面的墙被这句话覆盖了

其实我们打印的过程是这样的

我们调试看一下过程

2.蛇身结构体的创建与初始化

1.蛇身节点的结构体

2.食物节点的结构体

3.蛇身结构体的创建

因此我们就可以定义出下面的结构体

4.蛇身的初始化

定义好蛇身节点,食物节点和蛇的结构体之后

下面我们要初始化这条蛇

怎么初始化呢?

因此我们就可以写出这样的代码

这两个宏定义是Snake.h文件中的
#define INIT_X 24
#define INIT_Y 6
void InitSnake(Snake* ps)
{
  //初始化蛇身
  for (int i = 0; i < 5; i++)
  {
    SNode* newnode = (SNode*)malloc(sizeof(SNode));
    if (newnode == NULL)
    {
      perror("InitSnake():: malloc fail");
      exit(-1);
    }
    newnode->next = NULL;
    newnode->x = INIT_X + 2 * i;
    newnode->y = INIT_Y;
    if (ps->_pSnake == NULL)
    {
      ps->_pSnake = newnode;
    }
    else
    {
      newnode->next = ps->_pSnake;
      ps->_pSnake = newnode;
    }
  }
  //打印蛇身
  SNode* cur = ps->_pSnake;
  while (cur)
  {
    SetPos(cur->x, cur->y);
    wprintf(L"%lc", BODY);
    cur = cur->next;
  }
  //初始化其他属性
  ps->_dir = RIGHT;
  ps->_state = OK;
  ps->_foodWeight = 10;
  ps->_score = 0;
  ps->_sleepTime = 200;
}

后面两块是打印蛇身和初始化其他属性的注意事项

5.食物的初始化

注意:rand()%53生成的随机数的范围是:0~52

void CreateFood(Snake* ps)
{
  //创建食物
  while (1)
  {
    //保证初始化到墙内
    //x:2~54
    int x = rand() % 53 + 2;//0~52+2  ->  2~54
    //y:1~25
    int y = rand() % 25 + 1;//0~24+1  ->  1~25
    //保证初始化的x必须为偶数
    if (x % 2 != 0)
    {
      continue;//这里是continue while(1){...}这个循环,这次循环不再执行下面的语句,直接跳转到下一次while(1){...}
    }
    //保证初始化时不跟蛇身重合
    SNode* cur = ps->_pSnake;
    bool flag = false;
    while (cur)
    {
      //跟蛇身重合,重新通过rand函数设置x和y
      if (cur->x == x && cur->y == y)
      {
        flag = true;
        break;//这里是break出while(cur){...}这个循环
      }
      cur = cur->next;
    }
    //没有跟蛇身重合,就可以创建食物节点了
    if (!flag)
    {
      SNode* newnode = (SNode*)malloc(sizeof(SNode));
      if (newnode == NULL)
      {
        perror("CreateFood():: malloc fail");
        exit(-1);
      }
      newnode->next = NULL;
      newnode->x = x;
      newnode->y = y;
      ps->_pFood = newnode;
      break;
    }
  }
  //打印食物
  SetPos(ps->_pFood->x, ps->_pFood->y);
  wprintf(L"%lc", FOOD);
}

3.GameStart部分的完整代码

1.重点说明一下main函数

2.完整代码

1.Snake.h

#pragma once
#define WALL L'□'
#define BODY L'●'
#define FOOD L'★'
#include <stdio.h>
#include <Windows.h>
#include <stdbool.h>
#include <locale.h>
#include <stdlib.h>
#include <time.h>
#define INIT_X 24
#define INIT_Y 6
typedef struct SnakeNode
{
  struct SnakeNode* next;
  int x;
  int y;
}SNode;
enum Direction
{
  UP,
  DOWN,
  LEFT,
  RIGHT
};
enum GameState
{
  OK,
  EXIT_NORMAL,
  KILL_BY_WALL,
  KILL_BY_SELF
};
typedef struct Snake
{
  SNode* _pSnake;//蛇头节点
  SNode* _pFood;//食物
  enum Direction _dir;//蛇移动的方向
  enum GameState _state;//当前游戏状态
  int _score;//当前得分
  int _foodWeight;//每个食物的分数
  int _sleepTime;//蛇的休息时间,影响加速和减速和暂停
}Snake;
void Init();
void SetPos(short x, short y);
void GameStart(Snake* ps);
void WelcomeToGame();
void CreateMap();
void InitSnake(Snake* ps);
void CreateFood(Snake* ps);

2.Snake.c

#include "Snake.h"
void Init()
{
  HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);//让handle具有能够操作控制台标准输出设备的能力/权限
  CONSOLE_CURSOR_INFO CursorInfo;//这个结构体就是定义光标信息的结构体
  GetConsoleCursorInfo(handle, &CursorInfo);//获取控制台光标信息
  CursorInfo.bVisible = false;//隐藏控制台光标的操作
  SetConsoleCursorInfo(handle, &CursorInfo);//设置控制台光标状态
}
void SetPos(short x, short y)
{
  COORD pos = { x,y };
  HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
  SetConsoleCursorPosition(handle, pos);
}
void WelcomeToGame()
{
  SetPos(45, 12);
  printf("欢迎来到贪吃蛇小游戏");
  SetPos(45, 18);
  system("pause");
  system("cls");
  SetPos(45, 12);
  printf("用↑.↓.←.→ 分别控制蛇的移动,F1为加速,F2为减速");
  SetPos(45, 13);
  printf("加速能够得到更高的分数");
  SetPos(45, 18);
  system("pause");
  system("cls");
}
void CreateMap()
{
  //上
  SetPos(0, 0);
  for (int i = 0; i <= 56; i += 2)
  {
    wprintf(L"%lc", WALL);
  }
  //左
  for (int i = 0; i <= 25; i++)
  {
    SetPos(0, i);
    wprintf(L"%lc", WALL);
  }
  //右
  for (int i = 0; i <= 25; i++)
  {
    SetPos(56, i);
    wprintf(L"%lc", WALL);
  }
  //下
  SetPos(0, 26);
  for (int i = 0; i <= 56; i += 2)
  {
    wprintf(L"%lc", WALL);
  }
}
void InitSnake(Snake* ps)
{
  //初始化蛇身
  for (int i = 0; i < 5; i++)
  {
    SNode* newnode = (SNode*)malloc(sizeof(SNode));
    if (newnode == NULL)
    {
      perror("InitSnake():: malloc fail");
      exit(-1);
    }
    newnode->next = NULL;
    newnode->x = INIT_X + 2 * i;
    newnode->y = INIT_Y;
    if (ps->_pSnake == NULL)
    {
      ps->_pSnake = newnode;
    }
    else
    {
      newnode->next = ps->_pSnake;
      ps->_pSnake = newnode;
    }
  }
  //打印蛇身
  SNode* cur = ps->_pSnake;
  while (cur)
  {
    SetPos(cur->x, cur->y);
    wprintf(L"%lc", BODY);
    cur = cur->next;
  }
  //初始化其他属性
  ps->_dir = RIGHT;
  ps->_state = OK;
  ps->_foodWeight = 10;
  ps->_score = 0;
  ps->_sleepTime = 200;
}
void CreateFood(Snake* ps)
{
  //创建食物
  while (1)
  {
    //保证初始化到墙内
    //x:2~54
    int x = rand() % 53 + 2;//0~52+2  ->  2~54
    //y:1~25
    int y = rand() % 25 + 1;//0~24+1  ->  1~25
    //保证初始化的x必须为偶数
    if (x % 2 != 0)
    {
      continue;
    }
    //保证初始化时不跟蛇身重合
    SNode* cur = ps->_pSnake;
    bool flag = false;
    while (cur)
    {
      //跟蛇身重合
      if (cur->x == x && cur->y == y)
      {
        flag = true;
        break;
      }
      cur = cur->next;
    }
    //没有跟蛇身重合
    if (!flag)
    {
      SNode* newnode = (SNode*)malloc(sizeof(SNode));
      if (newnode == NULL)
      {
        perror("CreateFood():: malloc fail");
        exit(-1);
      }
      newnode->next = NULL;
      newnode->x = x;
      newnode->y = y;
      ps->_pFood = newnode;
      break;
    }
  }
  //打印食物
  SetPos(ps->_pFood->x, ps->_pFood->y);
  wprintf(L"%lc", FOOD);
}
void GameStart(Snake* ps)
{
  WelcomeToGame();
  CreateMap();
  InitSnake(ps);
  CreateFood(ps);
}

3.test.c

#include "Snake.h"
//初始化光标信息等
int main()
{
    setlocale(LC_ALL, "");
    system("mode con cols=120 lines=35");
    system("title 贪吃蛇");
    Init();
    Snake snake = { 0 };//将snake结构体变量的内容全都初始化为0
    //(这里主要是为了初始化p_Snake头节点的指针,为了防止头插法创建蛇身链表时出现野指针的非法访问问题)
    //p_Snake=0;而NULL指针的本质就是(void(*)0),在数值上0跟NULL是相等的,这里可以认为p_Snake==NULL
    srand((unsigned int)time(NULL));//设置随机数种子,防止每一次运行rand生成的随机数都是一样的
    GameStart(&snake);
    SetPos(0, 30);//这里我们要定位一下光标,
    //防止最后打印的那条包含:"返回值为0"的语句因为光标最后处于打印食物位置的下一行
    //而导致覆盖我们的墙体
    return 0;
}

3.最终实现情况:

4.游戏运行

我们的蛇身结构体和食物都已经初始化好了,游戏的开始工作结束

下面开始实现游戏运行的代码了

1.GameRun函数的整体框架

在这个GameRun函数中我们要实现的整体框架是:

因此我们可以写出这样的代码框架

2.帮助信息的打印

经过了前面打印欢迎界面之后,这个帮助信息的打印对我们来说就轻而易举了

3.获取按键情况

我们之前在API中提到过这个获取按键情况的宏

#define KEY_PRESS(VK) ((GetAsyncKeyState(VK) & 0x1) ? 1 : 0)
• 1

如果我们按了这个键,这个宏对应于这个键的值就是1

如果我们没有按这个键,这个宏对应于这个键的值就是0

那么怎么使用这个宏呢?

只需要将键盘上每个键的虚拟键值传递给这个宏,

就可以通过这个宏的返回值来判断是否按下了这个键

这是微软官方提供的虚拟键代码手册,我已经查阅好了相关的按键

大家感兴趣的话,也可以去看一下这个手册

虚拟键代码手册

因此我们就可以写出这样的代码

//调整方向
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_SPACE))
{
  pause();
}
//Esc退出
else if (KEY_PRESS(VK_ESCAPE))
{
  ps->_state = EXIT_NORMAL;
  break;
}
//加速
else if (KEY_PRESS(VK_F1))
{
  //防止一直加速导致sleepTime<0出现bug
  if (ps->_sleepTime >= 50)
  {
    ps->_sleepTime -= 30;
    ps->_foodWeight += 2;//加速时食物的分值会增加
  }
}
//减速
else if (KEY_PRESS(VK_F2))
{
  //防止一直减速导致程序运行太慢出现卡顿影响用户体验
  if (ps->_sleepTime < 350)
  {
    ps->_sleepTime += 30;
    ps->_foodWeight -= 2;
    //防止太慢时食物得分减为负数
    if (ps->_sleepTime == 350)
    {
      ps->_foodWeight = 1;
    }
  }
}

Sleep是C语言的库函数,可以让程序休息对应的时间

单位是ms

这里的pause是暂停函数:

所以我们就可以完善一下我们的GameRun函数了

void GameRun(Snake* ps)
{
  PrintHelpInfo();
  do
  {
    SetPos(65, 10);
    printf("得分: %d , 每个食物得分: %d ", ps->_score, 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_SPACE))
    {
      pause();
    }
    //Esc退出
    else if (KEY_PRESS(VK_ESCAPE))
    {
      ps->_state = EXIT_NORMAL;
      break;
    }
    //加速
    else if (KEY_PRESS(VK_F1))
    {
      //防止一直加速导致sleepTime<0出现bug
      if (ps->_sleepTime >= 50)
      {
        ps->_sleepTime -= 30;
        ps->_foodWeight += 2;//加速时食物的分值会增加
      }
    }
    //减速
    else if (KEY_PRESS(VK_F2))
    {
      //防止一直减速导致程序运行太慢出现卡顿影响用户体验
      if (ps->_sleepTime < 350)
      {
        ps->_sleepTime += 30;
        ps->_foodWeight -= 2;
        //防止太慢时食物得分减为负数
        if (ps->_sleepTime == 350)
        {
          ps->_foodWeight = 1;
        }
      }
    }
    //蛇每次移动都要有一定的休眠时间,时间越短,蛇移动的速度就越快
    Sleep(ps->_sleepTime);
    SnakeMove(ps);
  } while (ps->_state == OK);
}
//暂停函数
void pause()
{
        while (1)
        {
            Sleep(200);
            if (KEY_PRESS(VK_SPACE))
            {
                break;
            }
        }
}

4.蛇身的移动

1.整体框架

void SnakeMove(Snake* ps)
{
  //1.根据蛇头的坐标和方向,计算下一个节点的坐标
  int x = ps->_pSnake->x;
  int y = ps->_pSnake->y;
  switch (ps->_dir)
  {
  case UP:
    y--;
    break;
  case DOWN:
    y++;
    break;
  case LEFT:
    x -= 2;
    break;
  case RIGHT:
    x += 2;
    break;
  }
  //2.创建下一个节点
  SNode* pNextNode = (SNode*)malloc(sizeof(SNode));
  if (pNextNode == NULL)
  {
    perror("SnakeMove():: malloc fail");
    exit(-1);
  }
  pNextNode->x = x;
  pNextNode->y = y;
  pNextNode->next = NULL;
  //3.判断下一个是不是食物
  if (x == ps->_pFood->x && y == ps->_pFood->y)
  {
    //下一个位置有食物
    EatFood(pNextNode, ps);
  }
  //下一个位置没有食物
  else
  {
    NoFood(pNextNode, ps);
  }
  //判断是否撞墙
  IfKillByWall(ps, x, y);
  //判断是否咬到自己
  IfKillBySelf(ps, x, y);
}

下面我们就要实现一下下面的这4个函数,那么SnakeMove函数就成功完成了

2.EatFood和NoFood函数

所以我们就可以写出这样的代码

3.IfKillByWall和IfKillBySelf函数

这两个函数的返回值类型可以是void

因为我们可以直接在这两个函数当中修改游戏当前状态

也就是ps->_state

因此我们可以这样写:

5.GameRun部分的完整代码

这里只写了这一部分的完整代码

需要再加上GameStart部分的完整代码才可以正常运行

1.完整代码

Snake.h

#define KEY_PRESS(VK) ((GetAsyncKeyState(VK) & 0x1) ? 1 : 0)
void pause();
void GameRun(Snake* ps);
void PrintHelpInfo();
void EatFood(SNode* pNextNode, Snake* ps);
void NoFood(SNode* pNextNode, Snake* ps);
void IfKillByWall(Snake* ps, int x, int y);
void IfKillBySelf(Snake* ps, int x, int y);
void SnakeMove(Snake* ps);

Snake.c

//暂停函数
void pause()
{
  while (1)
  {
    Sleep(200);
    if (KEY_PRESS(VK_SPACE))
    {
      break;
    }
  }
}
void GameRun(Snake* ps)
{
  PrintHelpInfo();
  do
  {
    SetPos(65, 10);
    printf("得分: %d , 每个食物得分: %d ", ps->_score, 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_SPACE))
    {
      pause();
    }
    //Esc退出
    else if (KEY_PRESS(VK_ESCAPE))
    {
      ps->_state = EXIT_NORMAL;
      break;
    }
    //加速
    else if (KEY_PRESS(VK_F1))
    {
      //防止一直加速导致sleepTime<0出现bug
      if (ps->_sleepTime >= 50)
      {
        ps->_sleepTime -= 30;
        ps->_foodWeight += 2;//加速时食物的分值会增加
      }
    }
    //减速
    else if (KEY_PRESS(VK_F2))
    {
      //防止一直减速导致程序运行太慢出现卡顿影响用户体验
      if (ps->_sleepTime < 350)
      {
        ps->_sleepTime += 30;
        ps->_foodWeight -= 2;
        //防止太慢时食物得分减为负数
        if (ps->_sleepTime == 350)
        {
          ps->_foodWeight = 1;
        }
      }
    }
    //蛇每次移动都要有一定的休眠时间,时间越短,蛇移动的速度就越快
    Sleep(ps->_sleepTime);
    SnakeMove(ps);
  } while (ps->_state == OK);
}
void PrintHelpInfo()
{
  SetPos(65, 17);
  printf("不能穿墙,不能咬到自己");
  SetPos(65, 18);
  printf("用↑.↓.←.→ 分别控制蛇的移动");
  SetPos(65, 19);
  printf("F1为加速,F2为减速");
  SetPos(65, 20);
  printf("Esc: 退出游戏  space:暂停游戏");
  SetPos(65, 22);
  printf("编写者:wzs");
}
void EatFood(SNode* pNextNode, Snake* ps)
{
  pNextNode->next = ps->_pSnake;
  ps->_pSnake = pNextNode;
  //打印蛇身
  SNode* cur = ps->_pSnake;
  while (cur)
  {
    SetPos(cur->x, cur->y);
    wprintf(L"%lc", BODY);
    cur = cur->next;
  }
  //释放食物节点
  free(ps->_pFood);
  ps->_pFood = NULL;
  //加分
  ps->_score += ps->_foodWeight;
  //创建新食物
  CreateFood(ps);
}
void NoFood(SNode* pNextNode, Snake* ps)
{
  pNextNode->next = ps->_pSnake;
  ps->_pSnake = pNextNode;
  //释放最后一个节点
  SNode* 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 IfKillByWall(Snake* ps, int x, int y)
{
  if (x == 0 || x == 56 || y == 0 || y == 26)
  {
    ps->_state = KILL_BY_WALL;
  }
}
//判断是否咬到自己
void IfKillBySelf(Snake* ps, int x, int y)
{
  SNode* cur = ps->_pSnake->next;
  while (cur)
  {
    if (cur->x == ps->_pSnake->x && cur->y == ps->_pSnake->y)
    {
      ps->_state = KILL_BY_SELF;
      break;
    }
    cur = cur->next;
  }
}
void SnakeMove(Snake* ps)
{
  //1.根据蛇头的坐标和方向,计算下一个节点的坐标
  int x = ps->_pSnake->x;
  int y = ps->_pSnake->y;
  switch (ps->_dir)
  {
  case UP:
    y--;
    break;
  case DOWN:
    y++;
    break;
  case LEFT:
    x -= 2;
    break;
  case RIGHT:
    x += 2;
    break;
  }
  //2.创建下一个节点
  SNode* pNextNode = (SNode*)malloc(sizeof(SNode));
  if (pNextNode == NULL)
  {
    perror("SnakeMove():: malloc fail");
    exit(-1);
  }
  pNextNode->x = x;
  pNextNode->y = y;
  pNextNode->next = NULL;
  //3.判断下一个是不是食物
  if (x == ps->_pFood->x && y == ps->_pFood->y)
  {
    //下一个位置有食物
    EatFood(pNextNode, ps);
  }
  //下一个位置没有食物
  else
  {
    NoFood(pNextNode, ps);
  }
  //判断是否撞墙
  IfKillByWall(ps, x, y);
  //判断是否咬到自己
  IfKillBySelf(ps, x, y);
}

test.c

int main()
{
    setlocale(LC_ALL, "");
    system("mode con cols=120 lines=35");
    system("title 贪吃蛇");
    Init();
    Snake snake = { 0 };//将snake结构体变量的内容全都初始化为0
    //(这里主要是为了初始化p_Snake头节点的指针,为了防止头插法创建蛇身链表时出现野指针的非法访问问题)
    //p_Snake=0;而NULL指针的本质就是(void(*)0),在数值上0跟NULL是相等的,这里可以认为p_Snake==NULL
    srand((unsigned int)time(NULL));//设置随机数种子,防止每一次运行rand生成的随机数都是一样的
    GameStart(&snake);
    GameRun(&snake);
    SetPos(0, 30);//这里我们要定位一下光标,
    //防止最后打印的那条包含:"返回值为0"的语句因为光标最后处于打印食物位置的下一行
    //而导致覆盖我们的墙体
    return 0;
}

2.最终实现情况

咬到自己:

撞墙:

6.游戏结束后的处理

1.代码实现

2.Y/N 是否再来一局

int main()
{
  setlocale(LC_ALL, "");
  system("mode con cols=120 lines=35");
  system("title 贪吃蛇");
  Init();
  char input = 0;
  do
  {
    Snake snake = { 0 };//p_Snake=0;而NULL指针的本质就是(void(*)0),在数值上0跟NULL是相等的,这里可以认为p_Snake==NULL
    srand((unsigned int)time(NULL));
    GameStart(&snake);
    GameRun(&snake);
    GameEnd(&snake);
    SetPos(65, 26);
    printf("要在玩一局吗?(Y/N)");
    input = getchar();
    getchar();//清理'\n'
    system("cls");//清屏
    SetPos(45,12);
    if (input == 'n' || input == 'N')
    {
      printf("欢迎再次在玩");
    }
    else if (input == 'Y' || input == 'y')
    {
      printf("游戏即将开始,祝您玩的开心");
      SetPos(45, 14);
      system("pause");
      system("cls");//清屏
    }
  } while (input == 'y' || input == 'Y');
  SetPos(32, 0);
  return 0;
}

三.总结

上面就是我们贪吃蛇代码的整体分析和梳理

其实我们的整体思路就是这个图片所展现的

我们只需要先把大概的框架全部完成

具体的函数先声明出来

然后我们剩下的任务就只有去把那些函数一一实现即可

以上就是贪吃蛇代码实现与剖析(C语言)的全部内容,希望能对大家有所帮助!

相关文章
|
1月前
|
存储 搜索推荐 C语言
深入C语言指针,使代码更加灵活(二)
深入C语言指针,使代码更加灵活(二)
|
1月前
|
存储 程序员 编译器
深入C语言指针,使代码更加灵活(一)
深入C语言指针,使代码更加灵活(一)
|
1月前
|
C语言
深入C语言指针,使代码更加灵活(三)
深入C语言指针,使代码更加灵活(三)
深入C语言指针,使代码更加灵活(三)
|
2月前
|
定位技术 API C语言
C语言——实现贪吃蛇小游戏
本文介绍了一个基于Windows控制台的贪吃蛇游戏的实现方法。首先,需调整控制台界面以便更好地显示游戏。接着,文章详细描述了如何使用Win32 API函数如`COORD`、`GetStdHandle`、`GetConsoleCursorInfo`等来控制控制台的光标和窗口属性。此外,还介绍了如何利用`GetAsyncKeyState`函数实现键盘监听功能。文中还涉及了`&lt;locale.h&gt;`库的使用,以支持本地化字符显示。
57 1
C语言——实现贪吃蛇小游戏
|
1月前
|
C语言 定位技术 API
【C语言】实践:贪吃蛇小游戏(附源码)(二)
【C语言】实践:贪吃蛇小游戏(附源码)
【C语言】实践:贪吃蛇小游戏(附源码)(二)
|
2月前
|
安全 C语言
在C语言中,正确使用运算符能提升代码的可读性和效率
在C语言中,运算符的使用需要注意优先级、结合性、自增自减的形式、逻辑运算的短路特性、位运算的类型、条件运算的可读性、类型转换以及使用括号来明确运算顺序。掌握这些注意事项可以帮助编写出更安全和高效的代码。
49 4
|
1月前
|
存储 定位技术 API
C语言项目实战:贪吃蛇
C语言项目实战:贪吃蛇
|
1月前
|
C语言
【C语言】实践:贪吃蛇小游戏(附源码)(三)
【C语言】实践:贪吃蛇小游戏(附源码)
|
1月前
|
存储 API C语言
【C语言】实践:贪吃蛇小游戏(附源码)(一)
【C语言】实践:贪吃蛇小游戏(附源码)
|
1月前
|
C语言
C语言练习题代码
C语言练习题代码