神秘博客

纯C写贪吃蛇游戏

用了链表添头去尾的方法,添加了历史排行榜用文件统计,分数 等级 难度,暂停

#ifndef _SNAKE_H_
#define _SNAKE_H_
#include <stdbool.h>
//食物
typedef struct food
{
  int x;
  int y;
  int count;
} Food;


//蛇身
typedef struct item
{
  int x;
  int y;
} Item;

typedef struct snake
{
  Item item;
  struct snake *last;
  struct snake *next;
} Snake;

typedef struct list
{
  int hp;
  Snake *head;
  Snake *end;
} List;

static int PauseGame = 0;

//排行榜
typedef struct score
{
  int one;
  int two;
  int three;
} Score;

//绘制地图
void Map();

//初始化蛇
void InitializeSnake(List *pts);

//添加蛇
bool AddSnake(Item *snake, List *pts);

//显示蛇
void ShowSnake(List *pts);

//移动蛇
void MoveSnake(Food *tfood, List *pts);

//初始化食物
void InitializeFood(Food *temp);

//生成食物
void Foods(Food *temp, List *pts);

//判断食物是否与蛇身重叠
bool FoodSnake(Food *temp, List *pts);

//设置光标位置
void gotoxy(int x, int y);

//判断蛇碰到地图边界
bool MapSnake(List *pts);

//判断蛇碰到自己
bool MeSnake(List *pts);

//游戏统计
void ShowScore(Score *pt, List *pts);

//游戏速度控制
int Speed(List *pts);

//清除蛇
void DeleteSnake(List *pts);

//得分写入结构
void WriteData(Score *pt, List *pts);

#endif

#include <Windows.h>
#include <stdio.h>
#include "snake.h"

enum Key { U, D, L, R };

//设置光标位置
void gotoxy(int x, int y)
{
  COORD pos = { x,y };
  HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);// 获取标准输出设备句柄
  SetConsoleCursorPosition(hOut, pos);//两个参数分别是指定哪个窗体,具体位置
}

//初始化蛇
void InitializeSnake(List *pts)
{
  pts->head = pts->end = NULL;
  pts->hp = 0;
}

//添加蛇
bool AddSnake(Item *snake, List *pts)
{
  Snake *temp;

  temp = (Snake *)malloc(sizeof(Snake));
  if (temp == NULL)
  {
    fputs("错误: 添加蛇身失败", stderr);
    return false;
  }
  temp->item = *snake;
  temp->last = NULL;
  temp->next = NULL;
  pts->hp++;
  if (pts->end != NULL)
  {
    temp->last = pts->end;
    pts->end->next = temp;
  }
    
  if (pts->head == NULL)
  {
    pts->head = temp;
    pts->end = temp;
  }
  else
    pts->end = temp;
  ShowSnake(pts);
  return true;
}

//显示蛇
void ShowSnake(List *pts)
{
  Snake *temp;
  temp = pts->head;

  while (temp != NULL)
  {
    gotoxy(temp->item.x, temp->item.y);
    printf("■");
    temp = temp->next;
  }
  
}

//移动蛇
void MoveSnake(Food *tfood, List *pts)
{
  Snake *temp;  //添加新蛇头节点
  Snake *Temp;  //保存蛇尾上一个节点
  Item item;  //保存蛇尾坐标
  static char ch = D; //获取键值
  int Hp;
  Hp = pts->hp;

  temp = (Snake *)malloc(sizeof(Snake));
  temp->item = pts->head->item;
  temp->next = pts->head;
  temp->last = NULL;
  pts->head->last = temp;
  pts->head = temp;


  if (temp->item.x == tfood->x&&temp->item.y == tfood->y)
  {
    item = pts->end->item;
    pts->hp++;
    tfood->count--;
  }
  else
  {
    Temp = pts->end->last;
    Temp->next = NULL;
    item = pts->end->item;
    free(pts->end);
    pts->end = Temp;
  }
  
  if (GetAsyncKeyState(VK_UP) && ch != D)
  {
    ch = U;
  }
  else if (GetAsyncKeyState(VK_DOWN) && ch != U)
  {
    ch = D;
  }
  else if (GetAsyncKeyState(VK_LEFT) && ch != R)
  {
    ch = L;
  }
  else if (GetAsyncKeyState(VK_RIGHT) && ch != L)
  {
    ch = R;
  }
  else if (GetAsyncKeyState(VK_SPACE) && PauseGame == 1)
  {
    PauseGame = 2;
  }

  switch (ch)
  {
  case U:
    temp->item.y--;
    break;
  case D:
    temp->item.y++;
    break;
  case L:
    temp->item.x -= 2;
    break;
  case R:
    temp->item.x += 2;
    break;
  default:
    break;
  }
  gotoxy(temp->item.x, temp->item.y);
  printf("■");
  if (pts->hp == Hp)
  {
    if (item.x == temp->item.x&&item.y == temp->item.y); //防止追尾时清除蛇头
    else
    {
      gotoxy(item.x, item.y);
      printf(" ");
    }
  }

  //重置光标到底部
  gotoxy(0, 27);
}

