原来还有这么通俗易懂的贪吃蛇写法

(语言:C++ 版本:vs 2019 community )

提示:文章最末有代码的GitHub链接,可以直接下载,别忘记给星哦!
温馨提示:本代码对于锦城的学生尤其适用!(转载本文请指明出处)

文章目录

  • 前言
  • 一、代码框架
  • 二、核心功能
  • 三、运行截图
  • 四、代码


前言

贪吃蛇是我们的一个基本项目,但是我发现网上的贪吃蛇有很多拓展的写法,对于一些只需要的基本需求的贪吃蛇,有时候还不能拿来直接用,于是乎,在学校写这个贪吃蛇的时候,我就顺便记录一下。(本代码没有图形化,没有使用EasyX图形库)
本文中的贪吃蛇一些功能如下:
1.蛇的自由移动(w,s,a,d)
2.蛇移动时有效输入的判断:例如蛇往右移动时,输入a蛇不能改向
3.蛇的吃食物变长,分数增加,等级提升
3.食物的随机出现
4.背景音乐:用了playSound函数,不需要直接注释掉
5.菜单:不需要的话直接不添加文件并需要稍微修改原有代码


一、代码框架

贪吃蛇项目总体上用了6个类封装,分别是CUnit类, CFood类,CMap类, CSnake类, CGame类, CMenu类。

CUnit类主要功能:实现一个点的显示与擦除。

CFood类主要功能:创建随机食物位置。

CMap类主要功能:初始化窗口大小,绘制地图,显示初始信息。

CSnake类主要功能:显示、擦除,自由移动,吃食物蛇身变长等。

CGame类主要功能:运行、结束游戏,隐藏光标,运行时检测游戏等级、游戏分数、食物是否被吃并改变相应显示信息。

CMenu类主要功能:游戏加载页面,菜单显示。

二、核心功能

CSnake类:新增quitGame()函数,用于实现选择退出游戏。在该蛇的自由移动过程中,另外实现了按空格键暂停,按q键选择退出游戏,按+键增加游戏速度。

CMap类:新增了drawGameWindows函数,用于实现初始化游戏界面大小。

CGame类:增加了hideCursor函数,用于实现隐藏光标,增加了GameOver函数,用于蛇死亡后的一系列操作。

CMenu类:新增类,增加了showMenu()函数(菜单显示),startGame()函数(开始游戏),quitGame()函数(退出游戏),gameHelp()函数(游戏帮助),loadGame()函数(加载游戏界面)。

三、运行截图

原来还有这么通俗易懂的贪吃蛇写法_第1张图片
原来还有这么通俗易懂的贪吃蛇写法_第2张图片

原来还有这么通俗易懂的贪吃蛇写法_第3张图片
原来还有这么通俗易懂的贪吃蛇写法_第4张图片
原来还有这么通俗易懂的贪吃蛇写法_第5张图片

四、代码

Cunit类:

