/* Simple Solitare Card Game in Java Written by Tim Budd, Oregon State University, 1996 */ import java.awt.*; import java.applet.*; class Card { // constructor Card (int sv, int rv) { s = sv; r = rv; faceup = false; } // access attributes of card public int rank () { return r; } public int suit() { return s; } public boolean faceUp() { return faceup; } public void flip() { faceup = ! faceup; } public int color() { if (suit() == heart || suit() == diamond) return red; return black; } public void draw (Graphics g, int x, int y) { String names[] = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"}; // clear rectangle, draw border g.clearRect(x, y, width, height); g.setColor(Color.black); g.drawRect(x, y, width, height); // draw body of card if (faceUp()) { if (color() == red) g.setColor(Color.red); else g.setColor(Color.blue); g.drawString(names[rank()], x+3, y+15); if (suit() == heart) { g.drawLine(x+25, y+30, x+35, y+20); g.drawLine(x+35, y+20, x+45, y+30); g.drawLine(x+45, y+30, x+25, y+60); g.drawLine(x+25, y+60, x+5, y+30); g.drawLine(x+5, y+30, x+15, y+20); g.drawLine(x+15, y+20, x+25, y+30); } else if (suit() == spade) { g.drawLine(x+25, y+20, x+40, y+50); g.drawLine(x+40, y+50, x+10, y+50); g.drawLine(x+10, y+50, x+25, y+20); g.drawLine(x+23, y+45, x+20, y+60); g.drawLine(x+20, y+60, x+30, y+60); g.drawLine(x+30, y+60, x+27, y+45); } else if (suit() == diamond) { g.drawLine(x+25, y+20, x+40, y+40); g.drawLine(x+40, y+40, x+25, y+60); g.drawLine(x+25, y+60, x+10, y+40); g.drawLine(x+10, y+40, x+25, y+20); } else if (suit() == club) { g.drawOval(x+20, y+25, 10, 10); g.drawOval(x+25, y+35, 10, 10); g.drawOval(x+15, y+35, 10, 10); g.drawLine(x+23, y+45, x+20, y+55); g.drawLine(x+20, y+55, x+30, y+55); g.drawLine(x+30, y+55, x+27, y+45); } } else { // face down g.setColor(Color.yellow); g.drawLine(x+15, y+5, x+15, y+65); g.drawLine(x+35, y+5, x+35, y+65); g.drawLine(x+5, y+20, x+45, y+20); g.drawLine(x+5, y+35, x+45, y+35); g.drawLine(x+5, y+50, x+45, y+50); } } // data fields for colors and suits final static int width = 50; final static int height = 70; final static int red = 0; final static int black = 1; final static int heart = 0; final static int spade = 1; final static int diamond = 2; final static int club = 3; //private static String names[] = {"A", "2", "3", "4", "5", "6", // "7", "8", "9", "10", "J", "Q", "K"}; // data fields private boolean faceup; private int r; private int s; public Card link; } class CardPile { CardPile (int xl, int yl) { x = xl; y = yl; firstCard = null; } // access to cards are not overridden public Card top() { return firstCard; } public boolean empty() { return firstCard == null; } public Card pop() { Card result = null; if (firstCard != null) { result = firstCard; firstCard = firstCard.link; } return result; } // the following are sometimes overridden public boolean includes (int tx, int ty) { return x <= tx && tx <= x + Card.width && y <= ty && ty <= y + Card.height; } public void select (int tx, int ty) { // do nothing } public void addCard (Card aCard) { aCard.link = firstCard; firstCard = aCard; } public void display (Graphics g) { g.setColor(Color.black); if (firstCard == null) g.drawRect(x, y, Card.width, Card.height); else firstCard.draw(g, x, y); } public boolean canTake (Card aCard) { return false; } // coordinates of the card pile protected int x; protected int y; private Card firstCard; } class DeckPile extends CardPile { DeckPile (int x, int y) { // first initialize parent super(x, y); // then create the new deck // first put them into a local pile CardPile pileOne = new CardPile(0, 0); CardPile pileTwo = new CardPile(0, 0); int count = 0; for (int i = 0; i < 4; i++) for (int j = 0; j <= 12; j++) { pileOne.addCard(new Card(i, j)); count++; } // then pull them out randomly for (; count > 0; count--) { int limit = ((int)(Math.random() * 1000)) % count; // move down to a random location for (int i = 0; i < limit; i++) pileTwo.addCard(pileOne.pop()); // then add the card found there addCard(pileOne.pop()); // then put the decks back together while (! pileTwo.empty()) pileOne.addCard(pileTwo.pop()); } } public void select(int tx, int ty) { if (empty()) return; Solitare.discardPile.addCard(pop()); } } class DiscardPile extends CardPile { DiscardPile (int x, int y) { super (x, y); } public void addCard (Card aCard) { if (! aCard.faceUp()) aCard.flip(); super.addCard(aCard); } public void select (int tx, int ty) { if (empty()) return; Card topCard = pop(); for (int i = 0; i < 4; i++) if (Solitare.suitPile[i].canTake(topCard)) { Solitare.suitPile[i].addCard(topCard); return; } for (int i = 0; i < 7; i++) if (Solitare.tableau[i].canTake(topCard)) { Solitare.tableau[i].addCard(topCard); return; } // nobody can use it, put it back on our list addCard(topCard); } } class SuitPile extends CardPile { SuitPile (int x, int y) { super(x, y); } public boolean canTake (Card aCard) { if (empty()) return aCard.rank() == 0; Card topCard = top(); return (aCard.suit() == topCard.suit()) && (aCard.rank() == 1 + topCard.rank()); } } class TablePile extends CardPile { TablePile (int x, int y, int c) { // initialize the parent class super(x, y); // then initialize our pile of cards for (int i = 0; i < c; i++) { addCard(Solitare.deckPile.pop()); } // flip topmost card face up top().flip(); } public boolean canTake (Card aCard) { if (empty()) return aCard.rank() == 12; Card topCard = top(); return (aCard.color() != topCard.color()) && (aCard.rank() == topCard.rank() - 1); } public boolean includes (int tx, int ty) { // don't test bottom of card return x <= tx && tx <= x + Card.width && y <= ty; } public void select (int tx, int ty) { if (empty()) return; // if face down, then flip Card topCard = top(); if (! topCard.faceUp()) { topCard.flip(); return; } // else see if any suit pile can take card topCard = pop(); for (int i = 0; i < 4; i++) if (Solitare.suitPile[i].canTake(topCard)) { Solitare.suitPile[i].addCard(topCard); return; } // else see if any other table pile can take card for (int i = 0; i < 7; i++) if (Solitare.tableau[i].canTake(topCard)) { Solitare.tableau[i].addCard(topCard); return; } // else put it back on our pile addCard(topCard); } private int stackDisplay(Graphics g, Card aCard) { int localy; if (aCard == null) return y; localy = stackDisplay(g, aCard.link); aCard.draw(g, x, localy); return localy + 35; } public void display (Graphics g) { stackDisplay(g, top()); } } public class Solitare extends Applet { static DeckPile deckPile; static DiscardPile discardPile; static TablePile tableau[]; static SuitPile suitPile[]; static CardPile allPiles[]; public void init() { // first allocate the arrays allPiles = new CardPile[13]; suitPile = new SuitPile[4]; tableau = new TablePile[7]; // then fill them in allPiles[0] = deckPile = new DeckPile(335, 5); allPiles[1] = discardPile = new DiscardPile(268, 5); for (int i = 0; i < 4; i++) allPiles[2+i] = suitPile[i] = new SuitPile(15 + 60 * i, 5); for (int i = 0; i < 7; i++) allPiles[6+i] = tableau[i] = new TablePile(5 + 55 * i, 80, i+1); } public void paint(Graphics g) { for (int i = 0; i < 13; i++) allPiles[i].display(g); } public boolean mouseDown(Event evt, int x, int y) { for (int i = 0; i < 13; i++) if (allPiles[i].includes(x, y)) { allPiles[i].select(x, y); repaint(); return true; } return true; } }