Head First C#(钓鱼游戏)

游戏规则:

游戏从52张牌开始。给每个玩家发5张牌。给每个人发完之后剩下的牌称为未发完的牌(stock)。每个玩家挨个询问一个值(“你有没有7?”),如果其他人手中有牌面等于这个值得牌,就要交给这个玩家,如果所有都没有这样的牌,玩家就必须“钓鱼”,从未发完的牌里取一张牌。

 

这个游戏的最终目标是凑成套牌(book),一套牌就是有相同牌面的全部4张不同花色的牌。到游戏最后,哪个玩家拿到的套数最多,谁就是赢家。一个玩家一旦收集到一套牌,就会把它面朝上放在桌子上,这样所有其他玩家就能看到每个人都拿了哪些套牌。

 

在一个玩家把一套牌放在桌子上,他的牌可能出光。如果是这样,他必须从没发完的牌中再抽5张牌。如果剩下的牌不足5张,就把所有剩下的牌都取光。一旦所有牌都取光,游戏就结束了。然后根据谁的套数最多选出赢家。

 

对于这个计算机版钓鱼游戏,有两个计算机玩家和一个人类玩家。每一轮从人类玩家开始,他先选择手中的一张牌,这张牌会一直显示。为此,玩家要选择一张牌,并提示他要问牌了。然后两个计算机玩家也会问牌。游戏中将显示每一轮的结果。这个过程会重复,直到出现赢家。

 

这个游戏要负责所有牌的交换,还要自动取出成套的牌。一旦出现赢家,游戏就结束。这个游戏会显示赢家的名字(可能有多个赢家,因为有可能有平局)。玩家必须重启程序才能开始一个新游戏,除此以外没有别的办法。

 

根据游戏规则,抽取出4个类,扑克牌类,一组扑克牌类,玩家类,游戏规则类。类视图如下:

代码实现如下:

