0% found this document useful (0 votes)
51 views27 pages

Card Game

Uploaded by

api-596655668
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
51 views27 pages

Card Game

Uploaded by

api-596655668
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 27

// By: Alex O'Brien, Royal Williams, Adam Momand

// Assignment: Timed "Build" Game

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Assig6


{
public static void main(String[] args)
{
TBGModel gameModel = new TBGModel();
TBGView gameView = new TBGView();
TBGController gameController = new TBGController(gameModel,
gameView);
TBGTimer gameTimer = new TBGTimer(gameController);
gameTimer.start();
gameController.initializeGame(gameTimer);
}
}

class TBGTimer extends Thread


{
private Timer gameTimer;
TBGController controller;

// initialize controller
public TBGTimer(TBGController controller)
{
this.controller = controller;
}

// override method in Thread class


public void run()
{
gameTimer = new Timer(1000, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
controller.updateTimer();
doNothing(10);
}
});
}

public void doNothing(int milliseconds)


{
try
{
Thread.sleep(milliseconds);
}
catch (InterruptedException e)
{
System.out.println("Unexpected Interruption");
}
}

void startTimer()
{
gameTimer.start();
}

void stopTimer()
{
gameTimer.stop();
}
}

class TBGModel
{
// member data
static int NUM_CARDS_PER_HAND = 7;
static int NUM_PLAYERS = 2;
static int numPacksPerDeck = 1;
static int numJokersPerPack = 2;
static int numUnusedCardsPerPack = 0;
static Card[] unusedCardsPerPack = null;

CardGameOutline TimedBuildGame = new


CardGameOutline(numPacksPerDeck,
numJokersPerPack, numUnusedCardsPerPack, unusedCardsPerPack,
NUM_PLAYERS, NUM_CARDS_PER_HAND);

// accessor for game outline


public CardGameOutline getGame()
{
return TimedBuildGame;
}

class CardGameOutline
{
private static final int MAX_PLAYERS = 50;

private int numPlayers;


private int numPacks; // # standard 52-card packs
per deck
// ignoring jokers or unused cards
private int numJokersPerPack; // if 2 per pack & 3 packs per
deck, get 6
private int numUnusedCardsPerPack; // # cards removed from
each pack
private int numCardsPerHand; // # cards to deal each
player
private Deck deck; // holds the initial full
deck and gets
// smaller (usually) during play
private Hand[] hand; // one Hand for each player
private Card[] unusedCardsPerPack;// an array holding the
cards not used
// in the game. e.g. pinochle does not
// use cards 2-8 of any suit

public CardGameOutline( int numPacks, int numJokersPerPack,


int numUnusedCardsPerPack, Card[] unusedCardsPerPack,
int numPlayers, int numCardsPerHand)
{
int k;

// filter bad values


if (numPacks < 1 || numPacks > 6)
numPacks = 1;
if (numJokersPerPack < 0 || numJokersPerPack > 4)
numJokersPerPack = 0;
// > 1 card
if (numUnusedCardsPerPack < 0 || numUnusedCardsPerPack >
50)
numUnusedCardsPerPack = 0;
if (numPlayers < 1 || numPlayers > MAX_PLAYERS)
numPlayers = 4;
// one of many ways to assure at least one full deal to
all players
if(numCardsPerHand < 1 ||
numCardsPerHand > numPacks * (52 -
numUnusedCardsPerPack)
/ numPlayers )
numCardsPerHand = numPacks
* (52 - numUnusedCardsPerPack) / numPlayers;

// allocate
this.unusedCardsPerPack = new Card[numUnusedCardsPerPack];
this.hand = new Hand[numPlayers];
for (k = 0; k < numPlayers; k++)
this.hand[k] = new Hand();
deck = new Deck(numPacks);

// assign to members
this.numPacks = numPacks;
this.numJokersPerPack = numJokersPerPack;
this.numUnusedCardsPerPack = numUnusedCardsPerPack;
this.numPlayers = numPlayers;
this.numCardsPerHand = numCardsPerHand;
for (k = 0; k < numUnusedCardsPerPack; k++)
this.unusedCardsPerPack[k] = unusedCardsPerPack[k];

// prepare deck and shuffle


newGame();
}

// constructor overload/default for game like bridge


public CardGameOutline()
{
this(1, 0, 0, null, 4, 13);
}

public Hand getHand(int k)


{
// hands start from 0 like arrays

// on error return automatic empty hand


if (k < 0 || k >= numPlayers)
return new Hand();

return hand[k];
}

public Card getCardFromDeck() { return deck.dealCard(); }

public int getNumCardsRemainingInDeck() { return


deck.getNumCards(); }

public void newGame()


{
int k, j;

// clear the hands


for (k = 0; k < numPlayers; k++)
hand[k].resetHand();

// restock the deck


deck.init(numPacks);

// remove unused cards


for (k = 0; k < numUnusedCardsPerPack; k++)
deck.removeCard( unusedCardsPerPack[k] );

// add jokers
for (k = 0; k < numPacks; k++)
for ( j = 0; j < numJokersPerPack; j++)
deck.addCard( new Card('X', Card.Suit.values()
[j]) );
// shuffle the cards
deck.shuffle();
}

public boolean deal()


{
// returns false if not enough cards, but deals what it
can
int k, j;
boolean enoughCards;

// clear all hands


for (j = 0; j < numPlayers; j++)
hand[j].resetHand();

enoughCards = true;
for (k = 0; k < numCardsPerHand && enoughCards ; k++)
{
for (j = 0; j < numPlayers; j++)
if (deck.getNumCards() > 0)
hand[j].takeCard( deck.dealCard() );
else
{
enoughCards = false;
break;
}
}

// adding 3 cards to the play area


if (deck.getNumCards() >= 3)
{
TBGView.leftCards[0] = new Card(deck.dealCard());
TBGView.middleCards[0] = new Card (deck.dealCard());
TBGView.rightCards[0] = new Card (deck.dealCard());
}
else
enoughCards = false;

return enoughCards;
}

void sortHands()
{
int k;

for (k = 0; k < numPlayers; k++)


hand[k].sort();
}
Card playCard(int playerIndex, int cardIndex)
{
// returns bad card if either argument is bad
if (playerIndex < 0 || playerIndex > numPlayers - 1 ||
cardIndex < 0 || cardIndex > numCardsPerHand - 1)
{
//Creates a card that does not work
return new Card('M', Card.Suit.spades);
}

// return the card played


return hand[playerIndex].playCard(cardIndex);

boolean takeCard(int playerIndex)


{
// returns false if either argument is bad
if (playerIndex < 0 || playerIndex > numPlayers - 1)
return false;

// Are there enough Cards?


if (deck.getNumCards() <= 0)
return false;

return hand[playerIndex].takeCard(deck.dealCard());
}
}

static class Card


{
// enum type which defines the different possible suits of
cards
public enum Suit {clubs, diamonds, hearts, spades};

// instance variables
private char value;
private Suit suit;
private boolean cardError;

// constructor
public Card(char value, Suit suit)
{
set(value, suit);
}

// overloaded constructor, default card


public Card()
{
value = 'A';
suit = Suit.spades;
}

// copy constructor that will create a duplicate of the


original
public Card(Card origCard)
{
value = origCard.value;
suit = origCard.suit;
}

// displays the card if cardError != false


public String toString()
{
String string;
if (cardError)
string = "** INVALID **";
else
string = String.valueOf(value) + " of " +
String.valueOf(suit);
return string;
}

// mutator which will use private helper method isValid for


legal values
// sets cardError boolean to true or false based on isValid
boolean
public boolean set(char value, Suit suit)
{
if (isValid(value, suit))
{
cardError = false;
this.value = value;
this.suit = suit;
return true;
}
else
{
cardError = true;
return false;
}
}

// accessors
public Suit getSuit()
{
return suit;
}

public char getValue()


{
return value;
}

public boolean getCardError()


{
return cardError;
}

// equals method
public boolean equals(Card card)
{
return ((this.value == card.value) &&
(this.suit.equals(card.suit))
&& (this.getCardError() == card.getCardError()));
}

// private helper method to test whether char and suit are


legal
private boolean isValid(char value, Suit suit)
{
if ((value == 'A' || value == 'J' || value == 'Q' || value
== 'K'
|| value == '1' || value == '2' || value == '3' ||
value == '4'
|| value == '5' || value == '6' || value == '7' ||
value == '8'
|| value == '9' || value == 'T' || value == 'X')
&& (suit == Suit.clubs
|| suit == Suit.diamonds || suit == Suit.hearts
|| suit == Suit.spades))
return true;
else
{
return false;
}
}

//Rank from A to X
public static char[] valueRanks()
{
return "A123456789TJQKX".toCharArray();
}

static void arraySort(Card[] cards, int arraySize)


{
//Gets rank
char[] rank = valueRanks();

//Bubble sort from lowest to highest


for(int i = 0; i < arraySize - 1; i++)
{
for(int j = 0; j < arraySize + 1; j++)
{
//Checks rank by index
if(new String(rank).indexOf(cards[j].getValue()) >
new String(rank).indexOf(cards[j+1].getValue()))
{
//Swaps temp and arr[i]
Card temp = cards[j];
cards[j] = cards[j+1];
cards[j+1] = temp;
}
}
}
}
}

static class Hand


{
// maximum amount of cards in a hand
public static int MAX_HAND_CARDS = 56;

//private instance variables


private Card[] myCards;
private int numCards;

// default constructor
public Hand()
{
myCards = new Card[MAX_HAND_CARDS];
numCards = 0;
}

// removing cards from hand


public void resetHand()
{
for(int index = 0; index < myCards.length; index++)
{
myCards[index] = null;
}
}

// adds card to the next available position in the myCards


array
public boolean takeCard(Card card)
{
if(numCards < MAX_HAND_CARDS)
{
// using copy constructor from Card for deep copy
myCards[numCards] = new Card(card);
numCards++;
return true;
}
else
return false;
}

// returns/removes the card in the top spot occupied in the


array
// returns bad card if none left
public Card playCard()
{
Card playedCard;
if (myCards[numCards - 1] != null)
{
playedCard = new Card(myCards[numCards -
1].getValue(),
myCards[numCards - 1].getSuit());
myCards[numCards - 1] = null;
numCards--;
return playedCard;
}
else
{
playedCard = new Card('D', Card.Suit.diamonds);
return playedCard;
}
}

// prints the entire Hand of cards


public String toString()
{
String handValues = "";
int index;
for(index = 0; index < numCards; index++)
{
handValues += (String.valueOf(myCards[index]));
if (index < numCards - 1)
handValues += ", ";
if(index % 5 == 3)
handValues += "\n";
}
String entireHand = "Hand = ( " + handValues + " )";
return entireHand;
}

// accesor method
public int getNumCards()
{
return numCards;
}

// accessor for individual card, returns bad card if invalid


public Card inspectCard(int k)
{
Card inspectedCard;
if (myCards[k] != null)
{
inspectedCard = new Card(myCards[k].getValue(),
myCards[k].getSuit());
return inspectedCard;
}
else
{
inspectedCard = new Card('D', Card.Suit.diamonds);
return inspectedCard;
}
}

public void sort()


{
if(this.getNumCards() != 0)
Card.arraySort(myCards, numCards);
}

public Card playCard(int cardIndex)


{
if ( numCards == 0 ) //error
{
// creates a card that does not work
return new Card('M', Card.Suit.spades);
}
// decreases numCards
Card card = myCards[cardIndex];

numCards--;
for(int i = cardIndex; i < numCards; i++)
{
myCards[i] = myCards[i + 1];
}

myCards[numCards] = null;

return card;
}
}

static class Deck


{
// maximum of 6 packs x 56 cards
public static final int MAX_CARDS = 336;
// array containing 52 card references
private static Card[] masterPack = new Card[56];
// all of the cards
private Card[] cards;
// the top of the card deck, also variable for the number of
cards
private int topCard;

// constructor populates the arrays, assigns initial values to


members
public Deck(int numPacks)
{
allocateMasterPack();
topCard = ((numPacks * 56) - 1);
cards = new Card[numPacks * 56];

if ((numPacks * 56) > MAX_CARDS)


{
System.out.println("System Error. Maximum # of packs
is 6.");
System.exit(0);
}
int index = 0;
for (int k = 1; k <= numPacks; k++)
{
for (int i = 0; i < 56; i++)
{
cards[index] = masterPack[i];
index++;
}
}
}

// overloaded constructor for only 1 pack


public Deck()
{
allocateMasterPack();
topCard = 55;
cards = new Card[56];
for (int i = 0; i < cards.length; i++)
cards[i] = masterPack[i];
}

// repopulates cards[] with the standard 56 * numPack cards


public void init(int numPacks)
{
cards = new Card[numPacks * 56];
topCard = ((numPacks * 56) - 1);
int index = 0;
for (int k = 1; k <= numPacks; k++)
{
for (int i = 0; i < 56; i++)
{
cards[index] = masterPack[i];
index++;
}
}
}

// shuffles the cards in the deck with Math.random


public void shuffle()
{
int index;
Card tempCard = new Card();
for (int k = 0; k < cards.length; k++)
{
// using Math.random for int between 0 and
(cards.length - 1)
index = (int) (Math.random() * cards.length);
tempCard = cards[k];
cards[k] = cards[index];
cards[index] = tempCard;
}
}

// returns and removes card from top topCard in cards[]


public Card dealCard()
{
Card dealtCard;
if (cards[topCard] != null)
{
dealtCard = new Card(cards[topCard].getValue(),
cards[topCard].getSuit());
cards[topCard] = null;
topCard--;
return dealtCard;
}
else
{
dealtCard = new Card('D', Card.Suit.diamonds);
return dealtCard;
}
}

// accessor returns integer representing the position of the


top card
public int getTopCard()
{
return topCard;
}

// accessor for individual card, object copy, return bad card


if invalid
public Card inspectCard(int k)
{
Card inspectedCard;
if (cards[k] != null)
{
inspectedCard = new Card(cards[k].getValue(),
cards[k].getSuit());
return inspectedCard;
}
else
{
inspectedCard = new Card('D', Card.Suit.diamonds);
return inspectedCard;
}
}

// private method allows only one initialization of the


masterPack array
private static void allocateMasterPack()
{
if (masterPack[0] != null)
return;
else
{
// creating arrays for char values and enum suits
char[] values = {'A', '2', '3', '4', '5', '6',
'7', '8', '9', 'T', 'J', 'Q', 'K', 'X'};
Card.Suit[] suits = {Card.Suit.clubs,
Card.Suit.diamonds,
Card.Suit.hearts, Card.Suit.spades};

// initializing masterPack array with helper arrays


int counter = 0;
for (int i = 0; i < 14; i++)
for (int k = 0; k < 4; k++)
{
masterPack[counter] = new Card(values[i],
suits[k]);
counter ++;
}
}
}

// makes sure that there are not too many instances of a card
public boolean addCard(Card card)
{
if (topCard + 1 >= Hand.MAX_HAND_CARDS)
{
return false;
}
else
{
topCard++;
cards[topCard] = card;
return true;
}
}

// removes the card at the top of the deck


public boolean removeCard(Card card)
{
// loop to find a specific card
for(int i = 0; i < cards.length; i++)
{
if(card == cards[i])
{
cards[i] = null;
return true;
}
}
return false;
}

// re-sorts the deck of cards in the right order


public void sort()
{
Card.arraySort(cards, cards.length);
}

// returns the remaining number of cards in the deck


public int getNumCards()
{
int numOfCards = 0;
for(int i = 0; i < cards.length; i++)
{
if(cards[i] != null)
{
numOfCards++;
}
}
return numOfCards;
}
}
}
class TBGView
{
// int variables used to check if there is a possible play for
human/comp
static int card = 0;
static int leftCard = 0;
static int middleCard = 0;
static int rightCard = 0;
static int leftCardsIndex = 0;
static int middleCardsIndex = 0;
static int rightCardsIndex = 0;

// card arrays for play area


static TBGModel.Card[] leftCards = new TBGModel.Card[56];
static TBGModel.Card[] middleCards = new TBGModel.Card[56];
static TBGModel.Card[] rightCards = new TBGModel.Card[56];

// buttons, labels
static JButton[] humanButtons = new
JButton[TBGModel.NUM_CARDS_PER_HAND];
JButton stopButton = new JButton("Stop");
JButton startButton = new JButton("Start");
JButton cannotPlayButton = new JButton("I Cannot Play");
JLabel cardsLeftInDeckStat = new JLabel();
JLabel humanCannotPlayStat = new JLabel();
JLabel compCannotPlayStat = new JLabel();

// booleans, integers for cannot play stats


static boolean cannotPlayRequired;
static boolean compCannotPlayRequired;
static boolean humanCannotPlay;
static boolean compCannotPlay;
static int humanCannotPlays = 0;
static int compCannotPlays = 0;

// timer variables
static int counter = 0;
TBGTimer gameTimer;
JLabel timer;

// coloring the window


private Color lightOrange = new Color(255, 179, 102);
private Color beige = new Color(255, 230, 204);

// listeners
public void addStartListener(ActionListener startListener)
{
startButton.addActionListener(startListener);
}
public void addStopListener(ActionListener stopListener)
{
stopButton.addActionListener(stopListener);
}

public void addCannotPlayListener(ActionListener


cannotPlayListener)
{
cannotPlayButton.addActionListener(cannotPlayListener);
}

// establish main frame in which program will run


CardTable myCardTable = new CardTable("Timed Build Game",
TBGModel.NUM_CARDS_PER_HAND, TBGModel.NUM_PLAYERS);

// accessor for cardtable


public CardTable getTable()
{
return myCardTable;
}

// initializes game info, timer


public void initializeGame(TBGModel.CardGameOutline
timedBuildGame)
{
myCardTable.setSize(960, 720);
myCardTable.setLocationRelativeTo(null);
myCardTable.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myCardTable.pnlPlayArea.setLayout(new GridLayout(1, 3));
playerTurn(timedBuildGame);
timer = new JLabel("00:00", JLabel.CENTER);
myCardTable.pnlTimer.add(timer);
myCardTable.pnlTimer.add(startButton);
myCardTable.pnlTimer.add(stopButton);
}

public void playerTurn(TBGModel.CardGameOutline timedBuildGame)


{
// ends game if cards are empty
if ((timedBuildGame.getNumCardsRemainingInDeck() < 1)
|| (humanCannotPlay && compCannotPlay
&& timedBuildGame.getNumCardsRemainingInDeck() <= 3))
{
showWinner();
humanCannotPlay = false;
return;
}

// adds 3 cards to play area if both players skip


if (humanCannotPlay && compCannotPlay)
{
addThreeCards(timedBuildGame.getCardFromDeck(),
timedBuildGame.getCardFromDeck(),
timedBuildGame.getCardFromDeck());
humanCannotPlay = false;
compCannotPlay = false;
playerTurn(timedBuildGame);
}

// removes all cards/stats from panels every turn


myCardTable.pnlHumanHand.removeAll();
myCardTable.pnlComputerHand.removeAll();
myCardTable.pnlPlayArea.removeAll();
myCardTable.pnlStats.removeAll();

// setting booleans
// cannoyPlayRequired booleans will be true unless proven
otherwise
humanCannotPlay = false;
cannotPlayRequired = true;
compCannotPlay = false;
compCannotPlayRequired = true;

// initializing human buttons array


for (int i = 0; i < TBGModel.NUM_CARDS_PER_HAND; i++)
{
humanButtons[i] = new JButton(GUICard.getIcon
(timedBuildGame.getHand(1).inspectCard(i)));
humanButtons[i].setMargin(new Insets(0,0,0,0));
@SuppressWarnings("removal")
final Integer innerI = new Integer(i);
humanButtons[i].addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
addCard(timedBuildGame.playCard(1, innerI));
timedBuildGame.takeCard(1);
computerTurn(timedBuildGame);
playerTurn(timedBuildGame);
}
});

// setting up play area logic


card =
GUICard.valueAsInt(timedBuildGame.getHand(1).inspectCard(i));
leftCard = GUICard.valueAsInt(leftCards[leftCardsIndex]);
middleCard =
GUICard.valueAsInt(middleCards[middleCardsIndex]);
rightCard =
GUICard.valueAsInt(rightCards[rightCardsIndex]);

// only enabling cards that can be played


if (card != leftCard && (card == leftCard - 1
|| card == leftCard + 1)
|| card != middleCard && (card == middleCard - 1
|| card == middleCard + 1)
|| card != rightCard && (card == rightCard - 1
|| card == rightCard + 1))
{
humanButtons[i].setEnabled(true);
// only enables the cannot play button if required
if (cannotPlayRequired)
{
cannotPlayRequired = false;
}
}
else
humanButtons[i].setEnabled(false);
myCardTable.pnlHumanHand.add(humanButtons[i]);
}

// showing all back card images for computer


for (int i = 0; i < TBGModel.NUM_CARDS_PER_HAND; i++)
{
myCardTable.pnlComputerHand.add(new JLabel
(GUICard.getBackCardIcon()));
}

// populate play area


myCardTable.pnlPlayArea.add(new JLabel(
GUICard.getIcon(leftCards[leftCardsIndex])));
myCardTable.pnlPlayArea.add(new JLabel(
GUICard.getIcon(middleCards[middleCardsIndex])));
myCardTable.pnlPlayArea.add(new JLabel(
GUICard.getIcon(rightCards[rightCardsIndex])));

// populate stats panel


if (timedBuildGame.getNumCardsRemainingInDeck() == 1)
{
cardsLeftInDeckStat = new JLabel
(timedBuildGame.getNumCardsRemainingInDeck()
+ " card in deck");
}
else
{
cardsLeftInDeckStat = new JLabel
(timedBuildGame.getNumCardsRemainingInDeck()
+ " cards in deck");
}
myCardTable.pnlStats.add(cardsLeftInDeckStat);
humanCannotPlayStat = new JLabel("Player: " + humanCannotPlays
+ " cannot plays");
myCardTable.pnlStats.add(humanCannotPlayStat);
compCannotPlayStat = new JLabel("Computer: " + compCannotPlays
+ " cannot plays");
myCardTable.pnlStats.add(compCannotPlayStat);
cannotPlayButton.setEnabled(cannotPlayRequired);
myCardTable.repaint();
myCardTable.pnlStats.add(cannotPlayButton);
myCardTable.setVisible(true);
}

// computer will automatically play a card if a play is available


// otherwise, computer will add "cannot play" to stats
public void computerTurn(TBGModel.CardGameOutline timedBuildGame)
{
for (int i = 0; i < TBGModel.NUM_CARDS_PER_HAND; i++)
{
card =
GUICard.valueAsInt(timedBuildGame.getHand(0).inspectCard(i));
leftCard = GUICard.valueAsInt(leftCards[leftCardsIndex]);
middleCard =
GUICard.valueAsInt(middleCards[middleCardsIndex]);
rightCard =
GUICard.valueAsInt(rightCards[rightCardsIndex]);

// computer will play card if available


if (card != leftCard && (card == leftCard - 1
|| card == leftCard + 1)
|| card != middleCard && (card == middleCard - 1
|| card == middleCard + 1)
|| card != rightCard && (card == rightCard - 1
|| card == rightCard + 1))
{
// computer plays card, takes card from deck
// if able to play a card, cannotPlayRequired = false
addCard(timedBuildGame.playCard(0, i));
timedBuildGame.takeCard(0);
compCannotPlayRequired = false;
break;
}
}
// if no cards are playable, compCannotPlay++
if (compCannotPlayRequired)
{
compCannotPlay = true;
compCannotPlays++;
}
}
// if player wins, win message
public void playerWins()
{
JOptionPane.showMessageDialog(null, "Player Wins! Player had "
+ humanCannotPlays + " cannot plays and computer had "
+ compCannotPlays + " cannot plays.");
}

