字牌跑胡子王赖听牌算法c++|lua实现详解

static const vector<int> publicPailib
{
	101,102,103,104,105,106,107,108,109,110,
	101,102,103,104,105,106,107,108,109,110,
	101,102,103,104,105,106,107,108,109,110,
	101,102,103,104,105,106,107,108,109,110,
	201,202,203,204,205,206,207,208,209,210,
	201,202,203,204,205,206,207,208,209,210,
	201,202,203,204,205,206,207,208,209,210,
	201,202,203,204,205,206,207,208,209,210
};

static const int kindpai = 555;              //王赖牌

字牌有大字40张小字40张,特殊玩法会带王赖。

我们在玩字牌的时候,打出一张牌的时候会思考接下来听什么牌:

现在有手牌:101  102  103  104 105 106 107 108 109 110 (桌低有跑牌要做将情况)

暂时先不考虑最小和牌胡息就会有以下组合听牌:

(101 102 103)(104 105 106)(107 108 109)听 110

(101 102 103)(104 105 106)(108 109 110)听 107

(101 102 103)(105 106 107)(108 109 110)听 104

(102 103 104)(105 106 107)(108 109 110)听 101

那用代码的形式我们该怎样实现呢?

这里先找出手牌中由3个牌组成的所有有效组合。

(101 102 103)(102,103,104)(103,104,105)(104,105,106)

 (105,106,107)(106,107,108)(107,108,109) (108,109,110)

(102,107,110)

然后从有效组合中找出(手牌数除以3)组(101 102 103)(104 105 106)(107 108 109)

这样的有效牌组剩什么牌,再拿剩下的牌去判断听什么样的牌就行了。

有王赖的情况下会递归一层,用王赖替换掉可以组成有效牌型的牌,代码中做了很多优化,

不然纯穷举的话,时间复杂度会很高,特别是赖子很多情况下。

3张4张王的情况复杂度会很高。

4张王赖最高特殊情况用了27m,最低小于1秒。

王赖建议不要在工作中使用。

测试:

void test()
{
	//vector<int> handPokers = getRandziPai(9);             //随机发牌
	//handPokers.emplace_back(kindpai);
	//handPokers.emplace_back(kindpai);
	//handPokers.emplace_back(kindpai);
	//handPokers.emplace_back(kindpai);
	vector<int> handPokers = { 101,101,101,104,105,106,107,108,109,110 };
	handPokers.emplace_back(kindpai);
	//vector<int> handPokers = { 104,105,106,104,105,106,108,108,208,110,110,210,205,206,207,206,207,208 ,101,102,203};
	map<int, int> res;
	int huxi = 0;
	getTingPai(handPokers,res, huxi);

	for (auto it = res.begin(); it != res.end(); it++)
	{
		cout << " ting:" << it->first << " hufen:" << it->second << endl;
	}
}

int main()         //算听啥
{
	srand(time(unsigned(NULL)));
	while (getchar())
	{
		auto start = std::chrono::system_clock::now();
		test();
		auto end = std::chrono::system_clock::now();
		std::chrono::duration<double> elapsed_seconds = end - start;
		std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n";
	}

	getchar();
	return 0;
}

测试结果:

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值