C#德州扑克梭哈游戏(2):牌型与点数比较

接上一篇:

https://blog.csdn.net/ylq1045/article/details/157128226

新建玩家类Player

Player.cs源程序如下:

cs 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FiveCardStud
{
	/// <summary>
	/// 玩家:德州扑克玩家,最多拥有 5张牌.有五张牌时进行结算
	/// </summary>
	public class Player
	{
		public Player(string playerName, bool isDealer = false)
		{
			this.PlayerName = playerName;
			this.IsDealer = isDealer;
			this.ListCard = new List<string>();
		}
		/// <summary>
		/// 玩家名称
		/// </summary>
		public string PlayerName { get; set; }
		/// <summary>
		/// 是否庄家,True为庄家,False为玩家
		/// </summary>
		public bool IsDealer { get; set; }
		/// <summary>
		/// 手上持有的牌
		/// </summary>
		public List<string> ListCard { get; set; }
		public string IpAndPort { get; set; }
		/// <summary>
		/// 玩家手上的五张牌组成的牌型,比如是【顺子Straight】
		/// </summary>
		public CardCategory CurrentCardCategory
		{
			get
			{
				return CommonUtil.GetCurrentCategory(this.ListCard.ToArray());
			}
		}

		/// <summary>
		/// 按照点数,对五张扑克牌进行排序【倒序Descending】,如果点数一致,就按照黑桃♠>红心♥>梅花♣>方块♦ 排序
		/// </summary>
		public void Sort() 
		{
			//按照点数,对五张扑克牌进行排序【倒序Descending】,如果点数一致,就按照黑桃♠>红心♥>梅花♣>方块♦ 排序
			ListCard.Sort((x, y) =>
			{
				int offset = CommonUtil.Dict[y] - CommonUtil.Dict[x];
				if (offset == 0)
				{
					//如果点数一致,就按照 黑桃♠>红心♥>梅花♣>方块♦
					SuitCategory suitX = CommonUtil.GetSuitCategory(x);
					SuitCategory suitY = CommonUtil.GetSuitCategory(y);
					return (int)suitX - (int)suitY;
				}
				return offset;
			});
		}

		/// <summary>
		/// 展示玩家牌型等基本信息
		/// </summary>
		/// <returns></returns>
		public override string ToString()
		{
			return string.Format("{0}【{1}】--手上的牌:【{2}】,当前牌型:【{3}】-【{4}】", new object[]
			{
				this.IsDealer ? "庄家" : "玩家",
				this.PlayerName,
				string.Join(",", this.ListCard),
				this.CurrentCardCategory,
				CurrentCardCategory.GetEnumDescription()
			});
		}
	}
}

新建部分类CommonUtil.Partial.cs

字典Dict:Key为扑克牌名称,Value为点数【为了方便进行点数比较,设定J的点数认为是11,Q的点数是12,K的点数为13,A的点数是14】

图片字典DictImage:Key为扑克牌名称,Value为图片文件名,全路径在 应用程序根目录下的pokerImg目录下。比如 ♠A黑桃 所对应的文件路径为 :pokerImg\ace_of_spades.png

CommonUtil.Partial.cs源程序如下:

