一、贪吃蛇小游戏简介:

        用上下左右控制蛇的方向,寻找吃的东西,每吃一口就能得到一定的积分,而且蛇的身子会越吃越长,身子越长玩的难度就越大,不能碰墙,也不能咬到自己的身体,等到了一定的分数,就能过关。 

二、函数框架

三、数据结构

typedef struct Snake
{
  size_t x; //行
  size_t y; //列
  struct Snake* next;
}Snake, *pSnake;

定义蛇的结构体,利用单链表来表示蛇,每个结点为蛇身体的一部分。 

四、代码实现(vs2010  c语言)

1.Snake.h

#ifndef __SNAKE_H__
#define __SNAKE_H__

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <time.h>
#include <malloc.h>
#include <assert.h>
//标识地图大小
#define ROW_MAP 10  //地图的行
#define COL_MAP 20  //地图的列
#define SUCCESS_SCORE 10//通关分数
enum Direction //蛇行走的方向
{
  R, //右
  L, //左
  U, //上
  D //下
}Direction;

enum State
{
  ERROR_SELF, //咬到自己
  ERROR_WALL, //撞到墙
  NORMAL,   //正常状态
  SUCCESS   //通关
}State;

typedef struct Snake
{
  size_t x; //行
  size_t y; //列
  struct Snake* next;
}Snake, *pSnake;


void StartGame();
void RunGame();
void EndGame();

#endif

2.Snake.c

#include "Snake.h"


pSnake head = NULL; //定义蛇头指针
pSnake Food = NULL; //定义食物指针

int sleeptime = 500;//间隔时间,用来控制速度
int Score = 0; //总分
int everyScore = 1; //每步得分

//定义游戏中用到的符号
const char food = '#';
const char snake = '*';

void Pos(int x, int y)  //控制输出光标
{
  COORD pos; //pos为结构体
  pos.X = x; //控制列
  pos.Y = y; //控制行
  SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);//读取标准输出句柄来控制光标为pos
}

void Face()
{
  system("color 0C");
  printf("*******************************************************\n");
  printf("*        Welcome to Snake Game!        *\n");
  printf("*                           *\n");
  printf("*       ->开始游戏请按 enter键         *\n");
  printf("*       ->退出游戏请按 esc键          *\n");
  printf("*       ->暂停游戏请按 space键         *\n");
  printf("*       ->通过上下左右键来控制蛇的移动     *\n");
  printf("*       ->通过F1键减速    F2键加速     *\n");
  printf("*******************************************************\n");
}
void Map()  //初始化地图
{
  int i = 0;
  for(i = 0; i<COL_MAP; i+=2)  //打印上下边框(每个■占用两列)
  {
    Pos(i, 0);
    printf("■");
    Pos(i, ROW_MAP-1);
    printf("■");
  }
  for(i = 0; i<ROW_MAP; i++)  //打印左右边框
  {
    Pos(0, i);
    printf("■");
    Pos(COL_MAP-2, i);
    printf("■");
  }
}
void PrintSnake() //打印蛇
{
  pSnake cur = head;
  while(cur)
  {
    Pos(cur->y, cur->x);
    printf("%c", snake);
    cur = cur->next;
  }
}
void InitSnake()  //初始化蛇身
{
  int initNum = 3;
  int i = 0;
  pSnake cur;
  head = (pSnake)malloc(sizeof(Snake));
  head->x = 5;
  head->y = 10;
  head->next = NULL;

  cur = head;
  for(i = 1; i < initNum; i++)
  {
    pSnake newNode = (pSnake)malloc(sizeof(Snake));
    newNode->x = 5+i;
    newNode->y = 10;
    newNode->next = NULL;
    cur->next = newNode;
    cur = cur->next;
  }

  PrintSnake();
}

void CreateFood() //在地图上随机产生一个食物
{
  pSnake cur = head;
  Food = (pSnake)malloc(sizeof(Snake));

  //产生x~y的随机数 k=rand()%(Y-X+1)+X;
  srand((unsigned)time(NULL));
  Food->x = rand()%(ROW_MAP-2 - 1 + 1)+1;
  Food->y = rand()%(COL_MAP-3 - 2 + 1)+2;
  Food->next = NULL;
  while(cur)  //检查食物是否与蛇身重合
  {
    if(cur->x == Food->x && cur->y == Food->y)
    {
      free(Food);
      Food = NULL;
      CreateFood();
      return;
    }
    cur = cur->next;
  }
  Pos(Food->y, Food->x);
  printf("%c", food);
}

void StartGame() //游戏开始的所有设置
{
  Face();
  system("pause");

  if(GetAsyncKeyState(VK_RETURN))
  {
    system("cls");
    Pos(COL_MAP+5, 1);
    printf("当前分数/通关分数:");
    Pos(COL_MAP+20, 1);
    printf("%d/%d", Score, SUCCESS_SCORE);
    Pos(COL_MAP+5, 2);
    printf("当前分每步得分:");
    Pos(COL_MAP+20, 2);
    printf("%d", everyScore);
    Pos(COL_MAP+5, 3);
    printf("\n");
    Pos(COL_MAP+5, 4);
    printf("速度越快 得分越高哦!!\n");

    Map();
    InitSnake();
    CreateFood();
  }
  else if(GetAsyncKeyState(VK_ESCAPE))
  {
    exit(0);
  }
}

