[置顶] c++ 斗地主发牌程序中级(分配发牌算法)

    前言:欢迎转载,但请注明出处http://blog.csdn.net/jiadabin,因为原文可能会改动部分不足,最好从原文处阅读,同时也欢迎大家来点评丶吐槽!让我们大家共同进步......  


  前边一篇文章介绍了斗地主一般的发牌思路,今天我就分享一下有点难度的的分配发牌算法,欢迎各位提意见!

    需求是这样的:每局3个玩家手中至少有一个玩家手中有一个炸弹并且是随机发出的。

    解决思路是这样的:

    其实54张牌我们可以定义成一个这样的数组如下(其中元素为十六进制的数,括号内为十进制数)

static int card_arr[] = {
0x01(1 方块A), 0x11(17 梅花), 0x21(33 红桃), 0x31(49 黑桃),//A 
0x02(2 方块2), 0x12(18 梅花), 0x22(34 红桃), 0x32(50 黑桃),//2 
0x03(3 方块3), 0x13(19 梅花), 0x23(35 红桃), 0x33(51 黑桃),//3 
0x04(4 方块4), 0x14(20 梅花), 0x24(36 红桃), 0x34(52 黑桃),//4 
0x05(5 方块5), 0x15(21 梅花), 0x25(37 红桃), 0x35(53 黑桃),//5 
0x06(6 方块6), 0x16(22 梅花), 0x26(38 红桃), 0x36(54 黑桃),//6 
0x07(7 方块7), 0x17(23 梅花), 0x27(39 红桃), 0x37(55 黑桃),//7 
0x08(8 方块8), 0x18(24 梅花), 0x28(40 红桃), 0x38(56 黑桃),//8 
0x09(9 方块9), 0x19(25 梅花), 0x29(41 红桃), 0x39(57 黑桃),//9 
0x0A(10 方块10), 0x1A(26 梅花), 0x2A(42 红桃), 0x3A(58 黑桃),//10 
0x0B(11 方块J), 0x1B(27 梅花), 0x2B(43 红桃), 0x3B(59 黑桃),//J 
0x0C(12 方块Q), 0x1C(28 梅花), 0x2C(44 红桃), 0x3C(60 黑桃),//Q 
0x0D(13 方块K), 0x1D(29 梅花), 0x2D(45 红桃), 0x3D(61 黑桃),//K 
0x0E(14小王), 0x0F(15大王)
};

54张牌有了,下边我们针对这样的一副牌可以看出:1-13个数字就可以代表A-K了,所以我们就可以以这为基数,留下炸弹牌的基数,那么他另外的三张同值牌也就有了。

用一句来说也就是:先随机出1-N个炸弹,将炸弹的基数预留出来,在随机出每个玩家应该分配的炸弹数,把炸弹发给玩家,后其他牌随机发出即可。

下边请看具体代码:


<pre name="code" class="cpp">/*************************************************************************/
/***********斗地主发牌逻辑中级算法****************************************/
/*************************************************************************/
#include "stdafx.h"
#include <iostream>
#include <time.h>
#include <iomanip>
#include <vector>
#include <set>
#include <algorithm>  // 定义在该标准头文件中random_shuffle()定义在标准的头文件<algorithm.h>中。
//因为所有的STL算法都是在名字空间std::中声明的所以你要注意正确地声
//明数据类型。random_shuffle()有两个参数第一个参数是指向序列首元
//素的迭代器第二个参数则指向序列最后一个元素的下一个位置。
using namespace std;