cs 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FiveCardStud
{
    public partial class CommonUtil
	{
		/// <summary>
		/// 字典:Key为扑克牌名称,Value为点数【为了方便进行点数比较,设定J的点数认为是11,Q的点数是12,K的点数为13,A的点数是14】
		/// </summary>
		public static Dictionary<string, int> Dict = new Dictionary<string, int>
		{
			{
				"♠2黑桃",
				2
			},
			{
				"♠3黑桃",
				3
			},
			{
				"♠4黑桃",
				4
			},
			{
				"♠5黑桃",
				5
			},
			{
				"♠6黑桃",
				6
			},
			{
				"♠7黑桃",
				7
			},
			{
				"♠8黑桃",
				8
			},
			{
				"♠9黑桃",
				9
			},
			{
				"♠10黑桃",
				10
			},
			{
				"♠J黑桃",
				11
			},
			{
				"♠Q黑桃",
				12
			},
			{
				"♠K黑桃",
				13
			},
			{
				"♠A黑桃",
				14
			},
			{
				"♥2红心",
				2
			},
			{
				"♥3红心",
				3
			},
			{
				"♥4红心",
				4
			},
			{
				"♥5红心",
				5
			},
			{
				"♥6红心",
				6
			},
			{
				"♥7红心",
				7
			},
			{
				"♥8红心",
				8
			},
			{
				"♥9红心",
				9
			},
			{
				"♥10红心",
				10
			},
			{
				"♥J红心",
				11
			},
			{
				"♥Q红心",
				12
			},
			{
				"♥K红心",
				13
			},
			{
				"♥A红心",
				14
			},
			{
				"♣2梅花",
				2
			},
			{
				"♣3梅花",
				3
			},
			{
				"♣4梅花",
				4
			},
			{
				"♣5梅花",
				5
			},
			{
				"♣6梅花",
				6
			},
			{
				"♣7梅花",
				7
			},
			{
				"♣8梅花",
				8
			},
			{
				"♣9梅花",
				9
			},
			{
				"♣10梅花",
				10
			},
			{
				"♣J梅花",
				11
			},
			{
				"♣Q梅花",
				12
			},
			{
				"♣K梅花",
				13
			},
			{
				"♣A梅花",
				14
			},
			{
				"♦2方块",
				2
			},
			{
				"♦3方块",
				3
			},
			{
				"♦4方块",
				4
			},
			{
				"♦5方块",
				5
			},
			{
				"♦6方块",
				6
			},
			{
				"♦7方块",
				7
			},
			{
				"♦8方块",
				8
			},
			{
				"♦9方块",
				9
			},
			{
				"♦10方块",
				10
			},
			{
				"♦J方块",
				11
			},
			{
				"♦Q方块",
				12
			},
			{
				"♦K方块",
				13
			},
			{
				"♦A方块",
				14
			}
		};

		/// <summary>
		/// 图片字典:Key为扑克牌名称,Value为图片文件名,全路径在 应用程序根目录下的pokerImg目录下
		/// 比如 ♠A黑桃 所对应的文件路径为 :pokerImg\ace_of_spades.png
		/// </summary>
		public static Dictionary<string, string> DictImage = new Dictionary<string, string>
		{
			{
				"♠A黑桃",
				"ace_of_spades.png"
			},
			{
				"♠2黑桃",
				"2_of_spades.png"
			},
			{
				"♠3黑桃",
				"3_of_spades.png"
			},
			{
				"♠4黑桃",
				"4_of_spades.png"
			},
			{
				"♠5黑桃",
				"5_of_spades.png"
			},
			{
				"♠6黑桃",
				"6_of_spades.png"
			},
			{
				"♠7黑桃",
				"7_of_spades.png"
			},
			{
				"♠8黑桃",
				"8_of_spades.png"
			},
			{
				"♠9黑桃",
				"9_of_spades.png"
			},
			{
				"♠10黑桃",
				"10_of_spades.png"
			},
			{
				"♠J黑桃",
				"jack_of_spades.png"
			},
			{
				"♠Q黑桃",
				"queen_of_spades.png"
			},
			{
				"♠K黑桃",
				"king_of_spades.png"
			},
			{
				"♥A红心",
				"ace_of_hearts.png"
			},
			{
				"♥2红心",
				"2_of_hearts.png"
			},
			{
				"♥3红心",
				"3_of_hearts.png"
			},
			{
				"♥4红心",
				"4_of_hearts.png"
			},
			{
				"♥5红心",
				"5_of_hearts.png"
			},
			{
				"♥6红心",
				"6_of_hearts.png"
			},
			{
				"♥7红心",
				"7_of_hearts.png"
			},
			{
				"♥8红心",
				"8_of_hearts.png"
			},
			{
				"♥9红心",
				"9_of_hearts.png"
			},
			{
				"♥10红心",
				"10_of_hearts.png"
			},
			{
				"♥J红心",
				"jack_of_hearts.png"
			},
			{
				"♥Q红心",
				"queen_of_hearts.png"
			},
			{
				"♥K红心",
				"king_of_hearts.png"
			},
			{
				"♣A梅花",
				"ace_of_clubs.png"
			},
			{
				"♣2梅花",
				"2_of_clubs.png"
			},
			{
				"♣3梅花",
				"3_of_clubs.png"
			},
			{
				"♣4梅花",
				"4_of_clubs.png"
			},
			{
				"♣5梅花",
				"5_of_clubs.png"
			},
			{
				"♣6梅花",
				"6_of_clubs.png"
			},
			{
				"♣7梅花",
				"7_of_clubs.png"
			},
			{
				"♣8梅花",
				"8_of_clubs.png"
			},
			{
				"♣9梅花",
				"9_of_clubs.png"
			},
			{
				"♣10梅花",
				"10_of_clubs.png"
			},
			{
				"♣J梅花",
				"jack_of_clubs.png"
			},
			{
				"♣Q梅花",
				"queen_of_clubs.png"
			},
			{
				"♣K梅花",
				"king_of_clubs.png"
			},
			{
				"♦A方块",
				"ace_of_diamonds.png"
			},
			{
				"♦2方块",
				"2_of_diamonds.png"
			},
			{
				"♦3方块",
				"3_of_diamonds.png"
			},
			{
				"♦4方块",
				"4_of_diamonds.png"
			},
			{
				"♦5方块",
				"5_of_diamonds.png"
			},
			{
				"♦6方块",
				"6_of_diamonds.png"
			},
			{
				"♦7方块",
				"7_of_diamonds.png"
			},
			{
				"♦8方块",
				"8_of_diamonds.png"
			},
			{
				"♦9方块",
				"9_of_diamonds.png"
			},
			{
				"♦10方块",
				"10_of_diamonds.png"
			},
			{
				"♦J方块",
				"jack_of_diamonds.png"
			},
			{
				"♦Q方块",
				"queen_of_diamonds.png"
			},
			{
				"♦K方块",
				"king_of_diamonds.png"
			}
		};
	}
}

