2014年4月6日 星期日

[Code Review] Team 08 - Hw05



執行檔

ppt


Form1.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 homework5
{
    public partial class Form1 : Form
    {
        private CardDeck deck = null;
        private HandCard player1 = null;
        private HandCard player2 = null;
        public Form1()
        {
            InitializeComponent();
        }
        private string ShowHandCard(HandCard h)
        {
            string StrDisplay = "";
            for (int i = 0; i < 5; i++)
            {
                StrDisplay += " " + h.hand[i].RankToStr().ToString() + h.hand[i].SuitToAscii() + " ";
            }
            return StrDisplay;
        }
        private string WriteCard(PokerCard c)
        {
            string StrDisplay;
            StrDisplay = c.RankToStr().ToString() + c.SuitToAscii() + "  ";
            return StrDisplay;
        }
        private void button2_Click(object sender, EventArgs e)
        {
            //五百萬測試按鈕
            if (deck == null) // 第一次建立牌組
            {
                deck = new CardDeck();
                deck.CreateDeck();
                deck.ResetDeck();
            }
            //九個不同的牌型
            int[] TypeCount = new int[9];
            for (int i = 0; i <= 500000; i++)
            {
                deck.Shuffle();
                for (int j = 0; j < 10; j++)
                {
                    player1 = new HandCard();
                    for (int x = 0; x < 5; x++)
                        if (!player1.Add(deck.Deal()))
                            MessageBox.Show("Error!");
                    player1.GetCardType();
                    TypeCount[player1.CardTypeNum]++;
                    player1 = null;
                }
            }
            list_500wTest.Items.Clear();
            list_500wTest.Items.Add("High Card :" + TypeCount[0].ToString());
            list_500wTest.Items.Add("機率 :" + ((double)TypeCount[0] / 5000000).ToString());
            list_500wTest.Items.Add("One Pair :" + TypeCount[1].ToString());
            list_500wTest.Items.Add("機率 :" + ((double)TypeCount[1] / 5000000).ToString());
            list_500wTest.Items.Add("Two Pair :" + TypeCount[2].ToString());
            list_500wTest.Items.Add("機率 :" + ((double)TypeCount[2] / 5000000).ToString());
            list_500wTest.Items.Add("Three of a kind :" + TypeCount[3].ToString());
            list_500wTest.Items.Add("機率 :" + ((double)TypeCount[3] / 5000000).ToString());
            list_500wTest.Items.Add("Straight :" + TypeCount[4].ToString());
            list_500wTest.Items.Add("機率 :" + ((double)TypeCount[4] / 5000000).ToString());
            list_500wTest.Items.Add("Flush :" + TypeCount[5].ToString());
            list_500wTest.Items.Add("機率 :" + ((double)TypeCount[5] / 5000000).ToString());
            list_500wTest.Items.Add("Fullhouse :" + TypeCount[6].ToString());
            list_500wTest.Items.Add("機率 :" + ((double)TypeCount[6] / 5000000).ToString());
            list_500wTest.Items.Add("Four of a Kind :" + TypeCount[7].ToString());
            list_500wTest.Items.Add("機率 :" + ((double)TypeCount[7] / 5000000).ToString());
            list_500wTest.Items.Add("Straight Flush :" + TypeCount[8].ToString());
            list_500wTest.Items.Add("機率 :" + ((double)TypeCount[8] / 5000000).ToString());
        }
        private void button3_Click(object sender, EventArgs e)
        {
            //單人發牌按鈕
            if (deck == null) // 第一次建立牌組
            {
                deck = new CardDeck();
                deck.CreateDeck();
                deck.ResetDeck();
            }
            deck.Shuffle(); // 洗牌
            player1 = new HandCard();
            for (int i = 0; i < 5; i++) //發Player1牌
                if (!player1.Add(deck.Deal()))
                    MessageBox.Show("Error!");
            player1.GetCardType(); // 判斷牌型
            //手牌顯示
            txt_Player1.Clear();
            txt_Player2.Clear();
            txt_Player1.AppendText(ShowHandCard(player1));
            //手牌牌型顯示
            txt_Player1Type.Clear();
            txt_Player2Type.Clear();
            txt_Player1Type.AppendText(player1.CardType);
        }

        private void button4_Click(object sender, EventArgs e)
        {
            //雙人對戰按鈕
            if (deck == null)
            {
                deck = new CardDeck();
                deck.CreateDeck();
                deck.ResetDeck();
            }
            deck.Shuffle();
            player1 = new HandCard();
            player2 = new HandCard();
            for (int i = 0; i < 5; i++)
                if (!player1.Add(deck.Deal()))
                    MessageBox.Show("Error!");
            for (int i = 0; i < 5; i++)
                if (!player2.Add(deck.Deal()))
                    MessageBox.Show("Error!");
            player1.GetCardType();//判斷牌型
            player2.GetCardType();
            //手牌顯示
            txt_Player1.Clear();
            txt_Player1.AppendText(ShowHandCard(player1));
            txt_Player2.Clear();
            txt_Player2.AppendText(ShowHandCard(player2));
            //手牌牌型顯示
            txt_Player1Type.Clear();
            txt_Player1Type.AppendText(player1.CardType);
            txt_Player2Type.Clear();
            txt_Player2Type.AppendText(player2.CardType);
            //手牌最大值顯示
            txt_P1MaxRank.Clear();
            txt_P1MaxRank.AppendText(player1.MaxRank.ToString());
            txt_P2MaxRank.Clear();
            txt_P2MaxRank.AppendText(player2.MaxRank.ToString());
            //勝負顯示
            txt_Combat.Clear();
            if (player1.CombatTo(player2))
                txt_Combat.AppendText("玩者一勝");
            else
                txt_Combat.AppendText("玩者二勝");

        }

    }
}

