1. 程式人生 > >炸金花-模擬輸贏概率計算程式01

炸金花-模擬輸贏概率計算程式01

之前講到過用程式模擬炸金花這個過程,然後統計各種牌面的情況。最終通過大量的資料模擬,然後得到使用者輸贏的可能性。

由於前兩天是用java寫的,在控制檯裡面執行出來的。感覺不太過癮,逼格不搞,湊巧今天家裡停電了,百無聊賴之際打開了VS。

幾個月沒怎麼碰VS的了,用C#寫程式都有點生疏了。和java裡面還是有些不同的。

上圖說話:

      

控制檯裡面的,基本沒啥毛病的。

燃鵝寫的winform程式裡面還有個大bug,模擬洗牌的那個過程好像有點毛病,陣列的值並沒有被打亂。在java裡好好的,到C#裡怎麼有問題了的呢

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using CCWin;

namespace 炸金花_概率計算
{
    public partial class Form1 : Skin_Color
    {
        public Form1()
        {
            InitializeComponent();
        }
        static string[] DZ = new string[] { "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K" };
        static string[] HS = new string[] { "紅心", "黑桃", "梅花", "方塊" };
        public string[] data = new string[52];
        private void Form1_Load(object sender, EventArgs e)
        {
            //初始化,一副新牌
            int k = 0;
            for (int i = 0; i < DZ.Length; i++)
            {
                for (int j = 0; j < HS.Length; j++)
                {
                    data[k] = DZ[i] + " " + HS[j];
                    //繫結到下拉列表中
                    //cb_Pai1.Items.Add(data[k]);
                    //cb_Pai2.Items.Add(data[k]);
                    //cb_Pai3.Items.Add(data[k]);
                    k++;
                }
            }
            //繫結到下拉列表中,直接判斷陣列,相比上面一個個的新增要省事不少
            cb_Pai1.Items.AddRange(data);
            cb_Pai2.Items.AddRange(data);
            cb_Pai3.Items.AddRange(data);
        }