新建关键部分类CommonUtil.cs

关键方法:

public static Tuple<int, string> CompareCard(Player player1, Player player2):

两个玩家进行扑克牌大小比较【先进行牌型比较】。元组的第一个元素为1代表玩家一赢,为2代表玩家二赢

public static CardCategory GetCurrentCategory(string[] pokers):

获取玩家手中的五张牌组合而成的牌型 按照点数,对五张扑克牌进行排序【倒序Descending】,如果点数一致,就按照黑桃♠>红心♥>梅花♣>方块♦ 排序。 排序后,如果是相同点数的牌一定是相邻的

CommonUtil.cs源程序如下:

cs 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FiveCardStud
{
	public partial class CommonUtil
	{
		/// <summary>
		/// 获取玩家手中的五张牌组合而成的牌型
		/// 按照点数,对五张扑克牌进行排序【倒序Descending】,如果点数一致,就按照黑桃♠>红心♥>梅花♣>方块♦ 排序
		/// 排序后,如果是相同点数的牌一定是相邻的
		/// </summary>
		/// <param name="pokers"></param>
		/// <returns></returns>
		public static CardCategory GetCurrentCategory(string[] pokers)
		{
			if (pokers == null || pokers.Length != 5)
			{
				Console.WriteLine("德州扑克需要五张牌...");
				return CardCategory.Unknown;
			}
			//按照点数,对五张扑克牌进行排序【倒序Descending】,如果点数一致,就按照黑桃♠>红心♥>梅花♣>方块♦ 排序
			Array.Sort(pokers, (x, y) =>
			{
				int offset = Dict[y] - Dict[x];
				if (offset == 0)
				{
					//如果点数一致,就按照 黑桃♠>红心♥>梅花♣>方块♦
					SuitCategory suitX = GetSuitCategory(x);
					SuitCategory suitY = GetSuitCategory(y);
					return (int)suitX - (int)suitY;
				}
				return offset;
			});
			//对已排序的五张牌进行处理,相同点数的牌一定是相邻的
			bool isFlush = IsFlush(pokers);
			bool isStraight = IsStraight(pokers);
			bool isFourKind = IsFourKind(pokers);
			bool isFullHouse = IsFullHouse(pokers);
			bool isThreeKind = IsThreeKind(pokers);
			bool isTwoPairs = IsTwoPairs(pokers);
			bool isOnePair = IsOnePair(pokers);
			if (isFlush && isStraight)
			{
				//同花顺:同花 并且 顺子
				return CardCategory.StraightFlush;
			}
			else if (isFourKind)
			{
				return CardCategory.FourOfKind;
			}
			else if (isFullHouse)
			{
				return CardCategory.FullHouse;
			}
			else if (isFlush)
			{
				return CardCategory.Flush;
			}
			else if (isStraight)
			{
				return CardCategory.Straight;
			}
			else if (isThreeKind)
			{
				return CardCategory.ThreeOfKind;
			}
			else if (isTwoPairs)
			{
				return CardCategory.TwoPairs;
			}
			else if (isOnePair)
			{
				return CardCategory.OnePair;
			}
			return CardCategory.HighCard;
		}

		/// <summary>
		/// 玩家手上的五张牌组成的牌型
		/// </summary>
		/// <param name="player"></param>
		/// <returns></returns>
		public static CardCategory GetCurrentCategory(Player player) 
		{
			return GetCurrentCategory(player.ListCard.ToArray());
		}

		/// <summary>
		/// 玩家进行比较,然后按照牌的牌型,点数进行从大到小排序
		/// </summary>
		/// <param name="players"></param>
		public static void CompareCardAndSort(List<Player> players) 
		{
			players.Sort((x, y) => CompareCard(x, y).Item1 == 1 ? -1 : 1);
		}

		/// <summary>
		/// 两个玩家进行扑克牌大小比较【先进行牌型比较】
		/// 元组的第一个元素为1代表玩家一赢,为2代表玩家二赢
		/// </summary>
		/// <param name="player1"></param>
		/// <param name="player2"></param>
		/// <returns></returns>
		public static Tuple<int, string> CompareCard(Player player1, Player player2) 
		{
			CardCategory cardCategory1 = GetCurrentCategory(player1);
			CardCategory cardCategory2 = GetCurrentCategory(player2);
			if (cardCategory1 == CardCategory.Unknown || cardCategory2 == CardCategory.Unknown) 
			{
				throw new Exception($"玩家一或者玩家二尚未有五张牌");
			}
			string msg = $"玩家1【{player1.PlayerName}】的牌型是【{cardCategory1}】-【{cardCategory1.GetEnumDescription()}】,玩家2【{player2.PlayerName}】的牌型是【{cardCategory2}】-【{cardCategory2.GetEnumDescription()}】.";
			string win1 = $"{msg}玩家1【{player1.PlayerName}】赢";
			string win2 = $"{msg}玩家2【{player2.PlayerName}】赢";
			int compareValue = cardCategory2 - cardCategory1;//枚举相减,就类似于 整数的减法运算
			if (compareValue == 0)
			{
				//如果牌型一致,就对牌进行排序
				player1.Sort();
				player2.Sort();
                switch (cardCategory1)
                {
                    case CardCategory.StraightFlush:
					case CardCategory.Flush:
					case CardCategory.Straight:
					case CardCategory.HighCard:
						//同花顺: 比较最大的一张牌的点数,如果点数一致,就比较花色
						//同花:   比较最大的一张牌的点数,如果点数一致,就比较花色
						//顺子:   比较最大的一张牌的点数,如果点数一致,就比较花色
						//高牌:   比较最大的一张牌的点数,如果点数一致,就比较花色
						int point1 = Dict[player1.ListCard[0]];
						int point2 = Dict[player2.ListCard[0]];
						SuitCategory suit1 = GetSuitCategory(player1.ListCard[0]);
						SuitCategory suit2 = GetSuitCategory(player2.ListCard[0]);
						if (point1 == point2) 
						{
							if (suit1 - suit2 < 0)
							{
								return Tuple.Create(1, win1);
							}
							else 
							{
								return Tuple.Create(2, win2);
							}
						}
						return Tuple.Create(point1 > point2 ? 1 : 2, point1 > point2 ? win1 : win2);
					case CardCategory.FourOfKind:
						//【四条】,有ABBBB或者AAAAB,判断 炸弹的点数,第三个一定是炸弹的点数,比较点数即可
						point1 = Dict[player1.ListCard[2]];
						point2 = Dict[player2.ListCard[2]];
						return Tuple.Create(point1 > point2 ? 1 : 2, point1 > point2 ? win1 : win2); 
                    case CardCategory.FullHouse:
						//【葫芦、满堂红】,有AABBB或者 AAABB
						point1 = Dict[player1.ListCard[2]];
						point2 = Dict[player2.ListCard[2]];
						return Tuple.Create(point1 > point2 ? 1 : 2, point1 > point2 ? win1 : win2); 
                    case CardCategory.ThreeOfKind:
						//【三条】,有AAABC或者 ABBBC 或者ABCCC
						point1 = Dict[player1.ListCard[2]];
						point2 = Dict[player2.ListCard[2]];
						return Tuple.Create(point1 > point2 ? 1 : 2, point1 > point2 ? win1 : win2);
					case CardCategory.TwoPairs:
						//【两对】,先比较对子,如果两个对子的点数都一样,就比较杂牌
						return CompareTwoPairs(player1, player2, win1, win2);
                    case CardCategory.OnePair:
						//【对子】有一对,先比较对子的点数,如果点数一致,就比较杂牌
						GetIndexFromOnePair(player1, out int pairIndex1, out int highCardIndex1);
						GetIndexFromOnePair(player2, out int pairIndex2, out int highCardIndex2);
						point1 = Dict[player1.ListCard[pairIndex1]];//对子点数
						point2 = Dict[player2.ListCard[pairIndex2]];//对子点数
						int pointHigh1 = Dict[player1.ListCard[highCardIndex1]];//高牌点数
						int pointHigh2 = Dict[player2.ListCard[highCardIndex2]];//高牌点数
						suit1 = GetSuitCategory(player1.ListCard[highCardIndex1]);//高牌花色
						suit2 = GetSuitCategory(player2.ListCard[highCardIndex2]);//高牌花色
						if (point1 == point2)
						{
							if (pointHigh1 == pointHigh2)
							{
								if (suit1 - suit2 < 0)
								{
									return Tuple.Create(1, win1);
								}
								else
								{
									return Tuple.Create(2, win2);
								}
							}
							return Tuple.Create(pointHigh1 > pointHigh2 ? 1 : 2, pointHigh1 > pointHigh2 ? win1 : win2);
						}
						return Tuple.Create(point1 > point2 ? 1 : 2, point1 > point2 ? win1 : win2);
					default:
						throw new Exception($"玩家一或者玩家二尚未有五张牌");
				}
            }
			else if (compareValue < 0)
			{
				return Tuple.Create(2, win2);
			}
			else 
			{
				return Tuple.Create(1, win1);
			}
		}

		/// <summary>
		/// 两个对子进行比较:先比较较大的对子,再比较较小的对子。如果两个对子的点数都一样,就比较杂牌
		/// </summary>
		/// <param name="player1"></param>
		/// <param name="player2"></param>
		/// <returns></returns>
		private static Tuple<int, string> CompareTwoPairs(Player player1, Player player2, string win1, string win2) 
		{
			GetIndexFromTwoPairs(player1, out int pairIndexFirst1, out int pairIndexSecond1, out int highCardIndex1);
			GetIndexFromTwoPairs(player2, out int pairIndexFirst2, out int pairIndexSecond2, out int highCardIndex2);
			int pointFirst1 = Dict[player1.ListCard[pairIndexFirst1]];//大对子点数
			int pointFirst2 = Dict[player2.ListCard[pairIndexFirst2]];//大对子点数
			int pointSecond1 = Dict[player1.ListCard[pairIndexSecond1]];//小对子点数
			int pointSecond2 = Dict[player2.ListCard[pairIndexSecond2]];//小对子点数
			int pointHigh1 = Dict[player1.ListCard[highCardIndex1]];//高牌点数
			int pointHigh2 = Dict[player2.ListCard[highCardIndex2]];//高牌点数
			SuitCategory suit1 = GetSuitCategory(player1.ListCard[highCardIndex1]);//高牌花色
			SuitCategory suit2 = GetSuitCategory(player2.ListCard[highCardIndex2]);//高牌花色
			if (pointFirst1 == pointFirst2)
			{
				if (pointSecond1 == pointSecond2)
				{
					if (pointHigh1 == pointHigh2)
					{
						if (suit1 - suit2 < 0)
						{
							return Tuple.Create(1, win1);
						}
						else
						{
							return Tuple.Create(2, win2);
						}
					}
					return Tuple.Create(pointHigh1 > pointHigh2 ? 1 : 2, pointHigh1 > pointHigh2 ? win1 : win2);
				}
				return Tuple.Create(pointSecond1 > pointSecond2 ? 1 : 2, pointSecond1 > pointSecond2 ? win1 : win2);
			}
			return Tuple.Create(pointFirst1 > pointFirst2 ? 1 : 2, pointFirst1 > pointFirst2 ? win1 : win2);
		}

		/// <summary>
		/// 从两对【已排序完成】中,找出 第一个对子对应的数组索引,第二个对子对应的数组索引 以及 剩余的高牌索引
		/// </summary>
		/// <param name="player"></param>
		/// <param name="pairIndexFirst"></param>
		/// <param name="pairIndexSecond"></param>
		/// <param name="highCardIndex"></param>
		private static void GetIndexFromTwoPairs(Player player, out int pairIndexFirst, out int pairIndexSecond, out int highCardIndex)
		{
			pairIndexFirst = -1;
			pairIndexSecond = -1;
			highCardIndex = -1;
			List<int> pairIndexList = new List<int>();//所有对子的索引
			//找出第一个较大的对子 的索引
			for (int i = 0; i < 4; i++)
			{
				if (Dict[player.ListCard[i]] == Dict[player.ListCard[i + 1]])
				{
					pairIndexFirst = i;
					pairIndexList.AddRange(new int[] { pairIndexFirst, pairIndexFirst + 1 });
					break;
				}
			}
			//找出第二个对子 的索引
			for (int i = pairIndexFirst + 1; i < 4; i++)
            {
				if (Dict[player.ListCard[i]] == Dict[player.ListCard[i + 1]])
				{
					pairIndexSecond = i;
					pairIndexList.AddRange(new int[] { pairIndexSecond, pairIndexSecond + 1 });
					break;
				}
			}
			//找出高牌【杂牌】  的索引:去除两个对子的索引,剩下的就是高牌
			for (int i = 0; i < 5; i++)
			{
				if (!pairIndexList.Contains(i))
				{
					highCardIndex = i;
					break;
				}
			}
		}

		/// <summary>
		/// 从单个对子【已排序完成】中,找出 对子对应的数组索引 以及 最大的高牌索引
		/// </summary>
		/// <param name="player"></param>
		/// <param name="pairIndex"></param>
		/// <param name="highCardIndex"></param>
		private static void GetIndexFromOnePair(Player player, out int pairIndex, out int highCardIndex) 
		{
			pairIndex = -1;
			highCardIndex = -1;
			for (int i = 0; i < 4; i++)
			{
				if (Dict[player.ListCard[i]] == Dict[player.ListCard[i + 1]])
				{
					pairIndex = i;
					if (pairIndex == 0)
					{
						highCardIndex = 2;//对子 AABCD
					}
					else 
					{
						highCardIndex = 0;//ABBCD 或 ABCCD 或 ABCDD
					}
					break;
				}
			}
		}

		/// <summary>
		/// 是否同花,比如 五张牌都是 红心♥
		/// 五张牌 全都是 四种花色【黑桃♠,红心♥,梅花♣,方块♦】中的同一种
		/// </summary>
		/// <param name="pokers"></param>
		/// <returns></returns>
		public static bool IsFlush(string[] pokers)
		{
			SuitCategory suit1 = GetSuitCategory(pokers[0]);
			SuitCategory suit2 = GetSuitCategory(pokers[1]);
			SuitCategory suit3 = GetSuitCategory(pokers[2]);
			SuitCategory suit4 = GetSuitCategory(pokers[3]);
			SuitCategory suit5 = GetSuitCategory(pokers[4]);
			return suit1 == suit2 && suit2 == suit3 && suit3 == suit4 && suit4 == suit5;
		}

		/// <summary>
		/// 是否顺子,点数连续
		/// 点数:相邻的五个为顺子,比如:"Q", "J", "10", "9", "8"
		/// </summary>
		/// <param name="pokers"></param>
		/// <returns></returns>
		public static bool IsStraight(string[] pokers)
		{
			for (int i = 0; i < pokers.Length - 1; i++)
			{
				if (Dict[pokers[i]] - Dict[pokers[i + 1]] != 1)
				{
					return false;
				}
			}
			return true;
		}

		/// <summary>
		/// 是否四条 【四条】,也叫铁支,炸弹,有4张相邻的牌点数相同
		/// </summary>
		/// <param name="pokers"></param>
		/// <returns></returns>
		public static bool IsFourKind(string[] pokers)
		{
			return (Dict[pokers[0]] == Dict[pokers[1]] && Dict[pokers[1]] == Dict[pokers[2]] && Dict[pokers[2]] == Dict[pokers[3]])
				|| (Dict[pokers[1]] == Dict[pokers[2]] && Dict[pokers[2]] == Dict[pokers[3]] && Dict[pokers[3]] == Dict[pokers[4]]);
		}

		/// <summary>
		/// 是否【葫芦、满堂红】3张点数相同的牌,并且 加上一对子。
		/// 即排序后的五张牌点数为  AAA BB 或者 AA BBB
		/// </summary>
		/// <param name="pokers"></param>
		/// <returns></returns>
		public static bool IsFullHouse(string[] pokers) 
		{
			return (Dict[pokers[0]] == Dict[pokers[1]] && Dict[pokers[1]] == Dict[pokers[2]] && Dict[pokers[2]] != Dict[pokers[3]] && Dict[pokers[3]] == Dict[pokers[4]])
				|| (Dict[pokers[0]] == Dict[pokers[1]] && Dict[pokers[1]] != Dict[pokers[2]] && Dict[pokers[2]] == Dict[pokers[3]] && Dict[pokers[3]] == Dict[pokers[4]]);
		}

		/// <summary>
		/// 【三条】有3张点数相同的牌 AAABC或者 ABBBC 或者 ABCCC
		/// </summary>
		/// <param name="pokers"></param>
		/// <returns></returns>
		public static bool IsThreeKind(string[] pokers) 
		{
			return (Dict[pokers[0]] == Dict[pokers[1]] && Dict[pokers[1]] == Dict[pokers[2]] && Dict[pokers[2]] != Dict[pokers[3]] && Dict[pokers[3]] != Dict[pokers[4]])
				|| (Dict[pokers[0]] != Dict[pokers[1]] && Dict[pokers[1]] == Dict[pokers[2]] && Dict[pokers[2]] == Dict[pokers[3]] && Dict[pokers[3]] != Dict[pokers[4]])
				|| (Dict[pokers[0]] != Dict[pokers[1]] && Dict[pokers[1]] != Dict[pokers[2]] && Dict[pokers[2]] == Dict[pokers[3]] && Dict[pokers[3]] == Dict[pokers[4]]);
		}

		/// <summary>
		/// 【两对】有两对点数一样的牌,加1张杂牌。AABBC 或者 AABCC 或者 ABBCC
		/// </summary>
		/// <param name="pokers"></param>
		/// <returns></returns>
		public static bool IsTwoPairs(string[] pokers) 
		{
			return (Dict[pokers[0]] == Dict[pokers[1]] && Dict[pokers[1]] != Dict[pokers[2]] && Dict[pokers[2]] == Dict[pokers[3]] && Dict[pokers[3]] != Dict[pokers[4]])
				|| (Dict[pokers[0]] == Dict[pokers[1]] && Dict[pokers[1]] != Dict[pokers[2]] && Dict[pokers[2]] != Dict[pokers[3]] && Dict[pokers[3]] == Dict[pokers[4]])
				|| (Dict[pokers[0]] != Dict[pokers[1]] && Dict[pokers[1]] == Dict[pokers[2]] && Dict[pokers[2]] != Dict[pokers[3]] && Dict[pokers[3]] == Dict[pokers[4]]);
		}
		/// <summary>
		/// 只有一对,加3张杂牌组成。五张牌按点数分组,可以分成四组【肯定有两张牌点数一样】
		/// </summary>
		/// <param name="pokers"></param>
		/// <returns></returns>
		public static bool IsOnePair(string[] pokers)
		{
			IEnumerable<IGrouping<int, string>> groups = pokers.GroupBy(element => Dict[element]);
			if (groups.Count() == 4) 
			{
				return groups.ToList().Exists(x => x.Count() == 2);
			}
			return false;
		}

		/// <summary>
		/// 获取当前扑克牌对应的花色,【黑桃♠,红心♥,梅花♣,方块♦】中的一种
		/// </summary>
		/// <param name="poker"></param>
		/// <returns></returns>
		public static SuitCategory GetSuitCategory(string poker) 
		{
			if (poker == null || poker.Length == 0) 
			{
				throw new ArgumentException("当前扑克牌不能为空");
			}
			char suit = poker[0];
            switch (suit)
            {
				case '♠':
					return SuitCategory.Spade;
				case '♥':
					return SuitCategory.Heart;
				case '♣':
					return SuitCategory.Club;
				case '♦':
					return SuitCategory.Diamond;
				default:
                    return SuitCategory.None;
            }
        } 
	}
}

