贪吃蛇游戏——C/C++

整理一下以前学习时找到的程序。

一、游戏框架

在这里插入图片描述
1、蛇
蛇时以链表的形式保存的,增加长度是就新建节点,每次移动(刷新)蛇头向前进方向移动一格,把最后的节点删除;如果吃到食物就不删除尾部。

2、游戏
(1)撞墙:判断头部是否到达超过边界
(2)撞自己:遍历链表,判断头部是否在链表中位置一样
(3)加速减速:改变每次刷新(延时)时间

二、游戏代码

1、snake.h

#pragma once
#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 30				//地图的行
#define COL_MAP 90				//地图的列
#define SUCCESS_SCORE 1000		//通关分数

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.cpp

#include "Snake.h"

pSnake head = NULL; //定义蛇头指针
pSnake Food = NULL; //定义食物指针
int sleeptime = 500;//间隔时间,用来控制速度
int Score = 0;		//总分
int everyScore = 1; //每步得分

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

//控制输出光标
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 0B");
	printf("\t\t\t\t*******************************************************\n");
	printf("\t\t\t\t*                Welcome to Snake Game!               *\n");
	printf("\t\t\t\t*                                                     *\n");
	printf("\t\t\t\t*             -> 开始游戏 Enter 键                    *\n");
	printf("\t\t\t\t*             -> 退出游戏 Esc 键                      *\n");
	printf("\t\t\t\t*             -> 暂停游戏 Space 键                    *\n");
	printf("\t\t\t\t*             -> F1键减速 F2键加速                    *\n");
	printf("\t\t\t\t*             -> 上下左右控制蛇的移动	              *\n");
	printf("\t\t\t\t*******************************************************\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;
		newNode->y = 10 - i;
		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 = sleeptime + 50;
			everyScore = everyScore - 1;
			Pos(COL_MAP + 20, 2);
			printf("%d", everyScore);
		}
	}

	else if (GetAsyncKeyState(VK_F2))
	{
		if (sleeptime > 50)
		{
			sleeptime = sleeptime - 50;
			everyScore = everyScore + 1;
			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;
}

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

三、游戏界面

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值