2014年4月4日 星期五

[Code Review] Team 01 - Hw05

執行檔
Form1.cs
public partial class Form1 : Form
    {
        CardDeck Deck = new CardDeck();
        HandCardType[] Players = new HandCardType[5];
        HandCardType TestPlayer;
        double[] TypeTimes = new double[9];
        public Form1()
        {
            InitializeComponent();
        }
        private void Btn_Confirm_Click(object sender, EventArgs e)
        {
            Deck.Shuffle();
            switch (Cbox_Cards.SelectedIndex)
            {
                case 0:
                    if (Players[0] == null)
                        Players[0] = new HandCardType("Player1");
                    HandCardType.PlayerNum = 1;
                    Players[0].LicensingCard(Deck);
                    Players[0].Sort();

                    MessageBox.Show( HandCardType.ShowDeck(Players));
                    break;
                case 1:
                    if (Players[0] == null)
                    {
                        Players[0] = new HandCardType("Player1");
                        Players[1] = new HandCardType("Player2");
                    }
                    if (Players[1] == 1)
                        Players[1] = new HandCardType("Player2");
                    HandCardType.PlayerNum = 2;
                    Players[0].LicensingCard(Deck);
                    Players[0].Sort();
                    Players[1].LicensingCard(Deck);
                    Players[1].Sort();
                    MessageBox.Show(HandCardType.ShowDeck(Players)+"Winner is "+Winner());
                    break;
                case 2:
                    string Display = "";
                    if (Players == null)
                    {
                        Players = new HandCardType[1];
                        Players[0] = new HandCardType("Player1");
                    }
                    for (int i = 0; i < 9; i++)
                    {
                        TypeTimes[i] = 0;
                    }

                    for (int i = 0; i < 5000000; i++)
                    {
                        for (int j = 0; j < 10; j++)
                        {
                            Players[0].LicensingCard(Deck);
                            Players[0].Sort();
                            Players[0].Check();
                            TypeTimes[Players[0].TypeWeight]++;
                        }
                        Deck.Shuffle();
                    }
                    for (int i = 0; i < 9; i++)
                    {
                        Display+=HandCardType.Type[i]+" 機率為 "+(TypeTimes[i]/50000000).ToString()+"\n";
                    }
                    MessageBox.Show(Display);
                        break;
                default:
                    break;
            }
        }

        private void btn_test_Click(object sender, EventArgs e)//測試用
        {
            HandCardType.PlayerNum = 1;
            string TestDisplay = "";
            if (TestPlayer == null)
            {
                TestPlayer = new HandCardType("Test");
                for (int i = 0; i < 5; i++)
                {
                    TestPlayer.handcard[i] = new PokerCardUseUnitCode();
                }
            }
            TestPlayer.handcard[0].Rank = 13;
            TestPlayer.handcard[0].Suit = 5;
            TestPlayer.handcard[1].Rank = 11;
            TestPlayer.handcard[1].Suit = 6;
            TestPlayer.handcard[2].Rank = 1;
            TestPlayer.handcard[2].Suit = 4;
            TestPlayer.handcard[3].Rank = 10;
            TestPlayer.handcard[3].Suit = 3;
            TestPlayer.handcard[4].Rank = 11;
            TestPlayer.handcard[4].Suit = 3;
            TestPlayer.Sort();
            for (int i = 0; i < 5; i++)
            {
                TestDisplay += TestPlayer.handcard[i].RankToStr() + TestPlayer.handcard[i].SuitToUnicode() + "  ";
            }
            TestDisplay += TestPlayer.Check();
            if (TestPlayer.RankWeight == 1)
                TestPlayer.RankWeight = 14;
            TestPla
yer.AllWeight = TestPlayer.TypeWeight * 1000 + TestPlayer.RankWeight * 10 + TestPlayer.SuitWeight; TestDisplay += TestPlayer.AllWeight.ToString(); MessageBox.Show(TestDisplay); } public string Winner() { int index = 0; for (int i = 0; i < Players.Length; i++) { if (Players[i].RankWeight == 1) Players[i].RankWeight = 14; Players[i].AllWeight = Players[i].TypeWeight * 1000 + Players[i].RankWeight * 10 + Players[i].SuitWeight; if (Players[i].AllWeight > Players[index].AllWeight) index = i; } return Players[index].name; } }
HandCardType.cs
class HandCardType
    {
        public PokerCardUseUnitCode[] handcard = new PokerCardUseUnitCode[5];
        public static int PlayerNum = 0;
        public string name = "";
        public int TypeWeight = 0;
        public int RankWeight = 0;
        public int SuitWeight = 0;
        public int AllWeight = 0;

        public HandCardType(string name)
        {
            this.name = name;
        }
        public static string[] Type = { "Zilch", "One Pair", "Two Pairs", "Three of a kind", "Straight", "Flush", "Fullhouse", "Four of a Kind", "Straight Flush" };
        public void LicensingCard(CardDeck Deck)
        {
            TypeWeight = 0;
            RankWeight = 0;
            SuitWeight = 0;
            AllWeight = 0;
            for (int i = 0; i < 5; i++)
            {
                handcard[i] = Deck.Cards[Deck.Topindex];
                Deck.Topindex++;
            }
        }
        public void Sort()
        {
            PokerCardUseUnitCode temp;
            int index;
            for (int i = 4; i>0; i--)
            {
                index = i;
                for (int j = i ; j >=0; j--)
                {
                    if (handcard[j].Rank == 1)
                    {
                        index = j;
                        break;
                    }
                    if (handcard[j].Rank > handcard[index].Rank)
                        index = j;   
                }
                temp = handcard[i];
                handcard[i] = handcard[index];
                handcard[index] = temp;
            }
        }

        public string Check()//判斷牌型
        {
            switch (PairsNum())
            {
                case 0:
                    if (isStaright())
                    {
                        if (isFlush())
                            TypeWeight = 8; //同花順
                        else
                            TypeWeight = 4; //順子
                    }
                    else if (isFlush())
                    {
                        TypeWeight = 5; //同花 
                        RankWeight = handcard[4].Rank;
                        SuitWeight = handcard[4].Suit;
                    }
                    else
                    {
                        TypeWeight = 0;//無王
                        RankWeight = handcard[4].Rank;
                        SuitWeight = handcard[4].Suit;
                    }
                    break;
                case 1:
                    TypeWeight = 1;//一對
                    break;
                case 2:
                    if (isThreeOfkind())//三條
                    {
                        TypeWeight = 3;
                        RankWeight = handcard[2].Rank;
                    }
                    else
                        TypeWeight = 2;//兩對
                    break;
                case 3:
                    if (isFourOfKind())//四條
                        TypeWeight = 7;
                    else
                        TypeWeight = 6;//葫蘆
                    RankWeight = handcard[2].Rank;
                    break;
                default:
                    break;
            }
            return Type[TypeWeight];
        }

        public bool isFlush()//同花
        {
            for (int i = 1; i < handcard.Length; i++)
            {
                if (handcard[i - 1].Suit != handcard[i].Suit)
                    return false;
            }
            RankWeight = handcard[4].Rank;
            SuitWeight = handcard[4].Suit;
            return true;
        }
        public bool isStaright()//順子
        {
            if (handcard[0].Rank == 10 && handcard[1].Rank == 11 && handcard[2].Rank == 12 && handcard[3].Rank == 13 && handcard[4].Rank == 1)
            {
                RankWeight = handcard[4].Rank;
                SuitWeight = handcard[4].Suit;
                return true;
            }
            if (handcard[0].Rank == 2 && handcard[1].Rank == 3 && handcard[2].Rank == 4 && handcard[3].Rank == 5 && handcard[4].Rank == 1)
            {
                RankWeight = handcard[3].Rank;
                SuitWeight = handcard[3].Suit;
                return true;
            }
            for (int i = 1; i < handcard.Length; i++)
            {
                if ((handcard[i].Rank - handcard[i - 1].Rank) != 1)
                    return false;
            }
            RankWeight = handcard[4].Rank;
            SuitWeight = handcard[4].Suit;
            return true;
        }
        public bool isFourOfKind()//四條
        {
            if ((handcard[0].Rank == handcard[3].Rank || handcard[1].Rank == handcard[4].Rank))
            {
                RankWeight = handcard[2].Rank;
                return true;
            }
            else
                return false;
        }
        public bool isFullhouse()//葫蘆
        {
            if ((handcard[0].Rank == handcard[2].Rank && handcard[3].Rank == handcard[4].Rank) || (handcard[2].Rank == handcard[4].Rank && handcard[0].Rank == handcard[1].Rank))
            {
                RankWeight = handcard[2].Rank;
                return true;
            }
            else
                return false;
        }
        public bool isThreeOfkind()//三條
        {
            if ((handcard[0].Rank == handcard[2].Rank || handcard[1].Rank == handcard[3].Rank || handcard[2].Rank == handcard[4].Rank))
            {
                RankWeight = handcard[2].Rank;
                return true;
            }
            else
                return false;
        }
        public int PairsNum()//對子數量
        {
            int Num = 0;
            for (int i = 0; i < 4; i++)
            {
                if (handcard[i].Rank == handcard[i + 1].Rank)
                {
                    RankWeight = handcard[i].Rank;
                    SuitWeight = Math.Max(handcard[i].Suit, handcard[i+1].Suit);
                    Num++;
                }
            }
            return Num;
        }
        public static string ShowDeck(HandCardType[] player)
        {
            string Display = "";
            for (int j = 0; j < PlayerNum; j++)
            {
                Display += player[j].name + "\n";
                for (int i = 0; i < 5; i++)
                {
                    Display += player[j].handcard[i].RankToStr() + player[j].handcard[i].SuitToUnicode() + "  ";
                }
                Display += "\n";
                Display += player[j].Check() + "\n\n";
            }
            return Display;
        }
    }