//初始化食物
void InitializeFood(Food *temp)
{
  
  temp->x = temp->y = temp->count = 0;
}

//判断食物是否与蛇身重叠
bool FoodSnake(Food *temp, List *pts)
{
  Snake *Temp;
  Temp = pts->head;
  while (Temp != NULL)
  {
    if (temp->x == Temp->item.x&&temp->y == Temp->item.y)
      return false;
    Temp = Temp->next;
  }

  return true;
}

//生成食物
void Foods(Food *temp, List *pts)
{

  if (temp->count == 0)
  {
    temp->x = (rand() % 25 + 1) * 2;
    temp->y = rand() % 24 + 1;
    while (!FoodSnake(temp, pts))
    {
      temp->x = (rand() % 25 + 1) * 2;
      temp->y = rand() % 24 + 1;
    }
    temp->count++;
    gotoxy(temp->x, temp->y);
    printf("■");
  }
}

//判断蛇碰到地图边界
bool MapSnake(List *pts)
{
  if (pts->head->item.x < 2 || pts->head->item.x > 50)
    return false;
  if (pts->head->item.y < 1 || pts->head->item.y > 25)
    return false;
  return true;
}

//判断蛇碰到自己
bool MeSnake(List *pts)
{
  Snake *temp;
  temp = pts->head->next;

  while (temp != NULL)
  {
    if (pts->head->item.x == temp->item.x&&pts->head->item.y == temp->item.y)
      return false;
    temp = temp->next;
  }

  return true;
}

//游戏统计
void ShowScore(Score *pt, List *pts)
{
  gotoxy(58, 1);
  printf("历史排行榜:");
  gotoxy(62, 3);
  printf("第1名: %d", pt->one);
  gotoxy(62, 5);
  printf("第2名: %d", pt->two);
  gotoxy(62, 7);
  printf("第3名: %d", pt->three);
  gotoxy(58, 14);
  printf("游戏统计:");
  gotoxy(62, 16);
  printf("得分: %d", (pts->hp - 3) * 10);
  gotoxy(62, 18);
  printf("等级: %d", (pts->hp - 3) / 10 + 1);
  gotoxy(62, 20);
  printf("难度: %d", (pts->hp - 3) / 15 + 1);

  gotoxy(58, 24);
  printf("游戏状态: ");

  if (PauseGame == 0)
  {
    gotoxy(69, 24);
    printf("请按任意键开始");
    gotoxy(0, 27);
    system("pause");
    gotoxy(0, 27);
    printf("                    ");
    PauseGame = 1;
  }
  else if (PauseGame == 1)
  {
    gotoxy(69, 24);
    printf("游戏运行中   ");
    gotoxy(69, 26);
    printf("空格键暂停游戏");
    gotoxy(0, 27);
  }
  else if (PauseGame == 2)
  {
    gotoxy(69, 24);
    printf("游戏暂停中    ");
    gotoxy(69, 26);
    printf("任意键开始游戏");
    gotoxy(0, 27);
    system("pause");
    gotoxy(0, 27);
    printf("                    ");
    PauseGame = 1;
  }


}

//游戏速度控制
int Speed(List *pts)
{
  int speed = 300;

  speed -= (pts->hp - 3) / 15 * 30;

  return speed;
}

//绘制地图
void Map()
{
  int i;

  for (i = 0; i < 54; i += 2)
  {
    gotoxy(i, 0);
    printf("■");
    gotoxy(i, 26);
    printf("■");
  }

  for (i = 1; i < 26; i++)
  {

    gotoxy(0, i);
    printf("■");
    gotoxy(52, i);
    printf("■");
  }
  gotoxy(58, 9);
  printf("游戏说明:");
  gotoxy(62, 11);
  printf("控制: ↑ ↓ ← →");

  gotoxy(0, 27);
}

//清除蛇
void DeleteSnake(List *pts)
{
  Snake *temp;
  temp = pts->head;
  while (temp != NULL)
  {
    pts->head = pts->head->next;
    free(temp);
    temp = pts->head;
  }
}

//得分写入结构
void WriteData(Score *pt, List *pts)
{
  int temp;

  temp = (pts->hp - 3) * 10;

  if (temp > pt->one&&temp > pt->two&&temp > pt->three)
  {
    pt->three = pt->two;
    pt->two = pt->one;
    pt->one = temp;
  }
  else if (temp <= pt->one&&temp > pt->two&&temp > pt->three)
  {
    pt->three = pt->two;
    pt->two = temp;
  }
  else if (temp <= pt->one&&temp <= pt->two&&temp > pt->three)
    pt->three = temp;

}
#include <stdio.h>
#include <Windows.h>
#include <time.h>
#include <stdlib.h>
#include "snake.h"



int main()
{
  List snake;
  Item temp;
  int i;
  Food F_food;
  Score t_list;
  errno_t err;
  FILE *fp;

  while ((err = fopen_s(&fp, "data.dat", "rb")) != 0)
  {
    //如果没有数据文件创建新文件并把初始化结构写入文件
    if ((err = fopen_s(&fp, "data.dat", "wb")) != 0)
    {
      fputs("错误: 创建数据文件失败", stderr);
      exit(EXIT_FAILURE);
    }
    t_list.one = t_list.two = t_list.three = 0;
    fwrite(&t_list, sizeof(Score), 1, fp);
    fclose(fp);
  }
  rewind(fp);//打开文件回到开始
  fread(&t_list, sizeof(Score), 1, fp); //读取文件记录

  //初始化蛇
  InitializeSnake(&snake);
  for (i = 0; i < 3; i++)
  {
    temp.x = 16;
    temp.y = 8 - i;
    if (!AddSnake(&temp, &snake))
    {
      fputs("错误: 初始化蛇身失败\n", stderr);
      exit(EXIT_FAILURE);
    }
  }

  //初始化地图
  Map();
  srand((unsigned int)time(0));  //随机种子
  //初始化食物
  InitializeFood(&F_food);
  while (1)
  {
    ShowScore(&t_list, &snake);
    //生成食物
    Foods(&F_food, &snake);
    MoveSnake(&F_food, &snake);
    if (!MapSnake(&snake))  //判断蛇碰到边界
    {
      gotoxy(69, 24);
      printf("碰到地图边界, 游戏结束.");
      gotoxy(69, 26);
      printf("              ");
      WriteData(&t_list, &snake);
      //重置光标到底部
      gotoxy(0, 27);
      break;
    }
    if (!MeSnake(&snake))  //判断蛇碰到自己
    {
      gotoxy(69, 24);
      printf("碰到自己, 游戏结束.");
      gotoxy(69, 26);
      printf("              ");
      WriteData(&t_list, &snake);
      //重置光标到底部
      gotoxy(0, 27);
      break;
    }

    Sleep(Speed(&snake));
  }
  fclose(fp);
  if ((err = fopen_s(&fp, "data.dat", "wb")) != 0)
  {
    fputs("错误: 创建数据文件失败", stderr);
    exit(EXIT_FAILURE);
  }
  fwrite(&t_list, sizeof(Score), 1, fp);
  DeleteSnake(&snake);
  fclose(fp);
  system("pause");
  return 0;
}

 

版权说明:
点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注

觉得文章有用就请我吃包辣条吧

微信扫一扫打赏