// if comp wins, win message


public void compWins()
{
JOptionPane.showMessageDialog(null, "Computer Wins! Computer
had "
+ compCannotPlays + " cannot plays and player had "
+ humanCannotPlays + " cannot plays.");
}

// show win message or tie message at end of game


public void showWinner()
{
if (humanCannotPlays < compCannotPlays)
{
playerWins();
}
else if (humanCannotPlays > compCannotPlays)
{
compWins();
}
else
{
JOptionPane.showMessageDialog(null, "Tie game! Player had
"
+ humanCannotPlays + " cannot plays and computer had "
+ compCannotPlays + " cannot plays.");
}

// disables card buttons after the game has ended


for (int i = 0; i < TBGModel.NUM_CARDS_PER_HAND; i++)
humanButtons[i].setEnabled(false);
}

// updates the timer counter


public void updateTimer()
{
counter++;
timer.setText(String.format("%02d:%02d", counter / 60,
(counter % (24 * 3600)) % 60));
}
// below methods will help with logic for play area cards
// adds cards to all three piles in case of both players skipping
public void addThreeCards(TBGModel.Card cardOne, TBGModel.Card
cardTwo,
TBGModel.Card cardThree)
{
leftCardsIndex++;
leftCards[leftCardsIndex] = cardOne;
middleCardsIndex++;
middleCards[middleCardsIndex] = cardTwo;
rightCardsIndex++;
rightCards[rightCardsIndex] = cardThree;
}

