War Game
<< GreedGameContest | OtherProjectsTrailIndex | Roll Your Own >>
See a working copy at http://www.mathorama.com/WarGame.html
This is an Applet that plays the card Game "War" with five cards, and the winner of each turn gets both cards added to their pile. Winner is the one with all the cards. This version starts with 5 cards and two players. Ace is high, when two cards of the same rank appear, the winner is determined by the suit, in the hierarchy of the game "Bridge" (Spades>Hearts>Diamonds>Clubs). The Card class provided has other methods at your disposal to determine the higher of the two cards. The WarGame class provided can handle ties, and can be adapted easily to have more or less than 5 cards dealt, and more than 2 players.
Students have to write the Deck Class and the Player Class. The Deck class should represent a standard deck of 52 cards and be able to shuffle itself , "deal" the top card (removing the card from the deck), and be able to report how many cards are left. The Player class should have fields that contain the player's name, and an ArrayList<Card> that represents the player's hand. It should be able to report how many cards the player has in their hand, and be able to remove their next card, and add a card to the bottom of their hand.
Starter Code- The Card Class and the WarGame Class
WarGame.java
package war; import java.applet.Applet; import java.awt.Color; import java.awt.Graphics; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; @SuppressWarnings("serial") public class WarGame extends Applet implements MouseListener { Deck deck; Player[] player; String message="Turn No. 1"; int turn=1; public void init() { player = new Player[2]; for (int i=0; i<2; i++){ player[i]=new Player("Player "+(i+1)); } deck= new Deck(); deck.shuffle(); while (deck.cardsLeft()>=player.length && player[0].handSize()<5){ for (int i=0; i<player.length; i++){ player[i].addCard(deck.getCard()); } } addMouseListener(this); } public void paint(Graphics g) { g.setColor(Color.white); g.fillRect(0, 0, 600, 400); g.setColor(Color.black); g.drawString("War Game", 20, 20); g.setColor(Color.blue); g.drawString("click to see next turn", 20, 40); g.drawString(message , 20, 65); for (Player eachPlayer:player){ eachPlayer.showOnlyFirstCard(); //eachPlayer.showAllCards(); } for (int i=0;i<player.length;i++){ g.drawString(player[i].getName(), 20, 130+i*100); g.drawString(player[i].handSize()+" cards", 20, 160+i*100); } for (int i=0;i<player.length;i++){ player[i].draw(g, 80, 100+i*100); } } public void mouseClicked(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mousePressed(MouseEvent e) { } public void mouseReleased(MouseEvent e) { if (player[0].handSize()==0){ message=player[1].getName()+" won in "+turn+" turns"; } else if (player[1].handSize()==0){ message=player[0].getName()+" won in "+turn+" turns"; } else { turn++; message="Turn No. "+turn+". "; Card a=player[0].takeCard(); Card b=player[1].takeCard(); if (a.isLessThanAceHigh(b)){ message+=player[1].getName()+" won last turn with the "+b.toString()+". "; player[1].addCard(b); player[1].addCard(a); }else if (b.isLessThanAceHigh(a)){ message+=player[0].getName()+" won last turn with the "+a.toString()+". "; player[0].addCard(a); player[0].addCard(b); }else { message+=a.toString()+ "ties with the "+b.toString()+". "; player[0].addCard(a); player[1].addCard(b); } } repaint(); } }
Card.java
package war; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Rectangle; /** * class Card here represents a playing card * * @author Chris Thiel * @version 28 Sept 2008 */ public class Card { //some handy constants public static final int SPADES=3; public static final int HEARTS=2; public static final int DIAMONDS=1; public static final int CLUBS=0; /** * suitName is an array contains the name of the Suit * so that the index matches the suit number */ public static final String[] suitName={"Clubs","Diamonds","Hearts","Spades" }; /** * suitSymbol Have the unicode values to print the correct symbol, * arranges so thet the index matches the suit number */ public static final String[] suitSymbol={"\u2663", "\u2666","\u2665","\u2660"}; /** * pipName is an array that contains the name of the card's pips * so that the index matches the number of the card. * For example pipName[1] has a "Ace" */ public static final String[] pipName={"-","Ace","2","3","4","5","6","7","8","9","10", "Jack","Queen","King"}; // instance variables - or Card Attributes /** * suit contains the suit (0 to 3) */ private int suit; /** * pips contains the number of pips of the card (1-13) * Ace is 1 and 13 is King */ private int pips; /** * faceUp is true is the card is exposed * and false otherwise. */ private boolean faceUp; /** * Default Constructor for objects of class Card * is a random card of a random suit */ public Card() { // The default card is randomly chosen suit = (int)(Math.random()*4); pips = 1+(int)(Math.random()*13); faceUp=false; } /** * A Card can be constructed with a determined * number of pips (and integer 1-13) * and suit (an integer from 0-3) */ public Card(int p, int s) { if (s>=0 && s<4) suit = s; if (p>0 && p<14) pips = p; faceUp=false; } /** * A Card can be constructed with a determined * number of pips (a String "Ace" to "King") * and suit (a String "Clubs" to "Spades") */ public Card(String p, String s) { suit = indexOf(suitName, s); pips = indexOf(pipName, p); faceUp=false; } /** * indexOf returns the index of the String s * in the String Array a * (it returns -1 if not found). This method * ignores case. */ public int indexOf(String[] a, String s) { int idx=-1; for (int i=0; i< a.length; i++) if (a[i].toLowerCase().equals(s.toLowerCase())) idx=i; return idx; } /** * @return getSuit returns the Card's suit, * an int from 0 to 3 */ public int getSuit() { return suit; } /** * setSuit changes the Card's suit, * @param the suit 0 to 3. You can use the * predefined integer constants * SPADES, HEARTS, DIAMONDS and CLUBS * from the Card class. */ public void setSuit(int s) { if (s>=0 && s<4) suit=s; } /** * @return getPips returns the Card's pips, * an int from 1 to 13 where an Ace is a 1 * and a King is a 13. */ public int getPips() { // put your code here return pips; } /** * setPips changes the Card's pips, * @param the pips are an integer from 1 to 13, * where 1 is an Ace and 13 is a King. */ public void setPips(int p) { // put your code here if (p>0 && p<14) pips=p; } /** * @return getSuit returns the Card's suit, * an int from 0 to 3 */ public int getValue() { if (pips>9) return 10; return pips; } /** * Two cards are equal if they have * the same number of pips. The suit is ignored * with this comparison * * @return true if they match the number of pips */ public boolean equals(Card c) { if (c.getPips()==pips) return true; return false; } /** * toString will return the contents of the card * in a string format * @return The pips and suit of a card */ public String toString() { return pipName[pips]+" of "+suitName[suit]; } /** * info will return the contents of the card * in a short two character string * @return The pips and suit of a card */ public String info() { if (pips==10) return pipName[pips].substring(0,2)+suitSymbol[suit]; return pipName[pips].substring(0,1)+suitSymbol[suit]; } /** * comparePips will return the difference between * two cards' number of pips. The suit is ignored * with this comparison. Here the ace is low. * If the two cards happen to have the same * number of pips, it returns the integer 0. * * If, for example, * card1 is a 2 of clubs and card2 is a 6 of spades, * then card1.comparePips(card2) returns -4, since * card1 has four less pips than card2. * * @return the difference between number of pips */ public int comparePips( Card c ) { return pips-c.getPips(); } /** * comparePipsAceHigh will return the difference between * two cards' number of pips, Ace High. The suit is ignored * with this comparison, but the Ace is above a King. * If the two cards happen to have the same * number of pips, it returns the integer 0. * * If, for example, * card1 is an ace of clubs and card2 is a queen of spades, * then card1.comparePips(card2) returns 2, since * card1 is two larger than card2. * * @return the difference between number of pips */ public int comparePipsAceHigh( Card c ) { // This needs to be be implemented int myPips=pips; int theirPips=c.getPips(); if (myPips==1) myPips=14; if (theirPips==1) theirPips=14; return myPips-theirPips; } /** * isLessThan will compare two cards by pips, and in case of * a match, will compare the suit. If the number * of pips match, then the higher suit is considered. * * The the order of the suits * (from high to low) is SPADES, HEARTS, DIAMONDS, CLUBS * * The Ace is low, and is considered to be below a 2. * * If the two cards happen to have the same * number of pips, it then compares the suit returns the integer 0. * * If, for example, * card1 is an ace of clubs and card2 is a 2 of spades, * then card1.comparePips(card2) returns true, since * card1 is less than card2. * * If card1 is a 6 of hearts and card2 is a 6 of clubs, * than card1.isLessThan(card2) returns false, * since hearts is greater than clubs * * @return the difference between number of pips */ public boolean isLessThan( Card c ) { if (pips>c.getPips()) return false; if (pips<c.getPips()) return true; //if we got this far, its the same number of pips if (suit <c.getSuit()) return true; // if we got this far, it must have same suit or more return false; } public boolean isLessThanAceHigh( Card c ) { int myPips=pips; int theirPips=c.getPips(); if (myPips==1) myPips=14; if (theirPips==1) theirPips=14; if (myPips>theirPips) return false; if (myPips<theirPips) return true; //if we got this far, its the same number of pips if (suit <c.getSuit()) return true; // if we got this far, it must have same suit or more return false; } public void turnUp(){ faceUp=true; } public void turnDown(){ faceUp=false; } public void turnOver(){ faceUp=!faceUp; } public boolean isFaceUp(){ return faceUp; } public void draw(Graphics g, int x, int y){ g.setColor(Color.WHITE); Rectangle loc=new Rectangle(x,y,60,80); if (faceUp){ g.setFont(new Font("Helvetica", Font.BOLD, 20)); g.setColor(Color.WHITE); g.fillRect(loc.x,loc.y,loc.width,loc.height); g.setColor(Color.BLACK); g.drawRect(loc.x,loc.y,loc.width,loc.height); if (suit>0 && suit<3) g.setColor(Color.RED); g.drawString(this.info(), loc.x+8,loc.y+23); } else { g.setColor(Color.BLUE); g.fillRect(loc.x,loc.y,loc.width,loc.height); g.setColor(Color.BLACK); g.drawRect(loc.x,loc.y,loc.width,loc.height); g.setColor(Color.WHITE); for (int i=2; i<25; i+=5) g.drawRoundRect(loc.x+i, loc.y+i, loc.width-i*2, loc.height-i*2, i, i); } } }
Deck.java
package war; import java.util.ArrayList; public class Deck { private ArrayList<Card> deck; /** * initialize a deck with all 52 cards * use the Card class's Constructor Card(pips, suit) * for suits 0..3 and pips 1..14 */ public Deck (){ } /** * make two random numbers to pick 2 cards from the deck to exchange * do this 200 times. */ public void shuffle(){ } /** * if deck is not empty, remove the top card of the deck * and return it * @return the top card of the deck */ public Card getCard(){ } /** * * @return whether or not the deck has any cards left */ public boolean hasCards(){ } /** * * @return how many cards are left in the deck */ public int cardsLeft(){ } }
Player.java
package war; import java.awt.Graphics; import java.util.ArrayList; public class Player { private String name; private ArrayList<Card> hand; /** * Construct an instance of player with name s * and initialize a new hand of cards. * @param s the players name */ public Player(String s){ } /** * * @return the player's name */ public String getName(){ } /** * Set the player's name to s * @param s the new Name of the player */ public void setName(String s){ } /** * Add the card to the end of the player's hand * @param c is a Card. */ public void addCard(Card c){ } /** * remove the top card of the hand and return the card you removed * @return the top Card */ public Card takeCard(){ } /** * if hand is not empty, turn up the first card of the hand * using the Card class' turnUp() method, then turn down the * rest of the cards in the hand using the Card class' turnDown() method */ public void showOnlyFirstCard(){ } /** * if hand is not empty, the the Card class method turnUp() * to turn up all cards */ public void showAllCards(){ } /** * use a "for each" loop to turn down all the cards in the hand * using the Card class' method turnDown(); */ public void hideAllCards(){ } /** * If the hand is not empty, use a for loop to draw each card in the hand * the Card class can draw the card with the draw(g, x, y) method * offset the cards horizontally by 40 * * @param g the Graphics object to draw upon * @param left the horizontal location * @param top the vertical location */ public void draw(Graphics g, int left, int top){ if (!hand.isEmpty()){ for (int i=0; i<hand.size();i++){ hand.get(i).draw(g, left+i*40, top); } } } /** * * @return the number of cards in the hand */ public int handSize(){ } }