CardDeck.cs
class CardDeck
    {
        public PokerCardUseUnitCode[] Cards;
        public int Topindex = 0;
        public CardDeck()
        {
            Cards = new PokerCardUseUnitCode[52];
            CreateDeck();
            ResetDeck();
        }

        public void CreateDeck() //產生出52個PokerCardUseUnitCode的物件
        {
            for (int i = 0; i < 52; i++)
            {
                Cards[i] = new PokerCardUseUnitCode();
            }
        }
        public void ResetDeck() //牌堆回復原始狀態
        {
            for (int i = 0; i < 52; i++)
            {
                Cards[i].Suit = i / 13 + 3;
                Cards[i].Rank = i % 13 + 1;
            }
        }
        public void Shuffle() //洗牌
        {
            Random rand = new Random();
            PokerCardUseUnitCode temp;
            int T;
            for (int i = 0; i < 52; i++)
            {
                T = rand.Next(52);
                temp = Cards[i];
                Cards[i] = Cards[T];
                Cards[T] = temp;
            }
            Topindex = 0;
        }
        public void ResetDeckwithRank()
        {
            for (int i = 0; i < 52; i++)
            {
                Cards[i].Suit = i % 4 + 3;
                Cards[i].Rank = i /4  + 1;
            }
        }
    }