// method used in conjunction with playCard to play to correct


pile
public static boolean addCard(TBGModel.Card card)
{
int cardToAdd = GUICard.valueAsInt(card);
int leftCard = GUICard.valueAsInt(leftCards[leftCardsIndex]);
int middleCard =
GUICard.valueAsInt(middleCards[middleCardsIndex]);
int rightCard =
GUICard.valueAsInt(rightCards[rightCardsIndex]);

if (cardToAdd != leftCard
&& (cardToAdd == leftCard + 1
|| cardToAdd == leftCard - 1))
{
leftCardsIndex++;
leftCards[leftCardsIndex] = new
TBGModel.Card(card.getValue(),
card.getSuit());
}
else if (cardToAdd != middleCard
&& (cardToAdd == middleCard + 1
|| cardToAdd == middleCard - 1))
{
middleCardsIndex++;
middleCards[middleCardsIndex] = new
TBGModel.Card(card.getValue(),
card.getSuit());
}
else if (cardToAdd != rightCard
&& (cardToAdd == rightCard + 1
|| cardToAdd == rightCard - 1))
{
rightCardsIndex++;
rightCards[rightCardsIndex] = new
TBGModel.Card(card.getValue(),
card.getSuit());
}
else
return false;
return true;
}

class CardTable extends JFrame