void main()
{
	//存储54张牌的数组
	int card_arr[54] ={1,17,33,49,2,18,34,50,3,19,35,51,4,20,36,52,5,21,37,53,6,22,38,54,7,23,39,55,8,24,40,56,9,25,41,57,
		10,26,42,58,11,27,43,59,12,28,44,60,13,29,45,61,14,15};

	srand(time(NULL) + 1); //初始化随机数发送器 设置随机函数的启动数值
	
	int bomb_num = rand() % 3;
	if (bomb_num == 0){
		bomb_num =2;
		
	}

	//创建3个vector容器来装牌,注意容器是先进先出的。
	vector<int> new_arr_vc;
	vector<int> other_card_vc;
	vector<int> last_all_cards;
	new_arr_vc.clear(); // 装炸弹基数牌
	other_card_vc.clear();// 装除炸弹之外的牌
	last_all_cards.clear();// 装所有洗好的牌

	//new_arr_vc 0-12 共13个数字(玩家炸弹基数)
	for (int i = 0; i < 13; i++){
		new_arr_vc.push_back(i);
	}
	random_shuffle(new_arr_vc.begin(), new_arr_vc.end()); //随机函数 将其打乱
	for (int i = 12; i >=0; i--){
		cout<<setw(3)<<new_arr_vc[i];
	}

	cout<<endl;
	// 假设当炸弹数目为一个时 other_card_vc.size= (13-1)*4 =48 留四张牌凑一个炸弹
    // 假设当炸弹数目为两个时 other_card_vc.size= (13-2)*4 =44 留八张牌凑两个炸弹
	int othersize = 0; //调试时牌打印所用
	for (int i = 0; i< 13 - bomb_num; i++){
		for(int k=0; k < 4; k++){
			other_card_vc.push_back(card_arr[new_arr_vc[bomb_num+i]*4+k]);//new_arr_vc[bomb_num+i] 跳过要保留为炸弹基数的牌值
			cout<<setw(3)<<"other_card["<<othersize<<"]"<<other_card_vc[othersize]<<" pock base: "<<new_arr_vc[bomb_num+i]<<" ";
			othersize++;
		}
		cout<<endl;
	}
	cout<<endl;

	cout<<setw(3)<<"other_card_vc.size="<<other_card_vc.size()<<endl;
	other_card_vc.push_back(card_arr[52]); // 加入小王
	other_card_vc.push_back(card_arr[53]); // 加入大王
	random_shuffle(other_card_vc.begin(), other_card_vc.end()); //随机函数 将其打乱
	cout<<setw(3)<<"other_card_vc.size="<<other_card_vc.size()<<endl;

	// 随机玩家炸弹数
	unsigned int b_num1  = 0;	
	unsigned int b_num2  = 0; 
	unsigned int b_num3  = 0;

	int flag = rand() % 3;
	switch(bomb_num)
    {
		case 0:
			b_num1  = 0;	
			b_num2  = 0; 
			b_num3  = 0;
			break;
		case 1:
			if (flag == 0){
				b_num1  = 1;	
				b_num2  = 0; 
				b_num3  = 0;
			}else if (flag == 1){
				b_num1  = 0;	
				b_num2  = 1; 
				b_num3  = 0;
			}else{
				b_num1  = 0;	
				b_num2  = 0; 
				b_num3  = 1;
			}
			break;
		case 2:
			if (flag == 0){
				b_num1	= rand() %  3;
				b_num2	= rand() %  3;
				if (b_num1 + b_num2 >= 3){
					b_num1--;
					b_num2--;
				}
				b_num3 = bomb_num - b_num1 - b_num2;
			}else if (flag == 1){
				b_num1	= rand() %  3;
				b_num3	= rand() %  3;
				if (b_num1 + b_num3 >= 3){
					b_num1--;
					b_num3--;
				}
				b_num2 = bomb_num - b_num1 - b_num3;
			}else{
				b_num2	= rand() %  3;
				b_num3	= rand() %  3;
				if (b_num2 + b_num3 >= 3){
					b_num2--;
					b_num3--;
				}
				b_num1 = bomb_num - b_num2 - b_num3;
			}
			break;
		case 3:
			if (flag == 0){
				b_num1	= rand() %  4;
				b_num2	= rand() %  4;
				if (b_num1 + b_num2>=4 && b_num1 + b_num2<=5){
					b_num1--;
					b_num2--;
				}else if (b_num1 + b_num2 >= 6){
					b_num1 = b_num1 - 2;
					b_num2 = b_num2 - 2;	
				}else{
					//....
				}
				b_num3 = bomb_num - b_num1 - b_num2;
			}else if (flag == 1){
				b_num1	= rand() %  4;
				b_num3	= rand() %  4;
				if (b_num1 + b_num3>=4 && b_num1 + b_num3<=5){
					b_num1--;
					b_num3--;
				}else if (b_num1 + b_num3 >= 6){
					b_num1 = b_num1 - 2;
					b_num3 = b_num3 - 2;	
				}else{
					//....
				}
				b_num2 = bomb_num - b_num1 - b_num3;
			}else{
				b_num2	= rand() %  4;
				b_num3	= rand() %  4;
				if (b_num2 + b_num3>=4 && b_num2 + b_num3<=5){
					b_num2--;
					b_num3--;
				}else if (b_num2 + b_num3 >= 6){
					b_num2 = b_num2 - 2;
					b_num3 = b_num3 - 2;	
				}else{
					//....
				}
				b_num1 = bomb_num - b_num2 - b_num3;
			}
			break;
		default:
			break;
	}

	// 打印3个玩家分配到的炸弹数
	cout<<setw(3)<<"----player1:b_num1="<<b_num1<<"----"<<endl;
	cout<<setw(3)<<"----player2:b_num2="<<b_num2<<"----"<<endl;
	cout<<setw(3)<<"----player3:b_num3="<<b_num3<<"----"<<endl;

	int bomb_tmp = 0;
	int other_card = 0;
	for (int i = 0; i < 54;){
		if (last_all_cards.size() < 17){
			// 该判断是为了预留出炸弹的位置
			if (last_all_cards.size() < b_num1 * 4){
				// 满足条件分配炸弹  new_arr_vc[bomb_tmp]得到炸弹基数
				for (int j = 0; j < 4; j++){
					last_all_cards.push_back(card_arr[new_arr_vc[bomb_tmp] * 4 + j]);
					cout<<setw(3)<<"player1["<<i<<"]**zhang**:"<<last_all_cards[i]<<endl;
					i++;
					
				}
				bomb_tmp++;
			}else{
				last_all_cards.push_back(other_card_vc[other_card]);
				other_card++;
				cout<<setw(3)<<"player1["<<i<<"]zhang:"<<last_all_cards[i]<<endl;
				i++;
			}
			
		}else if (last_all_cards.size() >= 17 && last_all_cards.size() < 34){
			// 该判断是为了预留出炸弹的位置
			if (last_all_cards.size() < b_num2 * 4 + 17){
				// 满足条件分配炸弹
				for (int j = 0; j < 4; j++){
					last_all_cards.push_back(card_arr[new_arr_vc[bomb_tmp] * 4 + j]);
					cout<<setw(3)<<"player2["<<i<<"]**zhang**:"<<last_all_cards[i]<<endl;
					i++;
				}
				bomb_tmp++;
			}else{
				last_all_cards.push_back(other_card_vc[other_card]);
				other_card++;
				cout<<setw(3)<<"player2["<<i<<"]zhang:"<<last_all_cards[i]<<endl;
				i++;
			}
		}else if (last_all_cards.size() >= 34 && last_all_cards.size() < 51){
			// 该判断是为了预留出炸弹的位置
			if (last_all_cards.size() < b_num3 * 4 + 34){
				// 满足条件分配炸弹
				for (int j = 0; j < 4; j++){
					last_all_cards.push_back(card_arr[new_arr_vc[bomb_tmp] * 4 + j]);
					cout<<setw(3)<<"player3["<<i<<"]**zhang**:"<<last_all_cards[i]<<endl;
					i++;

				}
				bomb_tmp++;
			}else{
				last_all_cards.push_back(other_card_vc[other_card]);
				other_card++;
				cout<<setw(3)<<"player3["<<i<<"]zhang:"<<last_all_cards[i]<<endl;
				i++;
				
			}
		}else{
			// 加入三张公共牌
			last_all_cards.push_back(other_card_vc[other_card]);
			other_card++;
			cout<<setw(3)<<"common["<<i<<"]zhang:"<<last_all_cards[i]<<endl;
			i++;
		}
	}

     cout<<"last_all_cards size ="<<last_all_cards.size()<<endl;

	// 将54张牌打印出看效果
	for (int i = 53; i >= 0; i--){
		cout<<setw(3)<<last_all_cards[i];
		
	}
	cout<<endl;

	system("pause");
}


 
 


测试部分效果如下:有不明白的也可以问我,有更好的方法的可以吐槽,大家互相学习,谢谢!
[置顶] c++ 斗地主发牌程序中级(分配发牌算法)_第1张图片


你可能感兴趣的:(游戏,C++,随机算法,棋牌游戏发牌,斗地主发牌算法)