        private void But_Static_Click(object sender, EventArgs e)
        {
            //檢查所選的三張牌是否合法
            string cb_p1 = this.cb_Pai1.Text, cb_p2 = this.cb_Pai2.Text, cb_p3 = this.cb_Pai3.Text;
            if (cb_p1.Equals("") || cb_p2.Equals("")|| cb_p3.Equals(""))//判斷是否有底牌沒有選
            {
                MessageBox.Show("請選擇你的底牌喲!", "親,這樣不對哦", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            else if (cb_p1.Equals(cb_p2) || cb_p2.Equals(cb_p3) || cb_p3.Equals(cb_p1))//判斷選擇的底牌是否有重複的
            {
                MessageBox.Show("所選的底牌不合法,請重新選擇!", "親,這樣不對哦", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            //從陣列中剔除使用者所選的三張牌(也就是將這三張牌放到陣列的最後面),剩下的隨機組合和使用者所選的三張牌比大小
            int index1 = cb_Pai1.SelectedIndex, index2 = cb_Pai2.SelectedIndex, index3 = cb_Pai3.SelectedIndex;
            data[index1] = data[51];
            data[index2] = data[50];
            data[index3] = data[49];

            //獲取使用者手中牌的級別
            int Boos = getJB(cb_p1, cb_p2, cb_p3);

            //模擬次數,預設十萬次,當rb_Count1選中時,則模擬一萬次
            int count = 100 * 10;
            if (rb_Count1.Checked)
            {
                count = 100;
            }
            //設定進度條的最大值
            pb_jingdu.Maximum = count;
            pb_Win.Maximum = count;
            pb_Shu.Maximum = count;

            //獲取參與遊戲的人數
            int proper =int.Parse(nud_Num.Value.ToString());

            //模擬count次牌局
            for (int k = 0; k < count; k++)
            {
                getXP();//先洗牌一次

                pb_jingdu.Value++;

                bool fa = true;
                for (int i = 0; i < proper - 1; i++)
                {
                    int jibie = getJB(data[i * 3], data[i * 3 + 1], data[i * 3 + 2]);
                    if (jibie > Boos)
                    {
                        pb_Shu.Value++;
                        fa = false;
                        break;
                    }
                }
                if (fa)
                    pb_Win.Value++;
            }
        }

        /// <summary>
        /// 判斷牌的大小級別
        /// </summary>
        /// <param name="index1">第一張牌</param>
        /// <param name="index2">第二張牌</param>
        /// <param name="index3">第三張牌</param>
        /// <returns>級別大小說明:0-->散牌,1-->對子,2-->順子,3-->金花,4-->同花順,5-->三條</returns>
        private int getJB(string cb_p1, string cb_p2, string cb_p3)
        {
            //分割牌,hs為花色,ds為點數
            string[] str1 = cb_p1.Split(' ');
            string[] str2 = cb_p2.Split(' ');
            string[] str3 = cb_p3.Split(' ');

            //點數,用於對子,順子的比較
            string ds1 = str1[0];
            string ds2 = str2[0];
            string ds3 = str3[0];

            //花色,用於金花的比較
            string hs1 = str1[1];
            string hs2 = str2[1];
            string hs3 = str3[1];

            //對子a==b或者a==c或者b==c
            if (ds1.Equals(ds2) || ds2.Equals(ds3) || ds3.Equals(ds1))
            { 
                //三條,只有先是對子,才可能是三條的,a==b,a==c
                if (ds1.Equals(ds2) && ds1.Equals(ds3))
                {
                    return 5;//三條,返回級別5
                }
                else
                {
                    return 1;//對子,返回級別2
                }
            }else if(BoolShunzi(ds1,ds2,ds3))//判斷是否為順子,需將AJQK轉換成數字,然後再排序判斷
            {
                //判斷是否為,同花順,花色要是一樣的
                if (hs1.Equals(hs2) && hs1.Equals(hs3))
                {
                    return 4;//同花順,返回級別4
                }
                else
                {
                    return 2;//普通順子,返回級別2
                }
            }else if (hs1.Equals(hs2) && hs1.Equals(hs3))//判斷是否為金花,即花色都一樣
            {
                return 3;//金花,返回級別3
            }
            else
            {
                return 0; //排除以上所有情況,剩下的就只有散牌嘍
            }
        }

        /// <summary>
        /// 判斷是否為順子
        /// </summary>
        /// <param name="ds1"></param>
        /// <param name="ds2"></param>
        /// <param name="ds3"></param>
        /// <returns></returns>
        private bool BoolShunzi(string ds1, string ds2, string ds3)
        {
            int[] arr = new int[3];
            string[] shunzi = new string[] { ds1, ds2, ds3 };
            //將AJQK轉換成數子
            for (int i = 0; i < shunzi.Length; i++)
            {
                try
                {
                    arr[i] = int.Parse(shunzi[i]);
                }
                catch (Exception e)
                {
                    if (shunzi[i].Equals("A"))
                        arr[i] = 1;
                    else if (shunzi[i].Equals("J"))
                        arr[i] = 11;
                    else if (shunzi[i].Equals("Q"))
                        arr[i] = 12;
                    else
                        arr[i] = 13;
                }
            }
            //排序
            for (int i = 0; i < arr.Length; i++)
            {
                for (int j = 0; j < arr.Length; j++)
                {
                    if (arr[i] > arr[j])
                    {
                        int t = arr[i];
                        arr[i] = arr[j];
                        arr[j] = t;
                    }
                }
            }
            //判斷
            if (arr[0] - arr[1] == 1 && arr[1] - arr[2] == 1)
            {
                return true;
            }
            else if (arr[0] == 13 && arr[1] == 12 && arr[2] == 1)//QKA{
                return true;
            else
                return false;
        }

        /// <summary>
        /// 洗牌,隨機交換兩次牌,次數100就可以模擬洗牌的過程
        /// </summary>
        private  void getXP()
        {
            for (int i = 0; i < 200; i++)
            {
                //兩個隨機數,然後交換牌的順序
                Random r = new Random();
                int r1 = r.Next(0, 49);
                int r2 = r.Next(0, 49);
                string temp = data[r1];
                data[r1] = data[r2];
                data[r2] = temp;
            }
        }
    }
}

PS:半下午的時間,第一次寫這麼多的註釋,調理還算清晰,演算法也還算簡潔,介面也還湊合。還有一個地方解決下就好了!!操,突然家裡斷網了。還讓不讓人發表了