{
static int MAX_CARDS_PER_HAND = 56;
static int MAX_PLAYERS = 2;
private int numCardsPerHand;
private int numPlayers;

// panels for computer hand, player hand, play area, timer


public JPanel pnlComputerHand, pnlHumanHand, pnlPlayArea,
pnlTimer,
pnlStats;

// filters input, adds panels to JFrame, establishes layouts


CardTable(String title, int numCardsPerHand, int numPlayers)
{
setTitle(title);
setLayout(new BorderLayout());

if(numCardsPerHand > MAX_CARDS_PER_HAND || numPlayers >


MAX_PLAYERS)
{
return;
}
this.numPlayers = numPlayers;
this.numCardsPerHand = numCardsPerHand;

pnlComputerHand = new JPanel();

pnlComputerHand.setBorder(BorderFactory.createTitledBorder(
BorderFactory.createEtchedBorder(), "Computer Hand"));
add(pnlComputerHand, BorderLayout.NORTH);
pnlComputerHand.setBackground(lightOrange);

pnlHumanHand = new JPanel();


pnlHumanHand.setBorder(BorderFactory.createTitledBorder(
BorderFactory.createEtchedBorder(), "Player Hand"));
add(pnlHumanHand, BorderLayout.SOUTH);
pnlHumanHand.setBackground(lightOrange);

pnlPlayArea = new JPanel();


pnlPlayArea.setBorder(BorderFactory.createTitledBorder(
BorderFactory.createEtchedBorder(), "Play Area"));
add(pnlPlayArea, BorderLayout.CENTER);
pnlPlayArea.setBackground(beige);

pnlTimer = new JPanel();


pnlTimer.setBorder(BorderFactory.createTitledBorder(
BorderFactory.createEtchedBorder(), "Timer"));
add(pnlTimer, BorderLayout.WEST);
pnlTimer.setBackground(lightOrange);

pnlStats = new JPanel();


pnlStats.setBorder(BorderFactory.createTitledBorder(
BorderFactory.createEtchedBorder(), "Statistics"));
pnlStats.setPreferredSize(new Dimension(180, 600));
pnlStats.setMinimumSize(new Dimension(180, 600));
add(pnlStats, BorderLayout.EAST);
pnlStats.setBackground(lightOrange);

// accessors
public int getNumCardsPerHand()
{
return numCardsPerHand;
}
public int getNumPlayers()
{
return numPlayers;
}

public JPanel getHumanHandPnl()


{
return pnlHumanHand;
}

public JPanel getComputerHandPnl()


{
return pnlComputerHand;
}

public JPanel getPlayAreaPnl()


{
return pnlPlayArea;
}
}

static class GUICard


{
// member data, iconsLoaded allows to check if icons loaded
once already
private static Icon[][] iconCards = new ImageIcon[14][4];
private static Icon iconBack;
static boolean iconsLoaded = false;

// loads the iconCards 2D array one time


static void loadCardIcons()
{
// return if iconCards has already been initialized
if (iconsLoaded == true)
return;

// filling iconCards with Icons holding .gif files


int k, j;
for (k = 0; k < 14; k++)
for (j = 0; j < 4; j++)
{
iconCards[k][j] = new ImageIcon("images/"
+ turnIntIntoCardValue(k)
+ turnIntIntoCardSuit(j) + ".gif");
}
iconBack = new ImageIcon("images/BK.gif");
iconsLoaded = true;
}

// turns 0-13 into "A", "2", ... "Q", "K", "X"


static String turnIntIntoCardValue(int k)
{
String[] cardValues = {"A", "2", "3", "4", "5", "6",
"7", "8", "9", "T", "J", "Q", "K", "X"};
return cardValues[k];
}

// turns 0-3 into "C", "D", "H", "S"


static String turnIntIntoCardSuit(int j)
{
String[] cardSuits = {"C", "D", "H", "S"};
return cardSuits[j];
}

// returns an icon corresponding to the card argument


static public Icon getIcon(TBGModel.Card card)
{
loadCardIcons();
return iconCards[valueAsInt(card)][suitAsInt(card)];
}

// returns the back card icon


static public Icon getBackCardIcon()
{
loadCardIcons();
return iconBack;
}
// private helper method returns int corresponding with the
suit of card
private static int suitAsInt(TBGModel.Card card)
{
int suit = 99;
TBGModel.Card.Suit[] suits = {TBGModel.Card.Suit.clubs,
TBGModel.Card.Suit.diamonds,
TBGModel.Card.Suit.hearts,
TBGModel.Card.Suit.spades};
for (int i = 0; i < 4; i++)
if (card.getSuit() == suits[i])
suit = i;
return suit;
}

// private helper method returns int corresponding with the


card value
private static int valueAsInt(TBGModel.Card card)
{
int value = 99;
char[] values = {'A', '2', '3', '4', '5', '6',
'7', '8', '9', 'T', 'J', 'Q', 'K', 'X'};
for (int i = 0; i < 14; i++)
if (card.getValue() == values[i])
value = i;
return value;
}
}
}

class TBGController
{
TBGModel gameModel;
TBGView gameView;
TBGTimer gameTimer;
TBGModel.CardGameOutline game;
TBGView.CardTable cardTable;

public TBGController(TBGModel gameModel, TBGView gameView)


{
this.gameModel = gameModel;
this.gameView = gameView;

this.gameView.addStartListener(new StartListener());
this.gameView.addStopListener(new StopListener());
this.gameView.addCannotPlayListener(new CannotPlayListener());
}

public void initializeGame(TBGTimer gameTimer)


{
game = gameModel.getGame();
cardTable = gameView.getTable();
game.deal();
gameView.initializeGame(game);
this.gameTimer = gameTimer;
}

public void updateTimer()


{
gameView.updateTimer();
}

// inner class to start timer


class StartListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
gameTimer.startTimer();
}
}

// inner class to stop timer


class StopListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
gameTimer.stopTimer();
}
}

// inner class to track human cannot plays


class CannotPlayListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
TBGView.humanCannotPlay = true;
TBGView.humanCannotPlays++;
gameView.computerTurn(game);
gameView.playerTurn(game);
}
}
}

You might also like