展示扑克图片的辅助类:ShowImageUtil

ShowImageUtil源程序如下:

cs 复制代码
using System;
using System.Drawing;
using System.Windows.Forms;

namespace FiveCardStud
{
	public class ShowImageUtil
	{
		/// <summary>
		/// 显示五张牌的扑克图片到面板Panel中
		/// </summary>
		/// <param name="player"></param>
		/// <param name="form"></param>
		/// <param name="pnlPoker"></param>
		public static void DisplayPokerImage(Player player, Form form, Panel pnlPoker)
		{
			if (!form.IsHandleCreated) 
			{
				return;
			}
			form.BeginInvoke(new Action(delegate ()
			{
				pnlPoker.Controls.Clear();
				int pokerCount = player.ListCard.Count;
				int rowCount = (pokerCount + 4) / 5;
				for (int i = 0; i < rowCount; i++)
				{
					if (5 * i < pokerCount)
					{
						string joker = player.ListCard[5 * i];
						AddPicture(0, 190 * i, CommonUtil.DictImage[joker], pnlPoker);
					}
					if (5 * i + 1 < pokerCount)
					{
						string joker2 = player.ListCard[5 * i + 1];
						ShowImageUtil.AddPicture(130, 190 * i, CommonUtil.DictImage[joker2], pnlPoker);
					}
					if (5 * i + 2 < pokerCount)
					{
						string joker3 = player.ListCard[5 * i + 2];
						AddPicture(260, 190 * i, CommonUtil.DictImage[joker3], pnlPoker);
					}
					if (5 * i + 3 < pokerCount)
					{
						string joker4 = player.ListCard[5 * i + 3];
						ShowImageUtil.AddPicture(390, 190 * i, CommonUtil.DictImage[joker4], pnlPoker);
					}
					if (5 * i + 4 < pokerCount)
					{
						string joker5 = player.ListCard[5 * i + 4];
						AddPicture(520, 190 * i, CommonUtil.DictImage[joker5], pnlPoker);
					}
				}
			}));
		}

