Código del solitario

[- English -]

Revisando mis archivos me encontre una version del juego de cartas Solitario, esto lo hice en el 2007 usando java.



¿Cómo funciona?
El programa está dividido en cuatro clases:

  •   Carta Usando la orientación POO propia de java no podía ser de otra forma, cada carta es un objeto y esta clase se encarga de definir sus propiedades y metodos. Lo principal de cada carta son sus atributos: color, numero, palo (picas, treboles, corazones y diamantes). En segunda los metodos, ya que cada carta es en sí una imagen esta clase es un control grafico para mostrar la carta como tal, para esto la clase hereda de java.awt.Canvas y sobrecargando el metodo paint hago que se carge la imagen que corresponda. 
  •  
  • Pila Observando la conformación del area de juego decidí utilizar pilas para los conjuntos o grupos de cartas, así las filas de cartas de la parte inferior, la pila de reserva (en la esquina superior izquierda) y los cuatro grupos de cartas acomodadas o 'subidas' (parte superior derecha) son cada una, una pila. Los atributos de esta clase son para definir que tipo de pila es: si se le puede agregar cartas (adoptar), recordemos que en el caso el grupo de reserva no se puede; como se van a ordenar las cartas, creciente o decreciente segun si es grupo en juego (parte de abajo) o grupo de subidas (parte de arriba). Y los metodos adoptaCarta() [equivalente a push] y sacaCarta() [equivalente a pop]. Para un correcto comportamiento de pila la clase hereda de java.util.stack
  •  
  • Area de juego Esta clase es el área donde se colocan las pilas y donde se arrastran las cartas, al programarlo me preocupaba lo del arrastre y que unas cartas se mostrasen encimadas. Los contenedores de java se manejan por layouts y estos (hasta donde sabía en ese momento) manejan posiciones fijas y sin opción de encimar objetos. Llegue a pensar en manejar el contenedor con un layout = null y codificar directamente metodos de arrastre y componentes encimados, pero hubiera sido complejo y un considerable gasto de tiempo. Por suerte googleando me encontre que existe el JLayeredPane, el cual, como dice la API, "...agrega profundidad a los contenedores de Swing, permitiendo a los componentes sobreponerse unos a otros cuando es necesario..." Algo así como el z-index de CSS, y esto fue perfecto para lo que necesitaba. Como cada pila maneja sus propios objetos y coordenadas esta clase solo la hace de contenedor y sus unicos metodos son el paint() [para dibujar las posiciones de las pilas] y actualiza() [cuando una carta cambia de una pila a otra]. 
  •  
  • Solitario Finalmente esta clase es la ventana de la aplicación, la ventana contiene el area de juego y un pequeño menu de opciones. La clase hereda de javax.swing.JFrame y ademas de ser contenedor gestiona los movimientos, es decir el arrastre y movimientos de las cartas, para esto implemente las interfaces MouseMotionListener y MouseListener. Los metodos más relevantes son repartir() [reparte las cartas al iniciar un nuevo juego], arrastra() [gestiona el arrastre de una carta por el area de juego] y haGanado() [revisa despues de cada movimiento si todas las cartas han sido subidas, y por lo tanto, termina el juego]
Para las imagenes utilice imagenes jpg todas puesta en una carpeta llamada mazo, son trece imagenes por cada palo y cuatro palos, además de la imagen de reverso. La carpeta mazo debe estar en la misma ubicacion en que se ejecuta el programa, cada archivo de imagen fue llamado de la siguiente forma, paloN_V.jpg donde N es un valor segun el palo, así 1=corazones, 2=treboles, 3=diamantes y 4=picas; V es e valor de la carta que van desde 1 hasta 10 y asigne el 11, 12 y 13 a las cartas J, Q y K respectivamente.

Lo anterior sirve para que el programa cargue las imagenes respectivas, al momento de repartir las cartas, se crea cada objeto carta y segun el valor de esa carta llama a la imagen respectiva usando la configuración descrita en el parrafo anterior.

Aca muestro porciones del codigo fuente, lo puedes decscargar completo, compilado y listo para jugar desde aca: 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

  1. excelente tu aporte... pero puedes ayudarnos con ek codigo fuente,,, en el enlace solo esta el compilado...

    ResponderBorrar
  2. Sochmal: De hecho sí va todo incluido, cuando descargas el archivo descomprime hasta obtener el ejecutable, el .jar, abre el ejecutable.jar con winrar y ahi dentro estan los archivos .java con el código fuente.
    Saludos.

    ResponderBorrar

Publicar un comentario

Entradas populares