using System; using System.Drawing; using System.Collections.Generic; using System.Linq; using System.Text; namespace Gin_Rummy_Game { [Serializable] public class PlayingCard : IComparable { public static string[] suits = { "clubs", "hearts", "diamonds", "spades" }; public static string[] faces = { "ace", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "jack", "queen", "king" }; private static string[] faceFiles={"1","2","3","4","5","6","7","8","9","10","j","q","k"}; private static string CardImagesFolder="C:\\Documents and Settings\\spannm\\Desktop\\Personal Stuff\\C#\\C# Projects VS2008\\Gin Rummy\\Gin Rummy Game\\Card Images\\"; public PlayingCard(int v) { cardValue = v; } public PlayingCard(string faceVal, string suit) { int faceIndex = -1; int suitIndex = -1; for (int i = 0; i < faces.Length; i++) if (faces[i].CompareTo(faceVal) == 0) faceIndex = i; for (int i = 0; i < suits.Length; i++) if (suits[i].CompareTo(suit) == 0) suitIndex = i; cardValue = suitIndex * 13 + faceIndex; } public int CardValue { get{ return cardValue;} set { cardValue = value; } } public int CompareTo(object obj) { PlayingCard p = (PlayingCard)obj; if (p.cardValue < cardValue) return 1; else if (p.cardValue > cardValue) return -1; else return 0; } public int getSuit() { return cardValue / 13; } public int getFace() { return cardValue % 13; } public Image getImage() { int s = getSuit(); int f = getFace(); string fString=faceFiles[f]; char suitChar = suits[s][0]; string cardFile = "" + suitChar + fString+".gif"; cardFile = CardImagesFolder + cardFile; return Image.FromFile(cardFile); } public override string ToString() { string card="The " + faces[getFace()] + " of " + suits[getSuit()]; return card; } private int cardValue; } [Serializable] public class PlayingCardFromDeck // Encapsulates a playing card and the deck from where it came { public enum DeckType { DRAWDECK, DISCARDDECK }; public PlayingCardFromDeck(PlayingCard c, DeckType d) { card = c; deckType = d; } public PlayingCard Card { get { return card; } } public DeckType Deck { get { return deckType; } } private DeckType deckType; private PlayingCard card; } [Serializable] public class PlayState // Encapsulates information about a single play of a hand of gin rummy { public enum DeckType { DRAWDECK, DISCARDDECK, BOTHDECKS, NOPLAY }; public PlayState(PlayingCard c, DeckType d) { card = c; deckType = d; } public PlayingCard Card { get { return card; } } public DeckType Deck { get { return deckType; } } private PlayingCard card; private DeckType deckType; } public abstract class Player { public Player(string n) { hand = new List(); name = (string) n.Clone(); } public List Hand { get { return hand; } set { hand = value; } } public string Name { get { return name; } } public abstract PlayState playHand(DeckOfCards drawDeck, DeckOfCards discardDeck); public void upDateDecks(DeckOfCards drawDeck, DeckOfCards discardDeck, PlayState rp) { if (rp.Deck == PlayState.DeckType.NOPLAY) return; if (rp.Deck == PlayState.DeckType.BOTHDECKS) { PlayingCard drawDeckCard = drawDeck.drawCard(); discardDeck.addCard(drawDeckCard); } else { // Swap with deck's top card PlayingCard card = rp.Card; DeckOfCards deck = drawDeck; if (rp.Deck == PlayState.DeckType.DISCARDDECK) deck = discardDeck; PlayingCard topCard = deck.TopCard; PlayingCard c1 = getCard(card); swapCard(c1, topCard); deck.drawCard(); discardDeck.addCard(c1); } } public void displayHand() { hand.Sort(); Console.WriteLine(name + "'s hand is "); foreach (PlayingCard p in hand) Console.WriteLine(p.ToString()); Console.WriteLine(); } public void displayHand(List aHand) { aHand.Sort(); foreach (PlayingCard p in aHand) Console.WriteLine(p.ToString()); Console.WriteLine(); } public PlayingCard getCard(PlayingCard card) { foreach (PlayingCard c in hand) if (c.CompareTo(card) == 0) return c; return null; } public void swapCard(PlayingCard fromCard, PlayingCard toCard) { Hand.Remove(fromCard); Hand.Add(toCard); } public int handValue(List hand) { // Compute the value of the hand as the number of cards in the two largest groups. 7 equals a winning hand int value = 0; // For the current hand evaluate the max run length int startIndex; int maxRunLength = getMaxRunLength(hand, out startIndex); // For the current hand evaluate the max number of equal face values int maxFaceValue; int maxFaceCount = getMaxFaceCount(hand, out maxFaceValue); List tempHand = new List(); List tempHand1 = new List(); if ((maxRunLength == 1) && (maxFaceCount == 1)) return 0; if (maxRunLength > maxFaceCount) { value = maxRunLength; int mrl = maxRunLength; if (maxRunLength == 5) mrl = 4; // Copy all the cards not in the run to the temp hand and re-test for (int i = 0; i < 7; i++) { if ((i < startIndex) || (i >= startIndex + mrl)) tempHand.Add(hand[i]); } if (maxRunLength == 5) { value = mrl; for (int i = 0; i < 7; i++) { if ((i < (startIndex + 1)) || (i > startIndex + mrl)) tempHand1.Add(hand[i]); } } } else { value = maxFaceCount; // Copy all the cards not in max face list and re-test for (int i = 0; i < 7; i++) { int faceValue = hand[i].getFace(); if (faceValue != maxFaceValue) tempHand.Add(hand[i]); } } int value1 = value; maxRunLength = getMaxRunLength(tempHand, out startIndex); maxFaceCount = getMaxFaceCount(tempHand, out maxFaceValue); if (maxRunLength > maxFaceCount) { value += maxRunLength; if (maxRunLength == 1) value--; } else { value += maxFaceCount; if (maxFaceCount == 1) value--; } if (tempHand1.Count > 0) { int maxRunLength1 = getMaxRunLength(tempHand1, out startIndex); int maxFaceCount1 = getMaxFaceCount(tempHand1, out maxFaceValue); if (maxRunLength1 > maxFaceCount1) { value1 += maxRunLength1; if (maxRunLength1 == 1) value1--; } else { value1 += maxFaceCount1; if (maxFaceCount1 == 1) value1--; } } if (value1 > value) return value1; return value; } protected bool isRun(List h, int startIndex, int runLength) { h.Sort(); int valStart = h[startIndex].CardValue; int endIndex = startIndex + runLength - 1; if (endIndex >= h.Count) return false; else { int valEnd = h[endIndex].CardValue; int suitStart = h[startIndex].getSuit(); int suitEnd = h[endIndex].getSuit(); if (((valEnd - valStart) == runLength - 1)&&(suitStart==suitEnd)) return true; } return false; } private int getMaxFaceCount(List hand, out int maxFaceValue) { int[] faceValueHist = new int[13]; for (int i = 0; i < 13; i++) faceValueHist[i] = 0; foreach (PlayingCard p in hand) { int faceValue = p.getFace(); faceValueHist[faceValue]++; } int maxFaceCount = 0; maxFaceValue = -1; for (int i = 0; i < 13; i++) { if (faceValueHist[i] > maxFaceCount) { maxFaceCount = faceValueHist[i]; maxFaceValue = i; } } return maxFaceCount; } private int getMaxRunLength(List hand, out int startIndex) { int maxRunLength = 1; startIndex = 0; for (int r = 2; r <= 5; r++) { int i = -1; do { i++; } while ((!isRun(hand, i, r)) && (i < hand.Count - 1)); if (i < (hand.Count - 1)) { maxRunLength = r; startIndex = i; } } return maxRunLength; } protected List hand; protected String name; } public class InteractivePlayer : Player { public InteractivePlayer(string s) : base(s) {} public override PlayState playHand(DeckOfCards drawDeck, DeckOfCards discardDeck) { displayHand(); Console.WriteLine("There are " + drawDeck.Size + " card in the draw deck and " + discardDeck.Size + " in the discard deck"); PlayingCard discardDeckCard = discardDeck.TopCard; Console.WriteLine("The discard deck shows: " + discardDeckCard.ToString()); Console.WriteLine("Accept discard deck card (0) or draw new card (1): "); string s = Console.ReadLine(); if (s[0] == '0') // Accept discard deck card { PlayingCard c1 = null; PlayingCard c = null; do { Console.WriteLine("Which card do you want to swap? (face-suit)"); string faceString = Console.ReadLine(); string suitString = Console.ReadLine(); c = new PlayingCard(faceString, suitString); c1 = getCard(c); } while (c1 == null); // Swap with discard deck card PlayState returnObj = new PlayState(c,PlayState.DeckType.DISCARDDECK); return returnObj; } else if (s[0] == '1') // Draw a new card { PlayingCard drawDeckCard = drawDeck.TopCard; Console.WriteLine("You have drawn a " + drawDeckCard.ToString()); Console.WriteLine("Accept draw deck card (y/n): "); string s1 = Console.ReadLine(); if (s1[0] == 'y') // Accept drawn card { PlayingCard c1 = null; PlayingCard c = null; do { Console.WriteLine("Which card do you want to swap? (face-suit)"); string faceString = Console.ReadLine(); string suitString = Console.ReadLine(); c = new PlayingCard(faceString, suitString); c1 = getCard(c); } while (c1 == null); // Swap with draw deck card PlayState returnObj = new PlayState(c, PlayState.DeckType.DRAWDECK); return returnObj; } else if (s1[0] == 'n') { PlayState returnObj = new PlayState(null, PlayState.DeckType.BOTHDECKS); return returnObj; } } PlayState noplayObj = new PlayState(null, PlayState.DeckType.NOPLAY); return noplayObj; } } public class AutonomousPlayer : Player { public AutonomousPlayer(string s) : base(s) { } public override PlayState playHand(DeckOfCards drawDeck, DeckOfCards discardDeck) { PlayingCard discardDeckCard = discardDeck.TopCard; // Accept discard deck card or draw a new card PlayingCard card = acceptCard(discardDeckCard); if (card != null) { // Swap with discard deck card PlayingCard c1 = getCard(card); PlayState returnObj = new PlayState(c1, PlayState.DeckType.DISCARDDECK); return returnObj; } else if (card == null) // Draw a card from the draw deck { PlayingCard drawDeckCard = drawDeck.TopCard; // Choose whether to accept drawn card PlayingCard card1 = acceptCard(drawDeckCard); if (card1 != null) { // Swap with draw deck card PlayingCard c1 = getCard(card1); PlayState returnObj = new PlayState(c1, PlayState.DeckType.DRAWDECK); return returnObj; } else if (card1 == null) { PlayState returnObj = new PlayState(null,PlayState.DeckType.BOTHDECKS); return returnObj; } } PlayState noplayObj = new PlayState(null, PlayState.DeckType.NOPLAY); return noplayObj; } private PlayingCard acceptCard(PlayingCard card) { // Determines whether to accept a card. Returns the discarded card or null // Make a copy of the current hand List tempHand = new List(); foreach (PlayingCard c in hand) tempHand.Add(c); int currentValue = handValue(tempHand); // Swap each card in the hand with the input card and determine the maximum hand value int maxValue = 0; PlayingCard swappedCard = null; PlayingCard[] cardArray = new PlayingCard[7]; cardArray = tempHand.ToArray(); for (int i = 0; i < tempHand.Count; i++) { PlayingCard c = cardArray[i]; tempHand.Add(card); tempHand.Remove(c); int value = handValue(tempHand); if (value > maxValue) { maxValue = value; swappedCard = c; } tempHand.Add(c); tempHand.Remove(card); } if (maxValue > currentValue) return swappedCard; else return null; } } public class DeckOfCards { private static int shuffleIterations=50000; public DeckOfCards(bool empty) { deck=new List(); if (!empty) for (int i = 0; i < 52; i++) deck.Add(new PlayingCard(i)); } public PlayingCard TopCard { get { return deck.Last(); } set { deck.Add(value); } } public PlayingCard drawCard() { PlayingCard card = TopCard; deck.Remove(card); return card; } public void addCard(PlayingCard card) { deck.Add(card); } public int Size { get { return deck.Count; } } public void displayDeck() { int count = 0; foreach (PlayingCard p in deck) { Console.WriteLine(count + ": " + p.ToString()); count++; } } public void dealDeck(Player[] players, int numberOfPlayers) { for (int i=0; i deck; } public class GinRummyGame { public GinRummyGame(Player[] _players) { players = _players; } public void play() { // Create a shuffled deck DeckOfCards drawDeck = new DeckOfCards(false); drawDeck.shuffleDeck(); // Deal the cards drawDeck.dealDeck(players, players.Length); // Create initialize the discard deck DeckOfCards discardDeck = new DeckOfCards(true); PlayingCard card = drawDeck.drawCard(); discardDeck.addCard(card); foreach (Player p in players) p.displayHand(); drawDeck.displayDeck(); // Start game with player 0 int currentPlayer = 0; bool gameOver=false; int nplayers = players.Length; do { if (drawDeck.Size == 0) { // Reshuffle the discard deck which becomes the draw deck do { PlayingCard card1=discardDeck.drawCard(); drawDeck.addCard(card1); } while (discardDeck.Size>0); drawDeck.shuffleDeck(); card = drawDeck.drawCard(); discardDeck.addCard(card); } PlayState rp = null; Console.WriteLine("============================================================================\n"); Console.WriteLine(players[currentPlayer].Name + " to play"); rp = players[currentPlayer].playHand(drawDeck, discardDeck); players[currentPlayer].upDateDecks(drawDeck, discardDeck, rp); players[currentPlayer].displayHand(); Console.WriteLine("Drawdeck has " + drawDeck.Size + " and the discard deck has " + discardDeck.Size + " cards"); Console.WriteLine("Handval " + players[currentPlayer].handValue(players[currentPlayer].Hand)); if (players[currentPlayer].handValue(players[currentPlayer].Hand) == 7) { gameOver = true; Console.WriteLine(players[currentPlayer].Name + " wins!"); } currentPlayer = (currentPlayer+1) % nplayers; } while (!gameOver); Console.WriteLine("Game over"); } private Player[] players; } }