#ifndef MAHJONG_ALG_HEAD_FILE
#define MAHJONG_ALG_HEAD_FILE

#include "MahJongStruct.h"

//! 齫ɫ
/*!
	齫ɫ,ָеĻɫ
*/
enum enMahJongColor
{
	MahJongColor_Invalid	= 0x00,											/*!< Чֵ */
	MahJongColor_Wan		= 0x01,											/*!<  */
	MahJongColor_Tiao		= 0x02,											/*!<  */
	MahJongColor_Bing		= 0x04,											/*!< Ͳ */
	MahJongColor_Word		= 0x08,											/*!<  */
	MahJongColor_Flower		= 0x10											/*!<  */
};


//! 齫ͨ㷨
/*! 齫ͨ㷨ϣ齫㷨ֻ̳и༴ɡ
	\n Ѫս齫㷨ࣺCXZMahJongAlg
	\n class CXZMahJongAlg : public CMahJongAlg
	\n {
	\n 	//ı...
	\n
	\n 	//չķ...
	\n }
	\n ʹʱʹûͨ÷չķ
	\n CXZMahJongAlg* xzAlg = new CXZMahJongAlg(MahJongColor_Wan|MahJongColor_Tiao|MahJongColor_Bing);
	\n xzAlg->ķ();
	\n xzAlg->չķ();
	\noteʼʱҪ齫ɫ
	\sa CMahJongLogic
*/
class CMahJongAlg
{
private:
	MJBYTE				m_bMahJongColor;									/*!< 齫ɫ(ֻ) */

public:
	//! 캯
	/*!
		,Ĭϵ齫ɫ(ֻ)
		\param bMahJongColor 齫ɫ,ÿһλһɫ,enMahJongColor.Ĭɫ:ֻ
	*/
	CMahJongAlg(MJBYTE bMahJongColor = (MahJongColor_Wan|MahJongColor_Tiao|MahJongColor_Bing|MahJongColor_Word|MahJongColor_Flower)){ srand((uint32)time(NULL)); m_bMahJongColor = bMahJongColor; }

	//! 齫ɫ
	/*!
		齫ɫ,MJBYTEʾ,ÿһλһɫ
		\param bMahJongColor 齫ɫ,ÿһλһɫ,enMahJongColor
		\sa enMahJongColor, GetMahJongColor()
	*/
	inline void SetMahJongColor(MJBYTE bMahJongColor){ m_bMahJongColor = bMahJongColor; }

	//! ȡ齫ɫ
	/*!
		ȡ齫ɫ,MJBYTEʾ,ÿһλһɫ
		\return 齫ɫ,ÿһλһɫ,enMahJongColor
		\sa enMahJongColor, SetMahJongColor()
	*/
	inline MJBYTE GetMahJongColor(){ return m_bMahJongColor; }

	//
public:
	//! ȡ
	/*!
		ȡָΧ
		\param iMin ,Χ߽
		\param iMax ,Χұ߽
		\return iMiniMax֮
	*/
	virtual inline int GetRandomNum(int iMin, int iMax)
	{
		srand((uint32)time(NULL));
		return rand() % (iMax + 1 - iMin) + iMin;
	}

	//! 
	/*!
		˳,ҵĴRANDOM_TIMES
		\param bAllMJ 
		\param bAllMJCount С
		\sa RANDOM_TIMES
	*/
	virtual void RandomMJ(MJBYTE bAllMJ[], int bAllMJCount);

	//! 
	/*!
		С
		\param bAllMJ 
		\param bAllMJCount С
	*/
	virtual void SortHandMJ(MJBYTE bAllMJ[], int bAllMJCount);

	//! УǷ
	/*!
		УָǷ
		\param bAllMJ 
		\param bAllMJCount С
		\param bMJ ָ齫
		\return true-;false-
	*/
	virtual bool CheckMJExist(const MJBYTE bAllMJ[], int bAllMJCount, MJBYTE bMJ);

	//! ɾָ齫
	/*!
		ɾָ齫,ʱص(Ϊ0),1
		\param bAllMJ 
		\param bAllMJCount С
		\param bMJ ָ齫
		\return true-ɾɹ;false-ɾʧ
	*/
	virtual bool DeleteMJ(MJBYTE bAllMJ[], int &bAllMJCount, MJBYTE bMJ);

	//! ָ齫
	/*!
		\param bMJ 
		\param bMJCount С
		\param bM ָ齫
		\return ָ齫齫е
	*/
	virtual int GetMJCount(MJBYTE bMJ[], int &bMJCount, MJBYTE bM);

