Solitaire Card Game Source Code


Watching my older source code files I found out a solitaire card game version I made in the year 2007 using java.


How does it works??
The aplication is composed by four class:

  •   Carta (Card) Using the own java orientation OOP, it couldn't be other way, every card is an object and this class has the work to define a card's properties and methods. Properties of each card are: color, number, group (spades, clovers, hearts and diamonds). The methods, as every card is an image this class is a graphic control to show the card as a card, for this the class inherits from java.awt.Canvas and overloading the paint metod the respective image is displayed.
  •  

  • Pila (Stack)  Watching the game area shapes I decided to use stacks for every cards set or group, so the card columns on the center, the reserve stack (on the top-left corner) and the four sets ordered, which have every card in his own and final place (on the top right corner); each of them are a stack. The properties in this class are made to define what kind of stack is: if we can add more cards, keep in mind the reserve set can not add another cards; how the cards will be sorted, ascendig or descendig due to is a playing set (center area) or an ordered set (top-right corner). The methods, adoptaCarta() [equivalent to push] and sacaCarta() [equivalent to pop]. For have a right stack behavior the class inherits from java.util.stack
  •  
  • Area de juego (playing area) This class is the area where the stacks are placed to play and where the cards are dragged when playing, when I programm it I was worried about the drag efect and about the cards can be shown overlaped. The java containers work with layouts and these (until I knew at that moment) handles just fixed positions and not option for overlap objets. I considered to use a container with not layout (layout = null) and directly codify drag methods and overlaping methods, but it could had been very hard and a remarkable time spendig. For a luck, googling I found the JLayeredPane, which, how the API says "...append profundity to the Swing containers, letting components overlap each others when needed..." Some like the CSS z-index, and that was so perfect for what I was needing. As every stack handles its own objets and coordinates this class just works as containerand the only implemented methods are paint() [to draw the stacks] and actualiza() [to update when a card changes from a stack to another one].
  •  
  • Solitario Finally this class is the aplication window, the window contains the playing area and a little menu. The class inherits from javax.swing.JFrame and in adition of being container it handles the movements, the drag of a card, for this I implemented the interfaces MouseMotionListener and MouseListener. The more outstanding methods are repartir() [distribute the cards when starting a new game], arrastra() [takes the drag of a card on the playing area] and haGanado() [looks after every movement if every card has been placed right in his site, and therefore, the game ends]
For the images I used jpg files which are placed on a folder called mazo, there are thirteen images in every set and there are four sets, besides the back-side card image. The mazo folder must be in the same path where the aplication is running, every image file was called on this way, paloN_V.jpg where N is a value due to the set [palo], so 1=hearts, 2=clovers, 3=diamonds and 4=spades; V is the card value from 1 to 10 and I put 11, 12 and 13 to the J, Q and K cards respectively.

The previous is of use for the program can load the respective images when distributing cards at starting a new game, every card objet is created and due to its value the respective image is called using the settings described on the previous paragraph.

Here are some source code portions, you can download it complete, compiled and ready to play from: http://mygnet.net/codigos/java/juegos/juego_del_solitario.3487
public class Carta extends Canvas{

  public int palo; // valores 1, 2, 3 y 4
  public int color; // valores 1=rojo, 2=negro
  public int num; // valores del 1 al 13
  public boolean esReverso; // indica si la carta esta volteada o de reverso
  private Image imgCarta; // imagen de la carta
  private Image imgReverso; // imagen del reverso de la carta
  public Carta cartaHija; // indica una carta colocada bajo esta (this) en la
    // fila de cartas del juego (si la hay)
  public int esqX; // coordenada x superior donde se ubica la carta
  public int esqY; // coordenada y izquierda donde se ubica la carta
  public int mouseX; // coordenada x donde se encuentra el mouse (cuando el mouse esta sobre la carta)
  public int mouseY; // coordenada y donde se encuentra el mouse (cuando el mouse esta sobre la carta)
  public int enPila; // indica donde se encuentra la carta 1=repartidor esq sup der, 2=espacio
    // muestra, 3a6=posiciones finales, 7a13=pilas de la segunda fila
  public boolean arrastrandoHijas;
  
  // constructor

  public void paint(Graphics g){
    setSize(75,98);
    if(esReverso){
      g.drawImage(imgReverso,0,0,75,98,this);
      return;
    }
    g.drawImage(imgCarta,1,1,73,96,this);
    g.setColor(Color.BLACK);
    if(arrastrandoHijas){
     // acciones para gestionar el arrastre de cartas hijas
    }
    g.drawRect(0,0,74,97);
  }
}
Porción del código fuente de la clase Pila
// Atributos y constuctor

public boolean adoptaCarta(Carta cd){
    int xC = cd.getLocation().x;
    int yC = cd.getLocation().y;
    Carta tm=(size()<=0?null:peek());
    if(xC+75<esqX || xC>esqX+75 || yC+98<esqY || yC>esqY+98+((size()-1)*margenSup)
      || !adopta || (tm==null?false:tm.esReverso))
      return false;
    if(modoAdopcion==1){
      if(tm==null && cd.num!=1)
        return false;
      else if(tm==null && cd.num==1){
        adoptaYa(cd);
        return true;
      }
      if(tm.palo!=cd.palo || tm.num!=(cd.num-1) || cd.cartaHija!=null)
        return false;
      adoptaYa(cd);
    }
    else{
      if(tm==null && cd.num!=13)
        return false;
      else if(tm==null && cd.num==13){
       adoptaYa(cd);
       return true;
      }
      if(tm.num!=(cd.num+1) || tm.color==cd.color)
        return false;
      tm.cartaHija=cd;
      adoptaYa(cd);
    }
    return true;
}
Porción del código fuente de la clase Area de juego
public class AreaDeJuego extends JLayeredPane{

  public void paint(Graphics g){
    g.setColor(new Color(119,184,255,90));
    g.fillRect(45,25,75,98);
    // area de muestra en 130,25
    g.setColor(new Color(119,184,255,200));
    g.fillRect(305,30,75,98);
    g.fillRect(405,30,75,98);
    g.fillRect(505,30,75,98);
    g.fillRect(605,30,75,98);
    g.setColor(new Color(119,184,255,20));
    g.fillRect(100,140,75,98);
    g.fillRect(185,140,75,98);
    g.fillRect(270,140,75,98);
    g.fillRect(355,140,75,98);
    g.fillRect(440,140,75,98);
    g.fillRect(525,140,75,98);
    g.fillRect(610,140,75,98);
  }

  public void actualiza(Carta cd, int pila){ // si pila=-1 dejar la misma pila que tenga
    cd.enPila=(pila==-1?cd.enPila:pila);
    cd.setLocation(cd.esqX,cd.esqY);
    cd.arrastrandoHijas=false;
    cd.setVisible(true);
    cd.repaint();
    moveToFront(cd);
    if(cd.cartaHija!=null)
      actualiza(cd.cartaHija,pila);
    validate();
  }
}
Porción del código fuente de la clase Solitario
// atributos y constructor

  // otros metodos

  private void haGanado(){
    Carta tmp1=(pila[2].size()==0?null:pila[2].peek());
    Carta tmp2=(pila[3].size()==0?null:pila[3].peek());
    Carta tmp3=(pila[4].size()==0?null:pila[4].peek());
    Carta tmp4=(pila[5].size()==0?null:pila[5].peek());
    if(tmp1==null || tmp2==null || tmp3==null || tmp4==null) return;
    if(tmp1.num==13 && tmp2.num==13 && tmp3.num==13 && tmp4.num==13){
      mensaje.setText("Has terminado el juego");
      info.pack();
      info.setVisible(true);
    }

Comentarios

Entradas populares