PokerCardUseUnitCode.cs
class PokerCardUseUnitCode
    {
        public int Suit;  //花色
        public int Rank;  //點數
        public string RankToStr()  //將點數轉為字串
        {
            string RankString;
            switch (Rank)
            {
                case 1:
                    RankString = "A";
                    break;
                case 2:
                case 3:
                case 4:
                case 5:
                case 6:
                case 7:
                case 8:
                case 9:
                case 10:
                    RankString = Rank.ToString();
                    break;
                case 11:
                    RankString = "J";
                    break;
                case 12:
                    RankString = "Q";
                    break;
                case 13:
                    RankString = "K";
                    break;
                default:
                    RankString = "error";
                    break;
            }
            return RankString;
        }
        public string SuitToUnicode() //將花色轉為 UnitCode 字元碼
        {
            string[] SuitUnitcode = new string[4] { "\u2663", "\u2666", "\u2665", "\u2660" }; //梅花 方塊 紅心 黑桃
            return SuitUnitcode[Suit - 3];
        }
    }
投影片

3 則留言:

  1. 1. Form1看起來簡單乾淨,而且各項目都寫得蠻清楚。
    2. Form1的Winner()中,AllWeight的概念很有意思,可以省去了許多巢狀判斷。不過畢竟AllWeight與TypeWeight、RankWeight、SuitWeight相關,因此寫成HandCardType的方法會更佳。
    public int AllWeight()
    {
     return PTypeWeight * 1000 + RankWeight * 10 + SuitWeight;
    }
    3. 判斷RankWeight、SuitWeight的方式還不錯。

    回覆刪除
  2. [第六組]
    Form1.cs - 26行 if (Players[0] == null)
    這邊為什麼只判斷Player[0]之後就可以new兩個Player?
    然後再 31行 if (Players[1] == 1)
    反而這樣就new出Player[1]? 會不會是你們打錯?
    不知道你們是不是這樣想:"先檢查P0,不存在就把P0,P1一起new出來;如果P0存在,那就檢查P1,P1若不存在,那就只要new出P1即可".如果是這樣,建議你們用
    if(Players[0] == null)...else if(Players[1] == null)...
    這樣在第一個if把P0,P1 new出來後,就不必再檢查一次P1.

    HandCardType.cs
    11行 public HandCardType(string name)
    這個建構子只有把外部傳進的name指派到本身的name.
    如果是我的話,我會把它改成傳進int,然後這樣寫
    public HandCardType(int PlayerNum)
    {
    name = "Player" + Convert.ToSrting(PlayerNum);
    }
    這樣要宣告多個Player時,比較容易用for迴圈宣告.(原本的寫法還是可以,只是在form1.cs那邊就不太好寫.)
    另外,因為這個參數與name有關,思考一下如何屬性去處理或許更好.

    一副手牌最好就當作一個物件,這樣HandCardType這個類別內的ShowDeck就不必一次處理多副手牌.
    要顯示出多副手牌的話,只需要在Form1.cs將手牌名稱改成陣列:Player[].之後使用for迴圈配合Player[i]分批印出多副手牌應該會比較好.

    回覆刪除
    回覆
    1. Players[1] 的部分的確是打錯,你提出的方式確實比較好。

      name的部分,當時是想說玩家可以輸入各式各樣的名稱所以才這樣寫,類似玩遊戲的感覺
      ShowDeck也是因為遊戲中玩家要攤牌應該要一起攤,所以才採用這樣的寫法。
      這2部分只是個人愛玩,所以才用玩遊戲的想法寫,我也了解並不是這樣寫真的比較好。

      刪除