//.h
```cpp
#pragma once
#include
class Cunit
{
     
public:
	Cunit(int x = 0, int y = 0, char pic = '*');
	virtual ~Cunit();
	void show();
	void erase();
	static void gotoxy(int x, int y);

public:
	int m_ix;
	int m_iy;
	char m_cPic;
};
#include "CUnit.h"
#include
using namespace std;
Cunit::Cunit(int x, int y, char pic)
{
     
	m_ix = x;
	m_iy = y;
	m_cPic = pic;
}
Cunit::~Cunit()
{
     
}
void Cunit::gotoxy(int x, int y)
{
     
	COORD pos = {
      x,y };
	pos.X = x;
	pos.Y = y;
	//设置光标位置 
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}
void Cunit::show()
{
     
	gotoxy(m_ix, m_iy);
	cout << m_cPic;
}
void Cunit::erase()
{
     
	gotoxy(m_ix, m_iy);
	cout << " ";
}

CFood类:

#pragma once
#include "CUnit.h"
class CFood :
    public Cunit
{
     
public:
    CFood(int x =0, int y=0, char pic = '#');
    virtual ~CFood();
    void createPos();
};
#include "CFood.h"
#include"CUnit.h"
#include"CMap.h"
#include
#include
#include

using namespace std;

CFood::CFood(int x, int y, char pic) : Cunit(x, y, pic)
{
     

}

CFood::~CFood()
{
     

}

void CFood::createPos()
{
     
	/*m_ix = CMap::KLEFT + rand() % (CMap::KWIDTH - 2);
	m_iy = CMap::KUP + rand() % (CMap::KHEIGHT - 4);*/
	m_ix = CMap::KLEFT + rand() % (CMap::KWIDTH - CMap::KLEFT - 1);
	m_iy = CMap::KUP + rand() % (CMap::KHEIGHT - CMap::KUP - 1);
}

CSnake类:

#pragma once
#include"CFood.h"
#include
#include
#include
#include
using namespace std;

typedef enum {
     
	w,s,a,d
}Directions;
class CSnake
{
     
public:
	CSnake(int x = 40, int y = 15, int length = 4, Directions direction = d, int speed = 400, char pic = '*');
	virtual~CSnake();
	bool move();
	void eraseSnake();
	void eraseSnake(int flag);
	bool changeDirections(char vkValue);
	void changeDirections(Directions dir);  //改变方向
	bool quitGame();
	bool eatFood(CFood* pfood);
	bool checkFoodPos(CFood *pFood);    //检查食物位置
	void movePos();
	void growup();
	void showSnake();
public:
	int m_iLength;
	int m_iHeadX;
	int m_iHeadY;
	int m_iSpeed;       //蛇当前速度
	char m_pic;
	Directions m_enumCurrentDirection;  //蛇当前方向
	vector<Cunit> m_vecBody;   //存储蛇的位置
};
#include
#include
#include
#include
#include"CSnake.h"
#include"Cunit.h"
#include"CMap.h"
#include"CFood.h"
#include"CMenu.h"


using namespace std;

CSnake::CSnake(int x, int y, int length, Directions direct, int speed, char pic)
{
     
	m_iLength = length;
	m_iHeadX = x;
	m_iHeadY = y;
	m_iSpeed = speed;
	m_pic = pic;
	m_enumCurrentDirection = direct;
	Cunit c(0, 0, '@');
	m_vecBody.push_back(c);
	m_vecBody[0].m_ix = m_iHeadX;
	m_vecBody[0].m_iy = m_iHeadY;
	for (int i = 1; i < m_iLength; i++)
	{
     
		Cunit c;
		m_vecBody.push_back(c);
		switch (m_enumCurrentDirection)
		{
     
		case w:
			m_vecBody[i].m_ix = m_iHeadX;
			m_vecBody[i].m_iy = m_iHeadY + i;
			break;
		case s:
			m_vecBody[i].m_ix = m_iHeadX;
			m_vecBody[i].m_iy = m_iHeadY - i;
			break;
		case a:
			m_vecBody[i].m_ix = m_iHeadX + i;
			m_vecBody[i].m_iy = m_iHeadY;
			break;
		case d:
			m_vecBody[i].m_ix = m_iHeadX - i;
			m_vecBody[i].m_iy = m_iHeadY;
			break;
		}
	}

}

CSnake::~CSnake()
{
     

}

//显示蛇
void CSnake::showSnake()
{
     
	for (int i = 0; i < m_iLength; i++)
	{
     
		m_vecBody[i].show();
	}
}

//擦除
void CSnake::eraseSnake()
{
     
	/*for (int i = 0; i < m_iLength; i++)
	{
		m_vecBody[i].erase();
	}*/
	int i;
	for (i = 0; i < m_iLength - 1; i++);
	m_vecBody[i].erase();
}

void CSnake::eraseSnake(int flag)
{
     
	for (int i = 0; i < m_iLength; i++)
		m_vecBody[i].erase();
}

//改变方向
bool CSnake::changeDirections(char vkValue)
{
     
	switch (vkValue)
	{
     
	case'w':
		m_vecBody[0].m_iy--;
		m_enumCurrentDirection = w;
		return false;
	case's':
		m_vecBody[0].m_iy++;
		m_enumCurrentDirection = s;
		return false;
	case'a':
		if (m_enumCurrentDirection == a)
			m_iSpeed -= 20;
		m_vecBody[0].m_ix--;
		m_enumCurrentDirection = a;
		return false;
	case'd':
		m_vecBody[0].m_ix++;
		m_enumCurrentDirection = d;
		return false;
	case 'q':    //代表quit
		changeDirections(m_enumCurrentDirection);
		showSnake();
		if (quitGame())
		{
     
			return true;
		}
		return false;
	case '+':
		changeDirections(m_enumCurrentDirection);
		showSnake();
		m_iSpeed -= 50;
		return false;
	case ' ':
		changeDirections(m_enumCurrentDirection);
		showSnake();
		Cunit::gotoxy(CMap::KLEFT, CMap::KHEIGHT + 1);
		cout << "游戏暂停,请按任意键继续...";
		_getch();    //游戏暂停
		Cunit::gotoxy(CMap::KLEFT, CMap::KHEIGHT + 1);
		for (int i = 0; i < 27; i++)
			cout << ' ';
		return false;
	default:
		changeDirections(m_enumCurrentDirection);
		showSnake();
		return false;
	}
}

void CSnake::changeDirections(Directions dir)
{
     
	switch (dir)
	{
     
	case w:
		m_vecBody[0].m_iy--;
		break;
	case s:
		m_vecBody[0].m_iy++;
		break;
	case a:
		m_vecBody[0].m_ix--;
		break;
	case d:
		m_vecBody[0].m_ix++;
		break;
	default:
		break;
	}
}

bool CSnake::quitGame()  //退出游戏
{
     
	Cunit::gotoxy(CMap::KLEFT, CMap::KHEIGHT + 1);
	cout << "退出游戏?(y/n):";
	char ch;
	cin >> ch;
	Cunit::gotoxy(CMap::KLEFT, CMap::KHEIGHT + 1);
	for (int i = 0; i < 17; i++)
		cout << ' ';
	if (ch == 'y')
	{
     
      return true;
	}
  else return false;
}

//存储移动坐标
void CSnake::movePos()
{
     
	for (int i = m_iLength - 1; i > 0; i--)
	{
     
		m_vecBody[i].m_iy = m_vecBody[i - 1].m_iy;
		m_vecBody[i].m_ix = m_vecBody[i - 1].m_ix;
	}
}

//移动
bool CSnake::move()
{
     
	bool flag = false;
	movePos();
	if (_kbhit())
	{
     
		char key;
		key = _getch();
		if (key == 'a' && m_enumCurrentDirection == d)
		{
     
			key = 'd';
			flag=changeDirections(key);
		}
		else if (key == 'd' && m_enumCurrentDirection == a)
		{
     
			key = 'a';
			flag=changeDirections(key);
		}
		else if (key == 'w' && m_enumCurrentDirection == s)
		{
     
			key = 's';
			flag=changeDirections(key);
		}
		else if (key == 's' && m_enumCurrentDirection == w)
		{
     
			key = 'w';
			flag=changeDirections(key);
		}
		else flag=changeDirections(key);
	}
	else changeDirections(m_enumCurrentDirection);
	showSnake();
	Sleep(m_iSpeed);
	eraseSnake();
	return flag;
}

//判断是否吃到食物
bool CSnake::eatFood(CFood* pfood)
{
     
	if (pfood->m_ix == m_vecBody[0].m_ix && pfood->m_iy == m_vecBody[0].m_iy)
		return true;
	else
		return false;
}

//检查食物位置是否在蛇身上
bool CSnake::checkFoodPos(CFood *pFood)
{
     
	for (int i = 0; i < m_iLength; i++)
	{
     
		if (pFood->m_ix == m_vecBody[i].m_ix &&
			pFood->m_iy == m_vecBody[i].m_iy)
			return true;
	}
	return false;
}

//蛇吃到食物变长
void CSnake::growup()
{
     
	Cunit c;
	m_vecBody.push_back(c);
	m_iLength++;
}

由于代码量过大,所以这里只附加了部分代码,更多的请点击GitHub链接:
https://github.com/qing-qing-mei/Snake

你可能感兴趣的:(c++)