		/// <summary>
		/// 增加一个图片
		/// </summary>
		/// <param name="xPoint"></param>
		/// <param name="yPoint"></param>
		/// <param name="fileName"></param>
		/// <param name="pnlPoker"></param>
		public static void AddPicture(int xPoint, int yPoint, string fileName, Panel pnlPoker)
		{
			PictureBox pb = new PictureBox();
			pb.Name = fileName;
			pb.Size = new Size(125, 182);
			pb.Location = new Point(xPoint, yPoint);
			pb.Image = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "pokerImg\\" + fileName);
			pb.SizeMode = PictureBoxSizeMode.Zoom;
			pnlPoker.Controls.Add(pb);
		}
	}
}

窗体FormFiveCardStudEx设计器如下:

文件FormFiveCardStudEx.Designer.cs

cs 复制代码
using System.Drawing;
using System.Windows.Forms;

namespace FiveCardStud
{
    partial class FormFiveCardStudEx
    {
        /// <summary>
        /// 必需的设计器变量。
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// 清理所有正在使用的资源。
        /// </summary>
        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows 窗体设计器生成的代码

        /// <summary>
        /// 设计器支持所需的方法 - 不要修改
        /// 使用代码编辑器修改此方法的内容。
        /// </summary>
        private void InitializeComponent()
        {
            this.rtxtDisplay = new System.Windows.Forms.RichTextBox();
            this.pnlPoker1 = new System.Windows.Forms.Panel();
            this.button1 = new System.Windows.Forms.Button();
            this.pnlPoker2 = new System.Windows.Forms.Panel();
            this.pnlPoker3 = new System.Windows.Forms.Panel();
            this.pnlPoker4 = new System.Windows.Forms.Panel();
            this.SuspendLayout();
            // 
            // rtxtDisplay
            // 
            this.rtxtDisplay.Location = new System.Drawing.Point(8, 6);
            this.rtxtDisplay.Name = "rtxtDisplay";
            this.rtxtDisplay.ReadOnly = true;
            this.rtxtDisplay.Size = new System.Drawing.Size(593, 815);
            this.rtxtDisplay.TabIndex = 0;
            this.rtxtDisplay.Text = "";
            // 
            // pnlPoker1
            // 
            this.pnlPoker1.Location = new System.Drawing.Point(758, 2);
            this.pnlPoker1.Name = "pnlPoker1";
            this.pnlPoker1.Size = new System.Drawing.Size(660, 195);
            this.pnlPoker1.TabIndex = 16;
            // 
            // button1
            // 
            this.button1.Font = new System.Drawing.Font("宋体", 13F);
            this.button1.Location = new System.Drawing.Point(624, 178);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(101, 35);
            this.button1.TabIndex = 17;
            this.button1.Text = "刷新";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            // 
            // pnlPoker2
            // 
            this.pnlPoker2.Location = new System.Drawing.Point(758, 210);
            this.pnlPoker2.Name = "pnlPoker2";
            this.pnlPoker2.Size = new System.Drawing.Size(660, 195);
            this.pnlPoker2.TabIndex = 17;
            // 
            // pnlPoker3
            // 
            this.pnlPoker3.Location = new System.Drawing.Point(758, 418);
            this.pnlPoker3.Name = "pnlPoker3";
            this.pnlPoker3.Size = new System.Drawing.Size(660, 195);
            this.pnlPoker3.TabIndex = 18;
            // 
            // pnlPoker4
            // 
            this.pnlPoker4.Location = new System.Drawing.Point(758, 626);
            this.pnlPoker4.Name = "pnlPoker4";
            this.pnlPoker4.Size = new System.Drawing.Size(660, 195);
            this.pnlPoker4.TabIndex = 18;
            // 
            // FormFiveCardStudEx
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(1436, 847);
            this.Controls.Add(this.pnlPoker4);
            this.Controls.Add(this.pnlPoker3);
            this.Controls.Add(this.pnlPoker2);
            this.Controls.Add(this.button1);
            this.Controls.Add(this.pnlPoker1);
            this.Controls.Add(this.rtxtDisplay);
            this.Name = "FormFiveCardStudEx";
            this.Text = "斯内科---德州扑克【梭哈】游戏";
            this.Load += new System.EventHandler(this.FormFiveCardStudEx_Load);
            this.ResumeLayout(false);

        }