	//////////////////////////////////////////////////////////////////////////

	//ж
public:
	//! һж
	/*!
		жǷһƣ3*N+2Ƿܴճ 1ԽN齫
		\param bSelfHUMJ 
		\param bSelfHUMJCount С
		\param bSelfHandMJ 
		\param bSelfHandMJCount С
		\return true-ܺ;FLASE-ܺ
		\note жһĺʹ
	*/
	virtual bool IsNormalHu(MJBlock bSelfHUMJ[], int bSelfHUMJCount, MJBYTE bSelfHandMJ[], int bSelfHandMJCount);

	//
protected:
	//! һж
	/*!
		ʣǷܺʾ
		\param bHandMJ 
		\param bHandMJCount С
		\return true-ܺ;FLASE-ܺ
		\note жһĺʹ IsNormalHu() 
		\sa IsNormalHu(), CheckIsHu()
	*/
	virtual bool CheckRestHu(MJBYTE bHandMJ[], int bHandMJCount);

	//! һж
	/*!
		ǷܺƵĸMAX_ARRAY_MJС
		\param bMJ 齫
		\param bMaxCount 齫С
		\return true-ܺ;FLASE-ܺ
		\note жһĺʹ IsNormalHu() 
		\sa CheckRestHu(), MAX_ARRAY_MJ
	*/
	virtual bool CheckIsHu(MJBYTE bMJ[], int bMaxCount);

	//! ϹǷʣ
	/*!
		ǷʣƣƵĸMAX_ARRAY_MJС
		\param bMJ 齫
		\param bMaxCount 齫С
		\return Ƶĸ
		\note жһĺʹ IsNormalHu() 
		\sa MAX_ARRAY_MJ
	*/
	virtual int Remain(MJBYTE bMJ[], int bMaxCount);

	//! ȡ
	/*!
		пܵĺ,磺333 444 555 123 77ҲΪ345 345 345 123 7738
		\param bMJ 齫
		\param bMaxCount 齫С
		\param huTree 齫
		\return Ƿܴճ
		\note ȡʹ GetHuCombination() 
	*/
	virtual bool GetAllCombination(MJBYTE bMJ[], int bMaxCount, HuTree huTree);

	//! ȡƽṹ
	/*!
		ȡƽṹ(ƿ飬ʱ(ڵݹݴһ)Ŀп)
		\param huTree 齫
		\param bData 齫
		\param iCombinaCount 齫С
		\param bTmpData ʱ,ڵݹݴһ
		\param iCombinaIndex ǰ齫齫,bMaxBlockһ
		\param bMaxBlock 齫齫С
		\return Ƿܴճ1
		\note ȡʹ GetHuCombination() 
	*/
	virtual void ExtractHuBlock(HuNode *huTree, MJBlock bData[][MAX_BLOCK_COUNT], int &iCombinaCount, MJBlock bTmpData[MAX_BLOCK_COUNT], int &iCombinaIndex, MJBYTE bMaxBlock);

	//! ͷڴ
	/*!
		ͷڴͷźڴ
		\param huTree 齫ָ
	*/
	virtual void ReleaseHuTree(HuNode *huTree);

	//
public:
	//! ÿ
	/*!
		ø3Ƶ
		\param bMJ1 һ
		\param bMJ2 ڶ
		\param bMJ3 
		\return enBlockStyle
		\sa enBlockStyle
	*/
	virtual enBlockStyle GetBlockStyle(MJBYTE bMJ1, MJBYTE bMJ2, MJBYTE bMJ3);

	//! Ƽӵ
	/*!
		õ(˴)ƺһȻ,浽bCombineMJ
		\param bHandMJ 
		\param iHandMJCount С
		\param bMJ 
		\param bCombineMJ 
		\param iCombineMJCount С
	*/
	virtual void CombineHandMJ(MJBYTE bHandMJ[], int iHandMJCount, MJBYTE bMJ, MJBYTE bCombineMJ[], int &iCombineMJCount);

	//! пܵĺ
	/*!
		пܵĺ,(,ƸϿ(ǿ)ϸ)
		\param bHandMJ 
		\param iHandMJCount С
		\param bData Ͻṹ
		\param iCombinaCount ϽṹС
	*/
	virtual void GetHuCombination(MJBYTE bHandMJ[], int iHandMJCount, MJBlock bData[][MAX_BLOCK_COUNT], int &iCombinaCount);
};

#endif
