麻將胡牌算法——C#

這裏只介紹普通的麻將胡牌算法,也就是7個對子或者 1個對子+3*N; N = 三個順子或者三個一樣的 ,其中字牌(東南西北中發白)不能算順子。

首先對於每張牌 它有牌的的數字 1-9,牌的種類 (萬條筒以及字)

所以先封裝一個牌的包裝類。如果要和服務器交互的話就應該給這個類序列化 即加上System.Serializable,然後再轉Json格式,這裏只做胡牌的基本判斷。

 public class Card
    {
        private int number;

        public int Number
        {
            get { return number; }
            set { number = value; }
        }
        private int type;

        public int Type
        {
            get { return type; }
            set { type = value; }
        }

        public Card(int n, int t)
        {

            number = n;
            type = t;
        }
    }

首先對於一副牌應該先判斷是否滿足七對。不滿足則向下判斷。對於手牌會創建一個交錯數組來保管。即

int[][] handcards = new int[4][] { new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } };

每個數組的第一位(handcards[i][0])用來保存當前類型牌的總數。

對應每種類型首先分爲是否包含一個對子或者不包含對子。

所以對於四種類型應該是隻有一種包含一個對子其他不包含對子。

代碼如下:

//type爲0,1,2,3則爲萬條筒字
    class Program
    {

        public void asd(){}
        static void Main(string[] args)
        {
            Card c1 = new Card(1, 1);
            Card c2 = new Card(1, 1);
            Card c3 = new Card(2, 1);
            Card c4 = new Card(2, 1);
            Card c5 = new Card(2, 1);
            Card c6 = new Card(4, 1);
            Card c7 = new Card(4, 1);
            Card c8 = new Card(4, 1);
            Card c9 = new Card(4, 3);
            Card c10 = new Card(5, 3);
            Card c11 = new Card(6, 3);
            Card c12 = new Card(6, 1);
            Card c13 = new Card(6, 1);
            Card c14 = new Card(6, 1);
            Card[] cs = { c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14 };
            Console.WriteLine(isHu(cs));
        }

        public static bool isHu(Card[] cards)
        {
            int countCards = cards.Length;
            //判斷是否是七小對
            if (countCards == 14)
            {
                int count = 0;
                for (int i = 0; i < cards.Length; i += 2)
                {
                    if (cards[i].Number == cards[i + 1].Number)
                    {
                        count++;
                    }
                    else
                    {
                        break;
                    }
                }
                if (count == 7)
                {
                    return true;
                }
            }

            int[][] handcards = new int[4][] { new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } };
            for (int i = 0; i < cards.Length; i++)
            {
                //type爲0,1,2,3則爲萬條筒字。   [type = 0,1,2,3 ,  0]代表每種牌型的總數量
                switch (cards[i].Type)
                {
                    case 0: handcards[0][cards[i].Number]++;
                        handcards[0][0]++;
                        break;
                    case 1: handcards[1][cards[i].Number]++;
                        handcards[1][0]++;
                        break;
                    case 2: handcards[2][cards[i].Number]++;
                        handcards[2][0]++;
                        break;
                    case 3: handcards[3][cards[i].Number]++;
                        handcards[3][0]++;
                        break;
                }
            }
            
            bool isJiang = false;   //判斷是否有對子
            int jiangNumber = -1;
            for (int i = 0; i < handcards.GetLength(0); i++)
            {
                if (handcards[i][0] % 3 == 2)
                {
                    if (isJiang)
                    {
                        return false;
                    }
                    isJiang = true;
                    jiangNumber = i;
                }
                //因爲對應四種牌型只能有一種且僅包含一個對子
            }
            //先求沒有將牌的情況判斷其是不是都是由刻子或者砍組成
            for (int i = 0; i < handcards.GetLength(0); i++)
            {
                if (i != jiangNumber)
                {
                    if (!(IsKanOrShun(handcards[i], i == 3)))
                    {
                        return false;
                    }
                }
            }
            bool success = false;
            //有將牌的情況下
            for (int i = 1; i <= 9; i++)
            {
                if (handcards[jiangNumber][i] >= 2)
                {
                    handcards[jiangNumber][i] -= 2;
                    handcards[jiangNumber][0] -= 2;
                    if (IsKanOrShun(handcards[jiangNumber], jiangNumber == 3))
                    {
                        success = true;
                        break;
                    }
                    else
                    {
                        handcards[jiangNumber][i] += 2;
                        handcards[jiangNumber][0] += 2;
                    }
                }
            }
            return success;
        }

        //判斷是否滿足牌組爲順子或砍組成
        public static bool IsKanOrShun(int[] arr, bool isZi)
        {
            if (arr[0] == 0)
            {
                return true;
            }

            int index = -1;
            for (int i = 1; i < arr.Length; i++)
            {
                if (arr[i] > 0)
                {
                    index = i;
                    break;
                }
            }
            bool result;
            //是否滿足全是砍
            if (arr[index] >= 3)
            {
                arr[index] -= 3;
                arr[0] -= 3;
                result = IsKanOrShun(arr, isZi);
                arr[index] += 3;
                arr[0] += 3;
                return result;
            }
            //是否滿足爲順子
            if (!isZi)
            {
                if (index < 8 && arr[index + 1] >= 1 && arr[index + 2] >= 1)
                {
                    arr[index] -= 1;
                    arr[index + 1] -= 1;
                    arr[index + 2] -= 1;
                    arr[0] -= 3;
                    result = IsKanOrShun(arr, isZi);
                    arr[index] += 1;
                    arr[index + 1] += 1;
                    arr[index + 2] += 1;
                    arr[0] += 3;
                    return result;
                }
            }

            return false;
        }
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章