CardDeck.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace homework5
{
    class CardDeck
    {
        public PokerCard[] Cards = new PokerCard[52];
        static private int topIndex = 0;

        public void CreateDeck() //產生出52個PokerCard的物件
        {
            for (int i = 0; i < 52; i++)
            {
                Cards[i] = new PokerCard();
            }
        }
        public void ResetDeck() //牌堆回復原始狀態
        {
            for (int i = 0; i < 52; i++)
            {
                Cards[i].Rank = i % 13 + 1;
                Cards[i].Suit = i / 13 ;
            }
            topIndex = 0;
        }
        public void Shuffle() //洗牌
        {
            PokerCard ChangeCard;
            Random rand = new Random();
            int x;
            for (int i = 0; i < 52; i++)
            {
                ChangeCard = Cards[i];
                x = rand.Next(52);
                Cards[i] = Cards[x];
                Cards[x] = ChangeCard;
            }
            topIndex = 0;
        }
        public void OrderByRank()
        {
            int j = 0;
            for (int i = 0; i < 52; i++)
            {
                if (i % 4 == 0)
                    j++;
                Cards[i].Rank = j;
                Cards[i].Suit = i % 4 ;
            }
        }
        public PokerCard Deal()
        {
            if (topIndex >= 52)
                return null;
            return Cards[topIndex++]; 
        }
    }
}
HandCard.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace homework5
{
    class HandCard
    {
        public PokerCard[] hand = new PokerCard[5];
        private int amount = 0;
        private int maxRank = 0;
        private int secRank = 0;
        private int thrRank = 0;
        private string cardtype = "";
        private int cardtypenum = 0;
        private enum eCardType  {HighCard=0,OnePair,TwoPair,ThreeOfaKing,Straight,Flush,FullHouse,FourOfaKing,StraightFlush}
        public HandCard()
        {
            for (int i = 0; i < 5; i++)
            {
                hand[i] = new PokerCard();
            }
        }
        public void SortByRank()
        {
            //bubble sort
            PokerCard ChangeCard;
            for (int i = hand.GetUpperBound(0); i > 0; i--)
            {
                for (int j = 0; j < i; j++)
                {
                    if (hand[j].Rank > hand[j + 1].Rank)
                    {
                        ChangeCard = hand[j];
                        hand[j] = hand[j+1];
                        hand[j+1] = ChangeCard;
                    }
                }
            }
        }
        public void GetCardType()
        {
            //同花順(Straight Flush)n = 8
            //四條(Four of a Kind)n = 7
            //葫蘆(Fullhouse) n = 6
            //同花(Flush)n = 5
            //順子(Straight)n = 4
            //三條(Three of a kind)n = 3
            //兩對(Two Pairs)n = 2
            //一對(One Pair)n = 1
            //無對(High Card) n = 0

            SortByRank();
            if (CheckStraight() == "Stragiht" && CheckFlush() == "Flush") // 同花順 8
            {
                GetMaxRank();
                CardType = "Straight Flush";
                CardTypeNum = (int)eCardType.StraightFlush;
                return;
            }
            else if (CheckStraight() == null && CheckFlush() == "Flush") // 同花 5 
            {
                GetMaxRank();
                CardType = "Flush";
                CardTypeNum = (int)eCardType.Flush;
                return;
            }
            else if (CheckStraight() == "Stragiht" && CheckFlush() == null) // 順子 4
            {
                GetMaxRank();
                CardType = "Straight";
                CardTypeNum = (int)eCardType.Straight;
                return;
            }
            else if(CheckPair() != null)
            {
                CardType = CheckPair();
            }
            else
            {
                GetMaxRank();
                CardType = "High Card";
                CardTypeNum = (int)eCardType.HighCard;
                return;
            }
        }
        //函數內容: 檢查是否為順子
        //函數說明: 第2張是第1張 + 1 以此類推
        //須注意 A 10 J Q K 特殊例子
        public string CheckStraight()
        {
            int start = 0;
            if (hand[0].Rank == 1) // A,10,J,Q,K 特例
            {
                start = 10;
                for (int i = 0; i <= hand.GetUpperBound(0)-1; i++)
                    if (hand[i+1].Rank != start + i)
                        return null;
                return "Stragiht";
            }
            start = hand[0].Rank;
            for (int i = 0; i <= hand.GetUpperBound(0); i++)
                if (hand[i].Rank != start + i)
                    return null;
            return "Stragiht";
        }
        //函數內容: 檢查是否為同花
        //函數說明: 只要有一張不同即null 
        public string CheckFlush()
        {
            int start = hand[0].Suit;
            foreach (PokerCard card in hand)
                if (card.Suit != start)
                    return null;
            return "Flush";
        }
        //函數內容: 檢查是否為對子(包含 三條 葫蘆 鐵支)
        //函數說明: 先使用GETMAX()函數取得最長值
        //再依各情況分析
        public string CheckPair()
        {
            SortByRank();
            int sum = GetMax(); // 取得相同點數最長的數量
            // 4 張 只有鐵支
            if (sum == 4) 
            {
                CardTypeNum = (int)eCardType.FourOfaKing;
                return "Four Of a King";
            }
            // 3 張 有葫蘆 跟 三條
            // 葫蘆判斷 OOO XX 或 OO XXX 所以 1.2 與 3.4 張必相同
            // 為非則為三條
            if (sum == 3)
            {
                if (hand[0].Rank == hand[1].Rank && hand[3].Rank == hand[4].Rank)
                {   
                    CardTypeNum = (int)eCardType.FullHouse;
                    return "Full House";
                }
                else
                {
                    CardTypeNum = (int)eCardType.ThreeOfaKing;
                    return "Three Of aKing";
                }
            }
            // 2張 有 Two pair 跟 One pair
            // two pair排列組合 有 2 1 2 或 2 2 1 或 1 2 2 等情形
            // 再分別對各情形處理即可
            if (sum == 2)
            {
                if (hand[0].Rank == hand[1].Rank)
                {
                    if (hand[3].Rank == hand[4].Rank||hand[2].Rank == hand[3].Rank)
                    {
                        secRank = hand[0].Rank; // 第二組PAIR
                        thrRank = hand[2].Rank; // 雜牌
                        CardTypeNum = (int)eCardType.TwoPair;
                        return "Two Pair";
                    }
                    else // 1 1 2 3 4 情形
                    {
                        secRank = hand[4].Rank; // 單支 最後一張
                        secRank = hand[3].Rank; // 單支 倒數第二張
                        CardTypeNum = (int)eCardType.OnePair;
                        return "One Pair";
                    }
                }
                else
                {
                    if (hand[1].Rank == hand[2].Rank && hand[3].Rank == hand[4].Rank) // O XX WW 情形
                    {
                        secRank = hand[2].Rank; // 第二組PAIR
                        thrRank = hand[0].Rank; // 雜牌
                        CardTypeNum = (int)eCardType.TwoPair;
                        return "Two Pair";
                    }
                    else
                    {
                        //ONE PAIR牌剩下的三種情形 把最大 中間 第三 找到
                        if(hand[4].Rank == hand[3].Rank) //1 2 3 4 4 情形
                        {
                            secRank = hand[2].Rank;
                            thrRank = hand[1].Rank;
                        }
                        else if (hand[3].Rank == hand[2].Rank) // 1 2 3 3 4 情形
                        {
                            secRank = hand[4].Rank;
                            thrRank = hand[1].Rank;
                        }
                        else if (hand[2].Rank == hand[1].Rank) // 1 2 2 3 4 情形
                        {
                            secRank = hand[4].Rank;
                            thrRank = hand[3].Rank;
                        }
                        CardTypeNum = (int)eCardType.OnePair;
                        return "One Pair";
                    }
                }
            }
            return null;
        }
        //函數內容:取得最大相同牌數,並用maxRank紀錄最多相同牌的值
        //函數說明:
        //3 3 2 2 2 回傳 3 並記錄 2 
        //3 2 2 2 2 回傳 4 並紀錄 2
        //1 2 3 3 4 回傳 2 並記錄 3
        //1 2 3 4 5 回傳 1 
        //以此類推 
        public int GetMax() //取得最多相同牌數 
        {
            int count = 0;
            int max = 1;
            int last = 0;
            for (int j = 0; j < 5; j++)
            {
                if (last != hand[j].Rank)
                {
                    last = hand[j].Rank;
                    for (int i = j; i < 5; i++)
                    {
                        if (last == hand[i].Rank)
                            count++;
                    }
                    if (count > max)
                    {
                        max = count; // 紀錄長度
                        maxRank = last; // 紀錄點數
                    }
                }
                count = 0;
            }
            return max;
        }
        //函數內容: 一般情況下判定最大張的牌並記錄在maxRank值內 (雜牌.順子.同花.同花順)
        public void GetMaxRank()
        {
            if (hand[0].Rank == 1)
            {
                maxRank = hand[0].Rank + 13; // 若A為最大,A = 14點
                secRank = hand[4].Rank;
                thrRank = hand[3].Rank;
            }
            else
            {
                maxRank = hand[4].Rank; //最大張為 最後一張牌 (A 例外)
                secRank = hand[3].Rank;
                thrRank = hand[2].Rank;
            }
        }
        //函數內容: 增加一張手牌
        //函數說明: amount紀錄目前手牌數量,若超過傳回false
        public bool Add(PokerCard c)
        {
            if (c == null || amount == 5)
                return false;
            hand[amount] = c;
            amount++;
            return true;
        }
        //函數內容: 兩張手牌比較牌的大小
        //函數說明: 先比較牌型,牌型較大者獲勝
        //牌行相同則比較最大張牌,若相同則在比較下一張,直到第三張
        public bool CombatTo(HandCard p2)
        {
            int P1CardType = CardTypeNum;
            int P2CardType = p2.CardTypeNum;
            if (P1CardType > P2CardType)
                return true;
            else if (P1CardType < P2CardType)
                return false;
            else //牌型相同 則比最大張
            {
                if (MaxRank > p2.MaxRank)
                    return true;
                else if (MaxRank < p2.MaxRank)
                    return false;
                else // 最大張相同 則比第二大張
                {
                    if (SecRank > p2.SecRank)
                        return true;
                    else if (SecRank < p2.SecRank)
                        return false;
                    else// 第二大張相同 則比第三大張 
                    {
                        if (ThrRank > p2.ThrRank)
                            return true;
                        else if (ThrRank < p2.ThrRank)
                            return false;
                    }
                }
            }
            //要是第三大張在相同算1P贏
            return true;
        }
        public string CardType
        {
            get 
            {
                if (cardtype == "")
                    GetCardType();
                return cardtype; 
            }
            set { cardtype = value; }
        }
        public int CardTypeNum
        {
            get 
            {
                if (cardtypenum == 0)
                    GetCardType();
                return cardtypenum; 
            }
            set
            {
                if (value > 8 || value < 0)
                    cardtypenum = 0;
                else
                    cardtypenum = value;
            }
        }
        public int MaxRank
        {
            get { return maxRank; }
        }
        public int SecRank
        {
            get { return secRank; }
        }
        public int ThrRank
        {
            get { return thrRank; }
        }

    }
}

PokerCard.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace homework5
{
    class PokerCard
    {
        public int Suit;  //花色
        public int Rank;  //點數
        public string RankToStr()//將點數轉為字串
        {
            switch (Rank)
            {
                case 1:
                    return "A";
                case 11:
                    return "J";
                case 12:
                    return "Q";
                case 13:
                    return "K";
                default:
                    return Rank.ToString();
            }
        }
        public char SuitToAscii()  //將花色轉為 Ascii 字元碼
        {
            char disp = ' ';
            switch (Suit)
            {
                case 0:
                    disp = '\u2660';
                    break;
                case 1:
                    disp = '\u2665';
                    break;
                case 2:
                    disp = '\u2666';
                    break;
                case 3:
                    disp = '\u2663';
                    break;
            }
            return disp;
        }
    }
}

1 則留言:

  1. Form1的按鍵名稱沒有更改成有意義的名子,當程式較大時容易造成混淆。

    by 第一組

    回覆刪除