int IsCrossWall()       //判断是否碰到墙
{
  if(head->x <= 0 || head->x >= ROW_MAP-1
    ||head->y <= 1 || head->y >= COL_MAP-2)
  {
    State = ERROR_WALL;
    return 0;
  }
  return 1;
}

int IsEatSelf(pSnake newHead) //判断是否咬到自己
{
  pSnake cur = head;
  assert(newHead);
  while(cur)
  {
    if(cur->x == newHead->x && cur->y == newHead->y)
    {
      State = ERROR_SELF;
      return 0;
    }
    cur = cur->next;
  }
  return 1;
}

int IsFood(pSnake pos) //判断该位置是不是食物
{
  assert(pos);
  if(pos->x == Food->x && pos->y == Food->y)
  {
    return 1;
  }
  return 0;
}

void SnakeMove()  //蛇移动一次
{
  pSnake newHead = NULL;
  newHead = (pSnake)malloc(sizeof(Snake));

  if(Direction == R)
  {
    newHead->x = head->x;
    newHead->y = head->y+1;
    newHead->next = head;
  }
  else if(Direction == L)
  {
    newHead->x = head->x;
    newHead->y = head->y-1;
    newHead->next = head;
  }
  else if(Direction == U)
  {
    newHead->x = head->x-1;
    newHead->y = head->y;
    newHead->next = head;

  }
  else if(Direction == D)
  {
    newHead->x = head->x+1;
    newHead->y = head->y;
    newHead->next = head;
  }

  if(IsFood(newHead))
  {
    head = newHead;
    PrintSnake();
    CreateFood();
    Score += everyScore;
    Pos(COL_MAP+20, 1);
    printf("%d/%d", Score, SUCCESS_SCORE);
    if(Score >= SUCCESS_SCORE)
    {
      State = SUCCESS;
    }
  }
  else
    {
      if(IsCrossWall() && IsEatSelf(newHead))
      {
        pSnake cur = NULL;
        head = newHead;
        cur = head;
        //删除蛇尾并打印
        while(cur->next->next != NULL)
        {
          Pos(cur->y, cur->x);
          printf("%c", snake);
          cur = cur->next;
        }

        Pos(cur->y, cur->x);
        printf("%c", snake);
        Pos(cur->next->y, cur->next->x);
        printf(" "); //打印空格来覆盖频幕上的蛇尾
        free(cur->next);
        cur->next = NULL;
      }
      else
      {
        free(newHead);
        newHead = NULL;
      }
  }
}

void Pause()
{
  while(1)
  {
    Sleep(sleeptime);
    if(GetAsyncKeyState(VK_SPACE))
    {
      break;
    }
  }
}

void ControlSnake() //用键盘控制游戏
{
  if(GetAsyncKeyState(VK_UP) && Direction!=D)
  {
    Direction = U;
  }
  else if(GetAsyncKeyState(VK_DOWN) && Direction!=U)
  {
    Direction = D;
  }
  else if(GetAsyncKeyState(VK_LEFT) && Direction!=R)
  {
    Direction = L;
  }
  else if(GetAsyncKeyState(VK_RIGHT) && Direction!=L)
  {
    Direction = R;
  }
  else if(GetAsyncKeyState(VK_F1))
  {
    if(sleeptime != 500)
    {
      sleeptime = 500;
      everyScore = 1;
      Pos(COL_MAP+20, 2);
      printf("%d", everyScore);
    }
  }
  else if(GetAsyncKeyState(VK_F2))
  {
    if(sleeptime != 300)
    {
      sleeptime = 300;
      everyScore = 2;
      Pos(COL_MAP+20, 2);
      printf("%d", everyScore);
    }
  }
  else if(GetAsyncKeyState(VK_SPACE))
  {
    Pause();
  }
  else if(GetAsyncKeyState(VK_ESCAPE))
  {
    exit(0);
  }
}

void StateGame() //判断游戏失败或成功
{
  if(State == ERROR_SELF)
  {
    system("cls");
    printf("很遗憾,蛇咬到自己,游戏失败!\n");
  }
  else if(State == ERROR_WALL)
  {
    system("cls");
    printf("很遗憾,蛇碰到墙壁,游戏失败!\n");
  }
  else if(State == SUCCESS)
  {
    system("cls");
    printf("恭喜您,已通关!!!\n");
  }

}
void RunGame()
{
  Direction = R; //蛇初始行走方向为右
  State = NORMAL;//游戏初始为正常状态
  while(1)
  {
    ControlSnake();
    SnakeMove();
    if(State != NORMAL)
    {
      StateGame();
      break;
    }
    Sleep(sleeptime);
  }
}

void EndGame() //释放链表并恢复默认值
{
  pSnake cur = head;
  while(cur)
  {
    pSnake del = cur;
    cur = cur->next;
    free(del);
    del = NULL;
  }
  head = NULL;
  if(Food != NULL)
  {
    free(Food);
    Food = NULL;
  }
  Score = 0;
  everyScore = 1;
  sleeptime = 500;
}

3.Test.c

#include "Snake.h"

int main()
{
  while(1)
  {
    StartGame();
    RunGame();
    EndGame();
  }
  system("pause");
  return 0;
}

五、运行界面展示

1.欢迎界面

 

2.游戏界面


小小的c语言项目,用来练手,仅供参考哦!!
谢谢阅读,如有问题,欢迎提出。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

02-09 18:36