        #endregion
        private RichTextBox rtxtDisplay;
        private Panel pnlPoker1;
        private Panel pnlPoker2;
        private Panel pnlPoker3;
        private Panel pnlPoker4;
        private Button button1;
    }
}

FormFiveCardStudEx测试代码如下:

文件FormFiveCardStudEx.cs

cs 复制代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace FiveCardStud
{
    public partial class FormFiveCardStudEx : Form
    {
		public FormFiveCardStudEx()
        {
            InitializeComponent();
        }
		/// <summary>
		/// 显示消息
		/// </summary>
		/// <param name="addContent"></param>
		private void DisplayContent(string addContent)
		{
			if (!IsHandleCreated) 
			{
				return;
			}
			if (InvokeRequired)
			{
				Action<string> actionUpd = new Action<string>(this.DisplayContentEx);
				actionUpd.BeginInvoke(addContent, null, null);
			}
			else
			{
				this.DisplayContentEx(addContent);
			}
		}
		public void DisplayContentEx(string addContent)
		{
			Invoke(new MethodInvoker(delegate ()
			{
				if (this.rtxtDisplay.TextLength >= 10240)
				{
					this.rtxtDisplay.Clear();
				}
				this.rtxtDisplay.AppendText(addContent + "\n");
				this.rtxtDisplay.ScrollToCaret();
			}));
		}

        private void FormFiveCardStudEx_Load(object sender, EventArgs e)
        {
			FiveCardStudUtil.Init();
			Player player1 = new Player("斯内科");
			Player player2 = new Player("富饶格");
			Player player3 = new Player("曹孟德");
			Player player4 = new Player("刘玄德");
			for (int i = 0; i < 5; i++)
            {
				FiveCardStudUtil.DealCard(player1);
				FiveCardStudUtil.DealCard(player2);
				FiveCardStudUtil.DealCard(player3);
				FiveCardStudUtil.DealCard(player4);
			}
			player1.Sort();
			player2.Sort();
			player3.Sort();
			player4.Sort();
			DisplayContent(player1.ToString());
			DisplayContent(player2.ToString());
			DisplayContent(player3.ToString());
			DisplayContent(player4.ToString());
			ShowImageUtil.DisplayPokerImage(player1, this, pnlPoker1);
			ShowImageUtil.DisplayPokerImage(player2, this, pnlPoker2);
			ShowImageUtil.DisplayPokerImage(player3, this, pnlPoker3);
			ShowImageUtil.DisplayPokerImage(player4, this, pnlPoker4);

			List<Player> players = new List<Player>() { player1, player2, player3, player4 };
			CommonUtil.CompareCardAndSort(players);
			DisplayContent($"【{players.Count}】位玩家的牌型与点数从大到小排序为:");
            for (int i = 0; i < players.Count; i++)
            {
				DisplayContent($"【{players[i].PlayerName}】,牌型为【{players[i].CurrentCardCategory}】-【{players[i].CurrentCardCategory.GetEnumDescription()}】");
			}
		}

        private void button1_Click(object sender, EventArgs e)
        {
			FormFiveCardStudEx_Load(null, null);
		}
    }
}

运行如图:

相关推荐
柒儿吖2 小时前
rudp Reliable UDP 库在 OpenHarmony 的 lycium 适配与 CRC32 测试
c++·c#·openharmony
CreasyChan2 小时前
unity C# 实现屏蔽敏感词
unity·c#·游戏引擎
光泽雨2 小时前
C#中Process类详解
microsoft·c#·交互
柒儿吖2 小时前
三方库 Boost.Regex 在 OpenHarmony 的 lycium完整实践
c++·c#·openharmony
柒儿吖3 小时前
三方库 Emoji Segmenter 在 OpenHarmony 的 lycium 适配与测试
c++·c#·openharmony
hoiii1873 小时前
基于C#实现的高性能实时MP4录屏方案
开发语言·c#
yongui478343 小时前
基于C#实现Modbus RTU通信
开发语言·c#
Pure_White_Sword3 小时前
bugku-reverse题目-游戏过关
游戏·网络安全·ctf·reverse·逆向工程