微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

cocos2d-x俄罗斯方块--基于简单工厂的程序重构

1 前言

前些天看了一个Cocos2D写的俄罗斯方块代码(下载网址为:http://www.okbase.net/file/item/27944),代码逻辑很清晰。

2 讨论

俄罗斯方块游戏逻辑很简单(其实细节也很多),主要包含五个部分:下移、左移、右移、形状变换(上移)以及消行。于是,该代码的结构为:

这么写存在什么问题?举个例子,如果此时,玩家需要新增或自定义一些方块的样式,并将其加入至程序中,如何修改?对于上面的程序,无非是打开每一个函数添加Switch分支,并为每一个分支实现独立逻辑。

经常写代码的朋友一定知道,需求的更改最为恼人,尤其是当这些需求的更改将导致客户端代码的大量修订。解决这一问题的常用方法是将客户段逻辑与计算逻辑分离。那么对于这一游戏来说,能否采用这一设计来优化并重构现有代码

想要完成这一重构,我们必须想清楚,哪些属于客户端逻辑,哪些属于计算逻辑。很明显,当前得分,当前方块的行列位置,都属于客户端逻辑,而方块的具体逻辑动作:上(变换)、下、左、右、消除,都属于计算逻辑,如果我们将这些计算逻辑抽象出来,就能够实现计算逻辑与客户端的低耦合。如何抽象?很简单,声明一个父类,并定义所有的计算逻辑,如下:

class Square
{
public:
	//向下移动处理
	bool WhetherCanTodown(int pCurrLine,int pCurrColumn);
	void GoTodown(int pCurrLine,int pCurrColumn);
	//向左移动处理
	bool WhetherCanToLeft(int pCurrLine,int pCurrColumn);
	void GoToLeft(int pCurrLine,int pCurrColumn);
	//向右移动处理
	bool WhetherCanToRight(int pCurrLine,int pCurrColumn);
	void GoToRight(int pCurrLine,int pCurrColumn);
	//处理特定行
	bool ClearLastLine();
	void ClearLines(int linestart,int lineEnd);
protected:
	CCSprite*** pSquare;//窗体精灵数组
	int pRow,pColumn;//固定行列
};
之后,声明子类,并依此独立实现基类的方法,以下面这一方块为例:


//SquareType1成员
SquareType1::SquareType1(int pRow,int pColumn,CCSprite*** pSquare)
{
	this->pRow=pRow;
	this->pColumn=pColumn;
	this->pSquare=pSquare;
}

//向下移动处理
bool SquareType1::WhetherCanTodown(int pCurrLine,int pCurrColumn)
{
	for (int i = 0; i < 4; i++)
	{
		if (pSquare[pCurrLine][pCurrColumn + i]->getTag() == 1)//下层存在方块,禁止向下移动
		{
			return false;
		}
	}
	return true;
}
void SquareType1::GoTodown(int pCurrLine,int pCurrColumn)
{
	//下降一格
	for (int i = 0; i < 4; i++)
	{
		//消除原色:档处于第一行时,无需消除原色
		if (pCurrLine < pRow && pCurrLine > 0)
		{
			pSquare[pCurrLine - 1][pCurrColumn + i]->setColor(ccc3(255,255,255));
			pSquare[pCurrLine - 1][pCurrColumn + i]->setTag(0);
		}
		//显示新色
		if (pCurrLine < pRow)
		{
			pSquare[pCurrLine][pCurrColumn + i]->setColor(ccc3(52,228,249));
			pSquare[pCurrLine][pCurrColumn + i]->setTag(1);
		}
	}
}

//向左移动处理
bool SquareType1::WhetherCanToLeft(int pCurrLine,int pCurrColumn)
{
	if (pCurrLine < 1 || pCurrColumn <= 0 || pSquare[pCurrLine - 1][pCurrColumn - 1]->getTag() == 1)
	{
		return false;
	}
	return true;
}
void SquareType1::GoToLeft(int pCurrLine,int pCurrColumn)
{
	pSquare[pCurrLine - 1][pCurrColumn - 1]->setColor(ccc3(52,249));
	pSquare[pCurrLine - 1][pCurrColumn - 1]->setTag(1);
	pSquare[pCurrLine - 1][pCurrColumn + 3]->setColor(ccc3(255,255));
	pSquare[pCurrLine - 1][pCurrColumn + 3]->setTag(0);
}

//向右移动处理
bool SquareType1::WhetherCanToRight(int pCurrLine,int pCurrColumn)
{
	if (pCurrLine - 1 < 0 || pCurrColumn + 3 >= pColumn - 1 || pSquare[pCurrLine - 1][pCurrColumn + 3 + 1]->getTag() == 1)
	{
		return false;
	}
	return true;
}
void SquareType1::GoToRight(int pCurrLine,int pCurrColumn)
{
	pSquare[pCurrLine - 1][pCurrColumn + 3 + 1]->setColor(ccc3(52,249));
	pSquare[pCurrLine - 1][pCurrColumn + 3 + 1]->setTag(1);
	pSquare[pCurrLine - 1][pCurrColumn]->setColor(ccc3(255,255));
	pSquare[pCurrLine - 1][pCurrColumn]->setTag(0);
}

//方块运行至最后一行
void SquareType1::ProcessLastLine()
{
	ClearLines(pRow - 1,pRow - 1);
}

//变换当前方块的类型
bool SquareType1::WhetherCanChangeSquareType(int pCurrLine,int pCurrColumn)
{
	if (pCurrLine + 1 > pRow - 1)
	{
		return false;
	}
	for (int i = 0; i < 4; i++)
	{
		if (i != 1 && pCurrLine - 2 + i > -1 && pSquare[pCurrLine - 2 + i][pCurrColumn + 1]->getTag() == 1)
		{
			return false;
		}
	}
	return true;
}
void SquareType1::ChangeSquareType(int pCurrLine,int pCurrColumn)
{
	for (int i = 0; i < 4; i++)
	{
		if (i != 1 && pCurrLine - 1 > -1)
		{
			pSquare[pCurrLine - 1][pCurrColumn + i]->setColor(ccc3(255,255));
			pSquare[pCurrLine - 1][pCurrColumn + i]->setTag(0);
		}
		if (i != 1 && pCurrLine - 2 + i > -1)
		{
			pSquare[pCurrLine - 2 + i][pCurrColumn + 1]->setColor(ccc3(52,249));
			pSquare[pCurrLine - 2 + i][pCurrColumn + 1]->setTag(1);
		}
	}
}

之后,在客户端中,利用工厂方法的方式实例化某一特定类型的方块,并将其赋值给父类

Square* square=new SquareType1; 
从此,程序中所有的行为都用square进行操作。这有什么好处?1) 程序将及其简短;2) 需要添加其他类型方块?直接继承父类并独立实现其计算逻辑,客户端代码修改量为零。至此,程序的维护性与稳定性提升了一个等级。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