C++贪吃蛇设计

利用C++设计简单的控制台贪吃蛇游戏.

第一步:设计地图类:

class Map
{
private:
public:
	enum{MAPX = 10, MAPY = 2};
	enum{ROW = 20, COL = 40};
	char map[ROW][COL];				//地图
	Map();
	void DrawMap();					//绘制地图
	bool IsVaildPoint(int x, int y);
};

1.利用枚举来定义常量,在类外部可以通过作用域解析来获取枚举常量,便于所有类的交流.

2.通过二维数组存储地图,在构造的时候读取并绘制地图,

3.定义一个外部接口,用于判断点是否在地图上.


第二步:设计甜点类

class Snack;
class Dessert
{
private:
	int mark;		//分数
	char figure;
public:
	int x;
	int y;
	Dessert(int mark = 10, const char str = '$');
	~Dessert(void);
	void DrawDessert();			//绘制图形
	int GetMark(){return mark;} //获得积分
	void MakeNewDessert(const Snack &snack);
};

      1.使用前向声明,让编译器知道Snack类的存在

      2. MakeNewDessert更新甜点.


第三步:设计蛇类

class Dessert;
class Map;
class Point
{
public:
	int x;
	int y;
	void Draw(char ch)const
	{
		gotoxy(y, x);
		putchar(ch);
	}
};
class Snack
{
private:
	int len;				//蛇身的长度
	int MaxOpp;				//最大缓存操作
	vector<Point> Body;		//蛇身,默认蛇头为下标最大的点
	int v;					//速度
	Move dirction;
	queue<Move> moves;		//操作队列
	int num_moves;
public:
	Snack(int v = 200);
	~Snack(void);
	Point & operator[](int i)
	{
		return this->Body[i];
	}
	bool isBody(int x, int y)const;	//是否是蛇身的一部分
	//移动蛇身
	int MoveBody(Map &map, Dessert &d);
	//操作符入队列
	void InMoves(Move d);
	int GetV(){return v;};
};

      1.使用队列缓存操作.

      2.蛇要移动的时候,先从操作队列中读取操作,如果为空,默认移动的方向为当前的方向.

      参考代码:

int Snack::MoveBody(Map &map, Dessert &d)
{
	Point p;
	const Point &head = Body[len - 1];		//蛇头
	const Point &tail = Body.front();		//蛇尾
	
	Move move;
	bool flag = false;			//标示是否有操作
	
	while(!moves.empty())
	{
		move = moves.front();
		moves.pop();
		this->num_moves--;
		if(isReverseDirection(move, this->dirction))
			continue;
		else
		{
			flag = true;
			break;
		}
	}
	
	if(!flag)					//没有操作时自动行走
		move = this->dirction;

	this->dirction = move;				//更新运动方向

	switch(move)
	{
	case UP:
		p.x = head.x - 1;
		p.y = head.y;
		break;	
	case RIGHT:
		p.x = head.x;
		p.y = head.y + 1;
		break;	
	case DOWN:
		p.x = head.x + 1;
		p.y = head.y;
		break;	
	case LEFT:
		p.x = head.x;
		p.y = head.y - 1;
		break;	
	}

	if(!map.IsVaildPoint(p.x, p.y) || this->isBody(p.x, p.y))
	{
		return 0;		//失败
	}

	p.Draw('#');		//画新蛇头
	head.Draw('*');		//更新旧蛇头
	
	if(d.x == p.x && d.y == p.y)
	{
		Body.push_back(p);	//蛇身增长
		len++;
		return 1;		//吃到东西
	}
	tail.Draw(' ');		//去掉旧蛇尾
	for(int i = 0; i < len - 1; i++)
	{
		Body[i] = Body[i + 1];
	}
	Body[len - 1] = p;
	return 2;
}

void Snack::InMoves(Move d)
{
	if(this->num_moves >= this->MaxOpp)
		return;
	this->moves.push(d);
	this->num_moves++;
}

第四步:设计游戏类

class GamePlayer
{
	
private:
	int mark;				//分数
	int lvl;				//当前关数
	int getPress();			//获得按键符合
public:
	Map map;				//地图
	Snack snack;			//蛇
	Dessert dessert;		//甜点
	
	GamePlayer(void);
	~GamePlayer(void);
	void PressHandle();
	void WaitStart();
	bool isEnd(){return false;};
	int Getv(){return snack.GetV();};
	void MoveHandle();
	void updateMark();
	int getMark(){return mark;};
};

1.     把游戏逻辑的处理交给游戏类

2.     PressHandle();处理按键输入和执行

3.     getPress();是内部方法,应该隐藏起来

4.     MoveHandle();处理蛇身移动


第五步:测试游戏

#include <iostream>
#include <conio.h>
#include <cstdlib>
#include "GamePlayer.h"
#include <cstdlib>
#include <time.h>
#include <cstdio>
using namespace std;
int main()
{
	srand((unsigned)time(0));
	hideCursor();

	GamePlayer game;

	while(!game.isEnd())
	{
		long start;
		start = clock();             /*record the start time */
		while((clock() - start) <= game.Getv())			//固定时间
		{
			if(kbhit())
				game.PressHandle();
		}
		game.MoveHandle();

	}
	cin.get();
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值