SDL2 游戏开发日记(九) 单机麻将

SDL2 游戏开发日记(九) 单机麻将

单机麻将的基本功能其实年前已经完成了,只是写文档麻烦,再加上懒癌和重度拖延症,就一直拖着没更新。今天周末一个人没什么事干,抽空把它更新了。

麻将的表示

用数组表示,int card[136];值分别是 0-135;

值/4

0-8:表示万,9-17:表示饼,18-26:表示条,27-33:表示东南西北中发白

class MahjongCard : public Renderable{
private :
	int mCardNumber; //牌值,0-135
	bool mIsSelected;	//是否被选中的状态,玩家鼠标选择出牌时用
	Vector2I mOffset;	//选中后的位置偏移量,鼠标选择出牌时用
public :
	void SetCardNumber(int cardNumber){
		mCardNumber = cardNumber;
	}
	int GetCardNumber(){
		return mCardNumber;
	}
	bool IsSelected(){
		return mIsSelected;
	}

	void SetSelected(bool bSelected){
		mIsSelected = bSelected;
	}
	
	void SetOffset(int xOffset, int yOffset){
		mOffset.x = xOffset;
		mOffset.y = yOffset;
	}

	Vector2I &GetOffset(){
		return mOffset;
	}
	
};

麻将算法

分为胡牌算法和出牌ai

胡牌算法:声明一个辅助数组 int cardAssists[38],用0填充。如果是判断自摸,则遍历手上的牌并根据index的值填充辅助数组。如果是判断吃胡,则遍历手上的牌和最后一张打出的牌。并根据index的值填充辅助数字。

index = 具体的牌值/4:如果值小于等于8,cardAssists[index+1] ++;即cardAssists数组的1-9表示万,

如果index的值大于等于9并且小于等于17,cardAssists[index+2] ++;即11-19表示饼

如果index的值大于等于18并且小于等于26,cardAssists[index+3]++;即21-29表示条。

如果index的值大于等于27,cardAssists[index+4] ++;即31-37表示字牌。

class MahjongAI{
	
	//递归调用
	bool IsHu(){
		int sum = 0;
		for (int i = 0; i < 38; i++){
			sum += mCardAssistArray[i];
		}		
		if (sum == 0){
			//匹配完了,如果有找到将牌,表示可以胡牌了。
			if (mIsFindJiang)
				return true;
			else return false;
		}
		int index = 0;
		//跳过没有的牌
		for (index = 0; index < 38 && mCardAssistArray[index] == 0; index++);
		//如果是一刻,把这一刻去掉
		if (mCardAssistArray[index] >= 3){
			mCardAssistArray[index] -= 3;
			//再判断剩下的牌是否胡牌。
			if (IsHu()){
				return true;
			}			
			//没有胡牌,把这一刻加回去
			mCardAssistArray[index] += 3;
		}
		//如果是一对,并且还未找到将牌,
		if (mCardAssistArray[index] >= 2 && !mIsFindJiang){
			mIsFindJiang = true;
			mCardAssistArray[index] -= 2;
			//去掉,并判断剩下的牌能不能胡
			if (IsHu()){
				return true;
			}
			mIsFindJiang = false;
			//不能胡,加回去
			mCardAssistArray[index] += 2;
		}
		//索引大于30的不判断顺子
		if (index > 30)
			return false;
		//判断如果能组成顺子,把顺子牌拿掉,
		if (mCardAssistArray[index + 1] >= 1 && mCardAssistArray[index + 2] >= 1){
			mCardAssistArray[index] --;
			mCardAssistArray[index + 1] --;
			mCardAssistArray[index + 2] --;
			//判断剩下的牌能不能胡牌
			if (IsHu()){
				return true;
			}
			//不能胡牌,加回数组中
			mCardAssistArray[index] ++;
			mCardAssistArray[index + 1] ++;
			mCardAssistArray[index + 2] ++;
		}
		return false;
	}

}

出牌ai:判断有没有单独的字牌和单独的牌->拆掉那些不是对子并且不是顺子的牌->判断最佳的听牌组合->经过上面的方法还选不出来该出的牌?那就随机出牌。

MahjongCard *MahjongAI::GetBestOutCard(){
	MahjongCard *card = NULL;
	QueryInCards();
	vector<MahjongCard*> randomCardList,allCardList;
	CardMap &inHandcard = mPlayer->GetInHandCard();
	printf("inhandcard size:%d\n",inHandcard.size());
	CardMap::reverse_iterator iter = inHandcard.rbegin();
	while (iter != inHandcard.rend()){
		int cardIndex = GetCardIndex(iter->second);
		if (cardIndex > 30){
			if (mCardAssistArray[cardIndex] == 1){
				//printf("单独的字牌:%d\n", cardIndex);
				randomCardList.push_back(iter->second);
			}
		}
		else{
			if (mCardAssistArray[cardIndex] == 1){
				if (mCardAssistArray[cardIndex - 1] == 0 && mCardAssistArray[cardIndex+1] == 0){
					//printf("单独的牌:%d\n", cardIndex);
					randomCardList.push_back(iter->second);
				}
			}
		}
		allCardList.push_back(iter->second);
		iter++;
		printf("%d,",cardIndex);
	}
	printf("\n");
	if (randomCardList.size() == 0){		
		printf("不知道打什么牌1:进一步选择");
		while (iter != inHandcard.rend()){
			int cardIndex = GetCardIndex(iter->second);
			if (cardIndex > 30){
				break;
			}
			else{
				if (mCardAssistArray[cardIndex] == 1){
					if (mCardAssistArray[cardIndex - 1] >= 1 && mCardAssistArray[cardIndex + 1] >= 1){
						iter++;
						continue;
					}
					else if (mCardAssistArray[cardIndex + 1] >= 1 && mCardAssistArray[cardIndex + 2] >= 1){
						iter++;
						continue;
					}
					else{
						if (cardIndex % 10>2){
							if (mCardAssistArray[cardIndex - 2] >= 1 && mCardAssistArray[cardIndex - 1] >= 1){
								iter++;
								continue;
							}
						}
					}
					card = iter->second;
					printf(":%d\n", GetCardIndex(card));
					break;					
				}
			}						
		}
	}
	else{
		int index = rand() % randomCardList.size();
		card = randomCardList[index];
	}
	if (card == NULL){
		printf("进一步选择失败,判断ting\n");
		int assistArray[38];
		int bestIndex = -1, bestTingCount = -1;
		for (int i = 0; i < 38; i++){
			if (mCardAssistArray[i] == 0)
				continue;
			mCardAssistArray[i] --;
			memcpy(assistArray, mCardAssistArray, sizeof(assistArray));
			int tingCount = TingCount(assistArray);
			if (tingCount > 0){
				printf_s("Ting:%d,cardIndex:%d\n",tingCount,i);
				if (tingCount > bestTingCount){
					bestTingCount = tingCount;
				
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值