namespace 钓鱼
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private Game game;

        private void btnStart_Click(object sender, EventArgs e)
        {
            if (String.IsNullOrEmpty(txtName.Text))
            {
                MessageBox.Show("Please enter your name","Can't start the game yet");
                return;
            }
            game = new Game(txtName.Text, new string[] { "Joe", "Bob" }, txtProgress);
            btnStart.Enabled = false;
            txtName.Enabled = false;
            btnAsk.Enabled = true;
            UpdateForm();
        }

        private void UpdateForm()
        {
            listHand.Items.Clear();
            foreach (String cardName in game.GetPlayerCardNames())
                listHand.Items.Add(cardName);
            txtBooks.Text = game.DescribeBooks();
            txtProgress.Text += game.DescribePlayerHands();
            txtProgress.SelectionStart = txtProgress.Text.Length;
            txtProgress.ScrollToCaret();
        }

        private void btnAsk_Click(object sender, EventArgs e)
        {          
            if (listHand.SelectedIndex < 0)
            {
                MessageBox.Show("Please select a card");
                return;
            }
            if (game.PlayOneRound(listHand.SelectedIndex))
            {
                txtProgress.Text += "The winner is ..." + game.GetWinnerName()+"\r\n";
                txtBooks.Text = game.DescribeBooks();
                btnAsk.Enabled = false;
                btnStart.Enabled = true;
            }        
                UpdateForm();
        }
    }

    /// <summary>
    /// 牌类
    /// </summary>
    public class Card
    {
        /// <summary>
        /// 花色
        /// </summary>
        public enum Suits
        {
            黑桃 , 梅花, 红桃, 方块
        }

        /// <summary>
        /// 数值
        /// </summary>
        public enum Values
        { Ace = 1, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King }

        public Suits suit;
        public Values value;

        public Card(Suits suit, Values value)
        {
            this.suit = suit;
            this.value = value;
        }

        public string Name
        {
            get { return suit.ToString() + value.ToString(); }
        }

        /// <summary>
        /// 将值变为复数形式
        /// </summary>     
        public static string Plural(Card.Values value)
        {
            if (value == Values.Six)
                return "sixex";
            else
                return value.ToString() + "s";
        }
    }

    /// <summary>
    /// 一组牌
    /// </summary>
    public class Deck
    {
        private List<Card> cards;
        private Random random = new Random();

        /// <summary>
        /// 获得一副52张新牌
        /// </summary>
        public Deck()
        {
            cards = new List<Card>();
            for (int suit = 0; suit < 4; suit++)
                for (int value = 1; value < 14; value++)
                    cards.Add(new Card((Card.Suits)suit,(Card.Values)value));
        }

        public Deck(Card[] initialCards)
        {
            cards = new List<Card>(initialCards);
        }

        public int Count { get { return cards.Count; } }

        /// <summary>
        /// 向牌组里添加新牌
        /// </summary>
        public void Add(Card cardToAdd)
        {
            cards.Add(cardToAdd);
        }

        /// <summary>
        /// 返回指定索引牌,并删除
        /// </summary>
        /// <param name="index"></param>
        public Card Deal(int index)
        {
            Card CardToDeal = cards[index];
            cards.RemoveAt(index);
            return CardToDeal;
        }

        /// <summary>
        /// 返回指定索引牌
        /// </summary>
        public Card Peek(int cardNumber)
        {
            return cards[cardNumber];
        }

        /// <summary>
        /// 重载,没有传入参数就从最上面出牌
        /// </summary>
        public Card Deal()
        {
            return Deal(0);
        }

        /// <summary>
        /// 洗牌
        /// </summary>
        public void Shuffle()
        {
            List<Card> NewCards = new List<Card>();
            while (cards.Count > 0)
            {
                int CardToMove = random.Next(cards.Count);
                NewCards.Add(cards[CardToMove]);
                cards.RemoveAt(CardToMove);
            }
            cards = NewCards;
        }

        /// <summary>
        /// 获得牌组中牌的名字
        /// </summary>
        /// <returns></returns>
        public string[] GetCardNames()
        {
          string[] CardNames=new string[cards.Count];
          for (int i = 0; i < cards.Count; i++)
              CardNames[i] = cards[i].Name;
          return CardNames;
        }

        /// <summary>
        /// 根据花色排序
        /// </summary>
        public void Sort()
        {
            cards.Sort(new CardComparer_bySuit());
        }

        /// <summary>
        /// 根据值排序
        /// </summary>
        public void SortByValue()
        {
            cards.Sort(new CardComparer_byValue());
        }
      
        /// <summary>
        /// 拿出相同的牌并删除
        /// </summary>
        public Deck PullOutValues(Card.Values value)
        {
            Deck deckToReturn = new Deck(new Card[] {});
            for (int i = cards.Count - 1; i >= 0; i--)
                if (cards[i].value == value)
                    deckToReturn.Add(Deal(i));
            return deckToReturn;
        }

        /// <summary>
        /// 检查是否有套牌
        /// </summary>
        public bool HasBook(Card.Values value)
        {
            int NumberOfCards = 0;
            foreach (Card card in cards)
                if (card.value == value)
                    NumberOfCards++;
            if (NumberOfCards == 4)
                return true;
            else
                return false;
        }
       
    }

     class CardComparer_byValue : IComparer<Card>
    {
        public int Compare(Card x, Card y)
        {
            if (x.value < y.value)
            { return -1; }
            if (x.value > y.value)
            { return 1; }
            if (x.suit < y.suit)
            { return -1; }
            if (x.suit > y.suit)
            { return 1; }
            return 0;
        }
    }

     class CardComparer_bySuit : IComparer<Card>
     {
         public int Compare(Card x, Card y)
         {
             if (x.suit < y.suit)
             { return -1; }
             if (x.suit > y.suit)
             { return 1; }
             if (x.value < y.value)
             { return -1; }
             if (x.value > y.value)
             { return 1; }            
             return 0;
         }
     }

     public class Player
    {
        private string name;
        public string Name { get { return name; } }
        private Random random=new Random ();
        private Deck cards;
        private TextBox textBoxOnForm;
        public int CardCount {get {return cards.Count;}}

        public string[] GetCardNames(){return cards.GetCardNames();}

        public Card Peek(int cardNumber){return cards.Peek(cardNumber);}
        
        /// <summary>
        /// 拿牌
        /// </summary>
        public void TakeCard(Card card) { cards.Add(card); }
        /// <summary>
        /// 手里牌排序
        /// </summary>
        public void SortHand(){cards.SortByValue();}

        public Player(string name,TextBox textBoxOnForm)
        {
            this.name = name;
            this.textBoxOnForm = textBoxOnForm;
            this.cards = new Deck(new Card[]{});
            textBoxOnForm.Text += name + " has just joined the game\r\n";
        }

        /// <summary>
        /// 取出牌里的套牌
        /// </summary> 
        public List<Card.Values> PullOutBooks()
        {
            List<Card.Values> Books = new List<Card.Values>();
            for (int i = 1; i < 14; i++)
            {
                Card.Values value = (Card.Values)i;         
                if(cards.HasBook(value))
                { 
                    Books.Add(value);
                    for (int card = cards.Count - 1; card >= 0; card--)
                        if (cards.Peek(card).value == value)
                        { cards.Deal(card); }
                }
            }
            return Books;
        }

        public Card.Values GetRandomValue()
        {
            Card randomCard = cards.Peek(random.Next(cards.Count));
            return randomCard.value;
        }

        /// <summary>
        /// 得到相同的点数的牌
        /// </summary>
        public Deck DoYouHaveAny(Card.Values value)
        {
            Deck cardsIHave = cards.PullOutValues(value);
            textBoxOnForm.Text += Name + " has " + cardsIHave.Count + " " + Card.Plural(value) + "\r\n";
            return cardsIHave;
        }
        /// <summary>
        /// 计算机要牌
        /// </summary>
        public void AskForACard(List<Player> players, int myIndex, Deck stock)
        {
            Card.Values randomValue = GetRandomValue();
            AskForACard(players,myIndex,stock,randomValue);
        }

        /// <summary>
        /// 要牌
        /// </summary>      
        public void AskForACard(List<Player> players, int myIndex, Deck stock, Card.Values value)
        {
            textBoxOnForm.Text += Name + " Asks if anyone has a " + value + "\r\n";
            int totalCardsGive = 0;
            for (int i = 0; i < players.Count; i++)
            {
                if (i != myIndex)
                {
                    Player player = players[i];
                    Deck cardsGiven = player.DoYouHaveAny(value);
                    totalCardsGive = cardsGiven.Count;
                    while (cardsGiven.Count > 0)
                        cards.Add(cardsGiven.Deal());
                }
            }

            //如果要的牌没有则从地盘里摸张牌
            if (totalCardsGive == 0)
            {
                textBoxOnForm.Text += Name + " must draw from the stock.\r\n";
                cards.Add(stock.Deal());
            }
        }
    }
 
    public class Game
    {
        private List<Player> players;//一组玩家
        private Dictionary<Card.Values, Player> books;//已有套牌
        private Deck stock;//剩余牌
        private TextBox textBoxOnForm;

        public Game(string playerName, string[] opponentNames, TextBox textBoxOnForm)
        {
            textBoxOnForm.Text = "";
            this.textBoxOnForm = textBoxOnForm;
            players = new List<Player>();
            players.Add(new Player(playerName,textBoxOnForm));
            foreach (string player in opponentNames)
                players.Add(new Player(player, textBoxOnForm));
            books = new Dictionary<Card.Values, Player>();
            stock = new Deck();
            Deal();
            players[0].SortHand();
        }

        /// <summary>
        /// 洗牌发牌
        /// </summary>
        private void Deal()
        {
            stock.Shuffle();
            for (int i = 0; i < 5; i++)
                foreach (Player player in players)
                    player.TakeCard(stock.Deal());
            foreach (Player player in players)
                PullOutBooks(player);
        }

        /// <summary>
        /// 取出玩家手中的套牌
        /// </summary>
        public bool PullOutBooks(Player player)
        {
            List<Card.Values> BooksPulled = player.PullOutBooks();
            foreach (Card.Values value in BooksPulled)
                books.Add(value,player);
            if (player.CardCount == 0)
                return true;
            return false;
        }

        /// <summary>
        /// 要牌轮流一回合,返回游戏是否结束
        /// </summary>
        public bool PlayOneRound(int selectedPlayerCard)
        {
            Card.Values cardToAskFor = players[0].Peek(selectedPlayerCard).value;
            for (int i = 0; i < players.Count; i++)
            {
                if (i == 0)
                    players[0].AskForACard(players, 0, stock, cardToAskFor);
                else
                    players[i].AskForACard(players,i,stock);
                if (PullOutBooks(players[i]))
                {
                    textBoxOnForm.Text += players[i].Name + " drew a new hand\r\n";
                    //如果手里没牌,摸5张
                    for (int card = 1; card <= 5 && stock.Count > 0;card++ )
                    {
                        players[i].TakeCard(stock.Deal());                    
                    }
                    //摸完牌后检查是否有新的套牌
                    PullOutBooks(players[i]);
                }
                players[0].SortHand();
                if (stock.Count == 0)
                {
                    textBoxOnForm.Text += "The stock is out of cards.Game over!\r\n";
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 描述各玩家已有套牌
        /// </summary>
        public string DescribeBooks()
        {
            string whoHasWhichBooks = "";
            foreach (Card.Values value in books.Keys)
                whoHasWhichBooks += books[value].Name + " has a book of " + Card.Plural(value) + "\r\n";
            return whoHasWhichBooks;
        }

        /// <summary>
        /// 反馈胜利者姓名
        /// </summary>
        /// <returns></returns>
        public string GetWinnerName()
        {
            //Key存储姓名,Value存储共有几套books
            Dictionary<string, int> winners = new Dictionary<string, int>();
            foreach (Card.Values value in books.Keys)
            {
                string name = books[value].Name;
                if (winners.ContainsKey(name))
                    winners[name]++;
                else
                    winners.Add(name, 1);
            }

            int mostBooks = 0;
            foreach (string name in winners.Keys)
                if (winners[name] > mostBooks)
                    mostBooks = winners[name];
            bool tie = false;
            string winnerList = "";
            foreach(string name in winners.Keys)
                if (winners[name] == mostBooks)
                {
                    //如果已经有胜利者,产生平局
                    if (!String.IsNullOrEmpty(winnerList))
                    {
                        winnerList += " and ";
                        tie = true;
                    }
                    winnerList += name;
                }
            winnerList += " with " + mostBooks + " books";
            if (tie)
                return "A tie between " + winnerList;
            else
                return winnerList;
        }

        /// <summary>
        /// 返回牌的名字用于显示玩家手里的牌
        /// </summary>
        public string[] GetPlayerCardNames()
        {
            return players[0].GetCardNames();
        }

        /// <summary>
        /// 描述玩家手牌和剩余牌
        /// </summary>
        public string DescribePlayerHands()
        {
            string description = "";
            for (int i = 0; i < players.Count; i++)
            {
                description += players[i].Name + " has " + players[i].CardCount;
                if (players[i].CardCount == 1)
                    description += " card.\r\n";
                else
                    description += " cards.\r\n";
            }
            description += "The stock has " + stock.Count +" cards left.\r\n";
            return description;
        }
    }      
}


最后得到的程序截图:

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值