Advertisement
Guest User

Untitled

a guest
Dec 10th, 2018
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 16.64 KB | None | 0 0
  1.  
  2. import java.awt.*;
  3. import java.awt.event.*;
  4. import java.applet.*;
  5.  
  6. ////////////////////////
  7. // Defines a Link class
  8. //
  9. // used by LinkedList
  10. ////////////////////////
  11. class Link
  12. {
  13.   private Object valueField;
  14.   private Link   nextLink;
  15.  
  16.   public Link (Object newValue, Link next)
  17.   {
  18.     valueField = newValue;
  19.     nextLink   = next;
  20.   }
  21.  
  22.   // get Object part of link
  23.   public Object value()
  24.   {
  25.     return valueField;
  26.   }
  27.  
  28.   // get Link part of link
  29.   public Link next()
  30.   {
  31.     return nextLink;
  32.   }
  33. }
  34.  
  35. //////////////////////////////
  36. // Defines a LinkedList class
  37. //
  38. // used by CardPile
  39. //////////////////////////////
  40. class LinkedList
  41. {
  42.   private Link firstLink;
  43.  
  44.   public LinkedList()
  45.   {
  46.     firstLink = null;
  47.   }
  48.  
  49.   // true if empty, false otherwise
  50.   public boolean empty()
  51.   {
  52.     return firstLink == null;
  53.   }
  54.  
  55.   // add an Object to our list
  56.   public void add (Object newValue)
  57.   {
  58.     firstLink = new Link(newValue, firstLink);
  59.   }
  60.  
  61.   // inspect front of list
  62.   public Object front()
  63.   {
  64.     if (firstLink == null)
  65.       return null;
  66.  
  67.     return firstLink.value();
  68.   }
  69.  
  70.   // pop front of list
  71.   public Object pop()
  72.   {
  73.     if (firstLink == null)
  74.       return null;
  75.  
  76.     Object result = firstLink.value();
  77.     firstLink = firstLink.next();
  78.     return result;
  79.   }
  80.  
  81.   // return an iterator for the list
  82.   public ListIterator iterator()
  83.   {
  84.     return new ListIterator(firstLink);
  85.   }
  86. }
  87.  
  88. ////////////////////////////////
  89. // Defines a ListIterator class
  90. //
  91. // used by LinkedList
  92. ////////////////////////////////
  93. class ListIterator
  94. {
  95.   private Link currentLink;
  96.  
  97.   public ListIterator (Link firstLink)
  98.   {
  99.     currentLink = firstLink;
  100.   }
  101.  
  102.   // true if we reached end of list, false otherwise
  103.   public boolean atEnd()
  104.   {
  105.     return currentLink == null;
  106.   }
  107.  
  108.   // move to next link
  109.   public void next()
  110.   {
  111.     if (currentLink != null)
  112.       currentLink = currentLink.next();
  113.   }
  114.  
  115.   // return value of current link
  116.   public Object current()
  117.   {
  118.     if (currentLink == null)
  119.       return null;
  120.  
  121.     return currentLink.value();
  122.   }
  123. }
  124.  
  125. ////////////////////////
  126. // Defines a Card class
  127. //
  128. // used by CardPile
  129. ////////////////////////
  130. class Card
  131. {
  132.   // data fields for colors and suits
  133.   final static int width   = 50;
  134.   final static int height  = 70;
  135.  
  136.   final static int red     = 0;
  137.   final static int black   = 1;
  138.  
  139.   final static int heart   = 0;
  140.   final static int spade   = 1;
  141.   final static int diamond = 2;
  142.   final static int club    = 3;
  143.  
  144.   final static int ace     = 0;
  145.   final static int king    = 12;
  146.  
  147.   private static String names[] = {"A", "2", "3", "4", "5", "6",
  148.                    "7", "8", "9", "10", "J", "Q", "K"};
  149.  
  150.   // data fields
  151.   private boolean faceup;
  152.   private int rank;
  153.   private int suit;
  154.  
  155.   // constructor
  156.   Card (int s, int r)
  157.   {
  158.     suit = s;
  159.     rank = r;
  160.     faceup = false;
  161.   }
  162.  
  163.   // get rank of card as an int in the interval [0, 12]
  164.   public int rank()
  165.   {
  166.     return rank;
  167.   }
  168.  
  169.   // get suit of card as an int in the interval [0, 3]
  170.   public int suit()
  171.   {
  172.     return suit;
  173.   }
  174.  
  175.   // true if card is face up, false otherwise
  176.   public boolean faceUp()
  177.   {
  178.     return faceup;
  179.   }
  180.  
  181.   // change value of faceup
  182.   public void flip()
  183.   {
  184.     faceup = ! faceup;
  185.   }
  186.  
  187.   // true if card is ace, false otherwise
  188.   public boolean isAce()
  189.   {
  190.     return rank == ace;
  191.   }
  192.  
  193.   // true if card is king, false otherwise
  194.   public boolean isKing()
  195.   {
  196.     return rank == king;
  197.   }
  198.  
  199.   // return color of card as an int in the range [0,1]
  200.   public int color()
  201.   {
  202.     if (suit() == heart || suit() == diamond)
  203.       return red;
  204.  
  205.     return black;
  206.   }
  207.  
  208.   // draw the card
  209.   public void draw (Graphics g, int x, int y) {
  210.     // clear rectangle, draw border
  211.     g.clearRect(x, y, width, height);
  212.     g.setColor(Color.black);
  213.     g.drawRect(x, y, width, height);
  214.  
  215.     // draw body of card
  216.     if (faceUp())
  217.       {
  218.     if (color() == red)
  219.       g.setColor(Color.red);
  220.     else
  221.       g.setColor(Color.black);
  222.  
  223.     g.drawString(names[rank()], x+3, y+15);
  224.  
  225.     if (suit() == heart)
  226.       {
  227.         g.drawLine(x+25, y+30, x+35, y+20);
  228.         g.drawLine(x+35, y+20, x+45, y+30);
  229.         g.drawLine(x+45, y+30, x+25, y+60);
  230.         g.drawLine(x+25, y+60, x+5, y+30);
  231.         g.drawLine(x+5, y+30, x+15, y+20);
  232.         g.drawLine(x+15, y+20, x+25, y+30);
  233.       }
  234.     else if (suit() == spade)
  235.       {
  236.         g.drawLine(x+25, y+20, x+40, y+50);
  237.         g.drawLine(x+40, y+50, x+10, y+50);
  238.         g.drawLine(x+10, y+50, x+25, y+20);
  239.         g.drawLine(x+23, y+45, x+20, y+60);
  240.         g.drawLine(x+20, y+60, x+30, y+60);
  241.         g.drawLine(x+30, y+60, x+27, y+45);
  242.       }
  243.     else if (suit() == diamond)
  244.       {
  245.         g.drawLine(x+25, y+20, x+40, y+40);
  246.         g.drawLine(x+40, y+40, x+25, y+60);
  247.         g.drawLine(x+25, y+60, x+10, y+40);
  248.         g.drawLine(x+10, y+40, x+25, y+20);
  249.       }
  250.     else if (suit() == club)
  251.       {
  252.         g.drawOval(x+20, y+25, 10, 10);
  253.         g.drawOval(x+25, y+35, 10, 10);
  254.         g.drawOval(x+15, y+35, 10, 10);
  255.         g.drawLine(x+23, y+45, x+20, y+55);
  256.         g.drawLine(x+20, y+55, x+30, y+55);
  257.         g.drawLine(x+30, y+55, x+27, y+45);
  258.       }
  259.       }
  260.     else // face down
  261.       {
  262.     g.setColor(Color.yellow);
  263.     g.drawLine(x+15, y+5, x+15, y+65);
  264.     g.drawLine(x+35, y+5, x+35, y+65);
  265.     g.drawLine(x+5, y+20, x+45, y+20);
  266.     g.drawLine(x+5, y+35, x+45, y+35);
  267.     g.drawLine(x+5, y+50, x+45, y+50);
  268.       }
  269.   }
  270. }
  271.  
  272. //////////////////////////////////////
  273. // Defines a CardPile class
  274. //
  275. // used as a base to build card piles
  276. //////////////////////////////////////
  277. class CardPile
  278. {
  279.   // coordinates of the card pile
  280.   protected int x;
  281.   protected int y;
  282.  
  283.   // linked list of cards
  284.   protected LinkedList cardList;
  285.  
  286.   CardPile (int xl, int yl)
  287.   {
  288.     x = xl;
  289.     y = yl;
  290.     cardList = new LinkedList();
  291.   }
  292.  
  293.   /////////////////////////////////////
  294.   // access to cards are not overridden
  295.  
  296.   // true if pile is empty, false otherwise
  297.   public final boolean empty()
  298.   {
  299.     return cardList.empty();
  300.   }
  301.  
  302.   // inspect card at the top of pile
  303.   public final Card top()
  304.   {
  305.     return (Card)cardList.front();
  306.   }
  307.  
  308.   // pop card at the top of pile
  309.   public final Card pop()
  310.   {
  311.     return (Card)cardList.pop();
  312.   }
  313.  
  314.   /////////////////////////////////////////
  315.   // the following are sometimes overridden
  316.  
  317.   // true if point falls inside pile, false otherwise
  318.   public boolean includes (int tx, int ty)
  319.   {
  320.     return x <= tx && tx <= x + Card.width &&
  321.            y <= ty && ty <= y + Card.height;
  322.   }
  323.        
  324.   // to be overridden by descendants
  325.   public void select (int tx, int ty)
  326.   {
  327.     // do nothing
  328.   }
  329.  
  330.   // add a card to pile
  331.   public void addCard (Card aCard)
  332.   {
  333.     cardList.add(aCard);
  334.   }
  335.  
  336.   // draw pile
  337.   public void display (Graphics g)
  338.   {
  339.     g.setColor(Color.black);
  340.  
  341.     if (cardList.empty())
  342.       g.drawRect(x, y, Card.width, Card.height);
  343.     else
  344.       top().draw(g, x, y);
  345.   }
  346.  
  347.   // to be overridden by descendants
  348.   public boolean canTake (Card aCard)
  349.   {
  350.     return false;
  351.   }
  352.  
  353.   // get number of cards in pile
  354.   public int getNoCards()
  355.   {
  356.     int count = 0;
  357.     ListIterator iterator = cardList.iterator();
  358.  
  359.     while (!iterator.atEnd())
  360.       {
  361.     count++;
  362.     iterator.next();
  363.       }
  364.  
  365.     return count;
  366.   }
  367. }
  368.  
  369. ////////////////////////////
  370. // Defines a DeckPile class
  371. ////////////////////////////
  372. class DeckPile extends CardPile
  373. {
  374.   DeckPile (int x, int y)
  375.   {
  376.     // first initialize parent
  377.     super(x, y);
  378.  
  379.     // then create the new deck
  380.     // first put them into a local pile
  381.     CardPile pileOne = new CardPile(0, 0);
  382.     CardPile pileTwo = new CardPile(0, 0);
  383.  
  384.     int count = 0;
  385.     for (int i = 0; i < 4; i++)
  386.       for (int j = 0; j <= 12; j++)
  387.     {
  388.       pileOne.addCard(new Card(i, j));
  389.       count++;
  390.     }
  391.  
  392.     // then pull them out randomly
  393.     for (; count > 0; count--)
  394.       {
  395.     int limit = ((int)(Math.random() * 1000)) % count;
  396.  
  397.     // move down to a random location in pileOne
  398.     // while poping the cards into pileTwo
  399.     for (int i = 0; i < limit; i++)
  400.       pileTwo.addCard(pileOne.pop());
  401.  
  402.     // then add the card found there
  403.     // to our LinkedList object: cardList
  404.     addCard(pileOne.pop());
  405.  
  406.     // now put back into pileOne the cards
  407.     // that we poped into pileTwo
  408.     while (!pileTwo.empty())
  409.       pileOne.addCard(pileTwo.pop());
  410.     }
  411.   }
  412.  
  413.   public void select(int tx, int ty)
  414.   {
  415.     // if deck becomes empty, refill from discard pile
  416.     if (empty())
  417.       {
  418.     while (!Solitaire.discardPile.empty())
  419.       {
  420.         addCard(Solitaire.discardPile.pop());
  421.         top().flip();
  422.       }
  423.       }
  424.     else
  425.       Solitaire.discardPile.addCard(pop());
  426.   }
  427. }
  428.  
  429. ///////////////////////////////
  430. // Defines a DiscardPile class
  431. ///////////////////////////////
  432. class DiscardPile extends CardPile
  433. {
  434.   DiscardPile (int x, int y)
  435.   {
  436.     super (x, y);
  437.   }
  438.  
  439.   public void addCard (Card aCard)
  440.   {
  441.     if (!aCard.faceUp())
  442.       aCard.flip();
  443.  
  444.     super.addCard(aCard);
  445.   }
  446.  
  447.   public void select (int tx, int ty)
  448.   {
  449.     if (empty())
  450.       return;
  451.            
  452.     Card topCard = top();
  453.  
  454.     // check the SuitPile's first
  455.     for (int i = 0; i < Solitaire.no_suit_piles; i++)
  456.       if (Solitaire.suitPile[i].canTake(topCard))
  457.     {
  458.       Solitaire.suitPile[i].addCard(pop());
  459.       return;
  460.     }
  461.  
  462.     // then check the TablePile's
  463.     for (int i = 0; i < Solitaire.no_table_piles; i++)
  464.       if (Solitaire.tableau[i].canTake(topCard))
  465.     {
  466.       Solitaire.tableau[i].addCard(pop());
  467.       return;
  468.     }
  469.   }
  470. }
  471.  
  472. ////////////////////////////
  473. // Defines a SuitPile class
  474. ////////////////////////////
  475. class SuitPile extends CardPile
  476. {
  477.   SuitPile (int x, int y)
  478.   {
  479.     super(x, y);
  480.   }
  481.  
  482.   public boolean canTake (Card aCard)
  483.   {
  484.     if (empty())
  485.       return aCard.isAce();
  486.  
  487.     Card topCard = top();
  488.     return (aCard.suit() == topCard.suit()) &&
  489.            (aCard.rank() == 1 + topCard.rank());
  490.   }
  491.  
  492.   public void select (int tx, int ty)  
  493.   {
  494.     if (empty())
  495.       return;
  496.  
  497.     Card topCard = top();
  498.  
  499.     // check the TablePile's
  500.     for (int i = 0; i < Solitaire.no_table_piles; i++)
  501.       if (Solitaire.tableau[i].canTake(topCard))
  502.     {
  503.       Solitaire.tableau[i].addCard(pop());
  504.       return;
  505.     }  
  506.   }
  507. }
  508.  
  509. /////////////////////////////
  510. // Defines a TablePile class
  511. /////////////////////////////
  512. class TablePile extends CardPile
  513. {
  514.   final static int ydist = 25;
  515.  
  516.   TablePile (int x, int y, int c)
  517.   {
  518.     // initialize the parent class
  519.     super(x, y);
  520.  
  521.     // then initialize our pile of cards
  522.     for (int i = 0; i < c; i++)
  523.       addCard(Solitaire.deckPile.pop());
  524.  
  525.     // flip topmost card face up
  526.     top().flip();
  527.   }
  528.  
  529.   public boolean canTake (Card aCard)
  530.   {
  531.     if (empty())
  532.       return aCard.isKing();
  533.  
  534.     Card topCard = top();
  535.  
  536.     // if our topmost card is face down
  537.     // we can't accept another card
  538.     if (!topCard.faceUp())
  539.       return false;
  540.  
  541.     return (aCard.color() != topCard.color()) &&
  542.            (aCard.rank() == topCard.rank() - 1);
  543.   }
  544.  
  545.   public boolean includes (int tx, int ty)
  546.   {
  547.     if (empty())
  548.       return false;
  549.  
  550.     // don't test bottom of card
  551.     return x <= tx && tx <= x + Card.width &&
  552.            y <= ty;
  553.   }
  554.  
  555.   public void select (int tx, int ty)
  556.   {
  557.     if (empty())
  558.       return;
  559.  
  560.     // if face down, then flip
  561.     Card topCard = top();
  562.     if (!topCard.faceUp())
  563.       {
  564.     topCard.flip();
  565.     return;
  566.       }
  567.  
  568.     // see if any suit pile can take card
  569.     for (int i = 0; i < Solitaire.no_suit_piles; i++)
  570.       if (Solitaire.suitPile[i].canTake(topCard))
  571.     {
  572.       Solitaire.suitPile[i].addCard(pop());
  573.       return;
  574.     }
  575.  
  576.     // try to create a build
  577.     CardPile build = new CardPile(0, 0);
  578.  
  579.     // get the cards for the build from the suit pile
  580.     while (!empty())
  581.       {
  582.     // stop if we reached a card that is face down
  583.     if (!top().faceUp())
  584.       break;
  585.  
  586.     build.addCard(pop());
  587.       }
  588.  
  589.     // We don't allow the user to play a King card
  590.     // that is at the bottom of a table pile
  591.     // to another table pile
  592.     if (build.top().isKing() && empty())
  593.       {
  594.     while (!build.empty())
  595.       addCard(build.pop());
  596.     return;
  597.       }    
  598.  
  599.     // if we have to play only one card
  600.     if (build.top() == topCard)
  601.       {
  602.     // put it back into the table pile
  603.     addCard(build.pop());
  604.  
  605.     // we have already tried the suit piles
  606.         // see if any other table pile can take card
  607.         for (int i = 0; i < Solitaire.no_table_piles; i++)
  608.           if (Solitaire.tableau[i].canTake(topCard))
  609.             {
  610.               Solitaire.tableau[i].addCard(pop());
  611.               return;
  612.             }
  613.       }
  614.     else // we got ourselves a build to play
  615.       {
  616.     topCard = build.top();
  617.  
  618.     // see if any other table pile can take this build
  619.     for (int i = 0; i < Solitaire.no_table_piles; i++)
  620.       if (Solitaire.tableau[i].canTake(topCard))
  621.         {
  622.           while (!build.empty())
  623.         Solitaire.tableau[i].addCard(build.pop());
  624.          
  625.           return;
  626.         }
  627.    
  628.     // can't play the build?
  629.     // then we must restore our pile
  630.     while (!build.empty())
  631.       addCard(build.pop());
  632.       }
  633.   }
  634.  
  635.   private void stackDisplay(Graphics g)
  636.   {
  637.     // holds y-coordinate of cards in pile
  638.     int localy = y;
  639.  
  640.     LinkedList reverseCardList = new LinkedList();
  641.  
  642.     // get iterator for our list
  643.     ListIterator iterator = cardList.iterator();
  644.  
  645.     // build reversed order list
  646.     while (!iterator.atEnd())
  647.       {
  648.     reverseCardList.add(iterator.current());
  649.     iterator.next();
  650.       }
  651.  
  652.     // get iterator for reversed order list
  653.     iterator = reverseCardList.iterator();
  654.  
  655.     // Go through the reversed order list
  656.     // and draw each card in the list
  657.     while (!iterator.atEnd())
  658.       {
  659.     ((Card)iterator.current()).draw(g, x, localy);
  660.     localy += ydist;
  661.     iterator.next();
  662.       }
  663.   }
  664.  
  665.   public void display (Graphics g)
  666.   {
  667.     stackDisplay(g);
  668.   }
  669. }
  670.  
  671. ///////////////////////////
  672. // Defines Solitaire class
  673. ///////////////////////////
  674. public class Solitaire extends Applet
  675. {
  676.   final static int no_card_piles  = 13;
  677.   final static int no_suit_piles  = 4;
  678.   final static int no_table_piles = 7;
  679.  
  680.   final static int topMargin      = 40;
  681.   final static int leftMargin     = 5;
  682.   final static int distTable      = 5;
  683.   final static int distSuit       = 10;
  684.  
  685.   static DeckPile deckPile;
  686.   static DiscardPile discardPile;
  687.   static TablePile tableau[];
  688.   static SuitPile suitPile[];
  689.   static CardPile allPiles[];
  690.  
  691.   protected void initialize()
  692.   {
  693.     // first allocate the arrays
  694.     allPiles = new CardPile[no_card_piles];
  695.     suitPile = new SuitPile[no_suit_piles];
  696.     tableau  = new TablePile[no_table_piles];
  697.  
  698.     // then fill them in
  699.     int xDeck = leftMargin + (no_table_piles - 1) * (Card.width + distTable);
  700.     allPiles[0] = deckPile = new DeckPile(xDeck, topMargin);
  701.     allPiles[1] = discardPile = new DiscardPile(xDeck - Card.width - distSuit,
  702.                         topMargin);
  703.  
  704.     for (int i = 0; i < no_suit_piles; i++)
  705.       allPiles[2+i] = suitPile[i] =
  706.     new SuitPile(leftMargin + (Card.width + distSuit) * i, topMargin);
  707.  
  708.     for (int i = 0; i < no_table_piles; i++)
  709.       allPiles[6+i] = tableau[i] =
  710.     new TablePile(leftMargin + (Card.width + distTable) * i,
  711.               Card.height + distTable + topMargin, i+1);
  712.  
  713.     showStatus("Welcome to Solitaire!");
  714.   }
  715.  
  716.   protected boolean gameEnded()
  717.   {
  718.     if (!deckPile.empty())
  719.       return false;
  720.  
  721.     if (!discardPile.empty())
  722.       return false;
  723.  
  724.     for (int i = 0; i < no_table_piles; i++)
  725.       if (!tableau[i].empty())
  726.     return false;
  727.  
  728.     // if we reached this point then all piles are empty
  729.     // notify the user in the status bar
  730.     showStatus("Congratulations! You have won this game.");
  731.  
  732.     return true;
  733.   }
  734.  
  735.   public void init()
  736.   {
  737.     // Create a new game button
  738.     Button b = new Button("New game");
  739.  
  740.     // Define, instantiate, and register a listener to handle button presses
  741.     b.addActionListener(new ActionListener() {
  742.       public void actionPerformed(ActionEvent e)
  743.     {  // start a new game
  744.       initialize();
  745.       repaint();
  746.     }
  747.     });
  748.  
  749.     // Add the button to the applet
  750.     add(b);
  751.  
  752.     // Define, instantiate and register a MouseListener object.
  753.     addMouseListener(new MouseAdapter() {
  754.       public void mouseClicked(MouseEvent e)
  755.     {
  756.       if (gameEnded())
  757.         return;
  758.      
  759.       showStatus("Neat click!");
  760.  
  761.       int x = e.getX();
  762.       int y = e.getY();
  763.  
  764.       for (int i = 0; i < no_card_piles; i++)
  765.         if (allPiles[i].includes(x, y))
  766.           {
  767.         allPiles[i].select(x, y);
  768.         repaint();
  769.           }
  770.     }
  771.     });
  772.  
  773.     initialize();
  774.   }
  775.  
  776.   public void paint(Graphics g)
  777.   {
  778.     for (int i = 0; i < no_card_piles; i++)
  779.       allPiles[i].display(g);
  780.   }
  781. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement