游戏规则:
游戏从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;
}
}
}
最后得到的程序截图: