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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章