Juego de memoria para niños (Código Fuente)

Creado por jc mouse Martes, octubre 20, 2015

En un post anterior, desarrollamos un swing para simular un efecto FLIP  y recibí algunos mensajes pidiéndome un ejemplo de como usarlo. Cuando creamos un swing personalizado estos tienen casi las mismas propiedades que el resto de swing conocidos, esto se debe a que la mayoría de los componentes descienden de JComponent. Claro esta que también tienen sus propios métodos, por tanto se usan como cualquier otro swing.

Para mostrar el uso de ese componente FLIP, desarrollamos un sencillo juego de memoria. Este tipo de juegos sirve para desarrollar la memoria de los niños y niñas de una forma divertida, que es jugando 🙂 si señor profesor de mi infancia perdida, también se aprende jugando 😉

Sin más preámbulo describiremos a continuación el proyecto en cuestión:

La estructura del juego de memoria es la siguiente:

game java

En el paquete org.bolivia.game se encuentra un JFrame (GameFrame) que es la interfaz del juego compuesto por un JPanel y un JButton.

Tenemos también a la clase JFlipButton que es nuestro componente con el efecto flip con unas pequeñas modificaciones del original.

En el paquete org.bolivia.game.resources se encuentran las imágenes que se usan en el proyecto. En este caso son 10 imágenes de 100×100 pixeles en formato JPG

Clase JFlipButton

package org.bolivia.game;
import java.awt.BasicStroke;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.GeneralPath;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.Timer;
/**
 * @web http://www.jc-mouse.net/
 * @author Mouse
 */
public class JFlipButton extends JComponent implements MouseListener {
    
    private Timer timer                     =       null;    
    private boolean inTransition            =       false;
    private int speed                       =       4;//velocidad de flip en milisegundos
    private int displacement                =       2;//desplazamiento en pixeles
    public boolean isFront                  =       true;
    private boolean inward                  =       true;//sentido del desplazamiento
    //iconos por defecto
    private Icon iconBack                   =       new ImageIcon(getClass().getResource("/org/bolivia/game/resources/moe.jpg"));
    private Icon iconFront                  =       new ImageIcon(getClass().getResource("/org/bolivia/game/resources/cover.jpg"));
    private Image image                     =       ((ImageIcon)iconFront).getImage();
    //variables de desplazamiento
    private int displacementHorizontal      =       0;    
    private float displacementLeft          =       0;       
    private float displacementRight         =       0;    
    //tamaño por defecto
    private Dimension dimension             =       new Dimension(100,100);
    //
    private String nameCharacter            =       "";
    private int index                       =       -1;
    
    
    /**Constructor de clase*/
    public JFlipButton(){
        super();
        setSize(dimension);
        setPreferredSize(dimension);        
        setVisible(true);        
        setCursor(new Cursor(Cursor.HAND_CURSOR));
        addMouseListener(JFlipButton.this);        
    }
    
    @Override
    public void paintComponent(Graphics g){         
        Graphics2D g2 =(Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);            
        g2.setStroke(new BasicStroke( 1f ));
        //coordenas de imagen
        GeneralPath p = new GeneralPath();
            p.moveTo(displacementHorizontal, displacementLeft);//esquina A
            p.lineTo(getWidth()-displacementHorizontal, displacementRight);//esquina B
            p.lineTo(getWidth()-displacementHorizontal, getHeight()-displacementRight);//esquina D
            p.lineTo( displacementHorizontal, getHeight()-displacementLeft  );//esquina C
            p.closePath();
        Shape shp = p;
        g2.setClip(shp);
        g2.drawImage(image, 0, 0,getWidth() - displacementHorizontal,getHeight(), null);        
        g2.setClip(null);
        g2.draw(shp);
        g.dispose(); 
    }

    /**
     * Metodo que realiza los cambios en las variables de desplazamiento
     * @return Void
     */
    public void flipAnimate(){
        inTransition = !inTransition;
        //declaramos un evento para modificar el desplazamiento vertical y horizontal
        ActionListener animation = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                
                if(inward){   
                    displacementHorizontal += displacement;   
                    displacementRight += (displacementRight>=getHeight()/2)?0:displacement/(getSize().getWidth()/getSize().getHeight()+1f);                                        
                }else{
                    displacementHorizontal -= displacement;                                        
                    displacementLeft -=displacement/(getSize().getWidth()/getSize().getHeight()+1f);                                        
                }
                //repinta graficos
                repaint();
                
                //si se llego al medio del componente -> cambia de sentido
                if(displacementHorizontal >= getWidth()/2){ 
                    inward = false;
                    displacementLeft = displacementRight;                    
                    displacementRight=0;                    
                    //
                    if( isFront ){//mostrar imagen de atras
                        isFront=false;
                        image=((ImageIcon)iconBack).getImage();                            
                    }else{//mostrar imagen de adelante
                        isFront =true;                        
                        image=((ImageIcon)iconFront).getImage();                        
                    }                    
                } 
                //volvio a su posicion inicial -> detener animacion
                if( inward == false && displacementHorizontal == 0 ){
                    inTransition=false;   
                    timer.stop();
                    displacementLeft=0;
                    displacementRight=0;
                    displacementHorizontal=0;
                    inward = true;                                 
                }
            }
        }; 
        //
        if( inTransition )
        {
            if(timer != null)timer.stop();
            timer = new Timer( speed, animation);
            timer.start(); //inicia animacion      
        }
    }
    
    public void cancel(){
        if(timer != null)timer.stop();
        inTransition=false;           
    }
    
    @Override
    public void mouseClicked(MouseEvent e) {
        flipAnimate();
    }

    @Override
    public void mousePressed(MouseEvent e) {/*...*/}

    @Override
    public void mouseReleased(MouseEvent e) {/*...*/}

    @Override
    public void mouseEntered(MouseEvent e) {/*...*/}

    @Override
    public void mouseExited(MouseEvent e) {/*...*/}

    public Icon getIconBack() {
        return iconBack;
    }

    public void setIconBack(Icon iconBack) {
        this.iconBack = iconBack;
    }

    public Icon getIconFront() {
        return iconFront;
    }

    public void setIconFront(Icon iconFront) {
        this.iconFront = iconFront;
    }

    public int getDisplacement() {
        return displacement;
    }

    public void setDisplacement(int displacement) {
        this.displacement = displacement;
    }

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    public String getNameCharacter() {
        return nameCharacter;
    }

    public void setNameCharacter(String nameCharacter) {
        this.nameCharacter = nameCharacter;
        iconBack = new ImageIcon(getClass().getResource("/org/bolivia/game/resources/"+ this.nameCharacter +".jpg"));
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }
    
}

La lógica del juego se controlo desde la clase GameFrame

public class GameFrame extends javax.swing.JFrame {

    private List<String> characters = new LinkedList<String>();
    private Character character1 = new Character();
    private Character character2 = new Character();
    private int hits = 0;
    
    /**
     * Creates new form GameFrame
     */
    public GameFrame() {
        initComponents();       
        
        setTitle("Game Memory [http://www.jc-mouse.net/]");
        setLocationRelativeTo(null);
        
        //layout
        jPanel1.setLayout(new GridLayout(4, 4));
        
        //se añaden las figuras al panel
        for(int i=0;i<16;i++){
            jPanel1.add( new JFlipButton() );    
        }
        
        //se crea nuevo juego
        newGame();
        
        //se añade eventos para cada casilla
        for(int i=0;i<16;i++){
            
            final JFlipButton button = (JFlipButton) jPanel1.getComponent(i);
            
            button.addMouseListener( new MouseListener(){

                @Override
                public void mouseClicked(MouseEvent e) {                    
                    /* --------- controla el juego en si -------- */
                    if( button.isFront ){//si imagen esta tapada
                    
                        if( character1.isEmpty() ){
                            character1.setKey( button.getIndex() );
                            character1.setName( button.getNameCharacter() );                        
                        }else if( character2.isEmpty() ){
                            character2.setKey( button.getIndex() );
                            character2.setName( button.getNameCharacter() );     
                            
                            //si figuras de ambas casillas son iguales
                            if(character1.getName().equals( character2.getName() ) ){
                                character1.setKey( -1 );
                                character1.setName( "" ); 
                                character2.setKey( -1 );
                                character2.setName( "" ); 
                                hits +=1; 
                                //completo el juego?
                                if(hits==8){//si
                                    JOptionPane.showMessageDialog(null, "--------------------------- YOU WIN!!! ---------------------------", "Atención", JOptionPane.INFORMATION_MESSAGE);
                                }
                            }else{//no son iguales
                                //se comienza un hilo que espera X tiempo hasta que la casilla de completamente la vuelta
                                new Thread(){
                                    @Override
                                    public void run()
                                    {
                                        try {
                                            Thread.sleep(500);
                                        } catch (InterruptedException ex) {}   
                                        //oculta figuras
                                        ((JFlipButton) jPanel1.getComponent(character1.getKey())).flipAnimate();
                                        ((JFlipButton) jPanel1.getComponent(character2.getKey())).flipAnimate();
                                        character1.setKey( -1 );
                                        character1.setName( "" ); 
                                        character2.setKey( -1 );
                                        character2.setName( "" ); 
                                    }                            
                                }.start();
                            }
                        }     

                    }else{                       
                       button.cancel();//se cancela animacion
                    }
                    
                }

                @Override
                public void mousePressed(MouseEvent e) {/* nada q ver circulando jovenes... */}

                @Override
                public void mouseReleased(MouseEvent e) {/* nada q ver circulando jovenes... */}

                @Override
                public void mouseEntered(MouseEvent e) {/* nada q ver circulando jovenes... */}

                @Override
                public void mouseExited(MouseEvent e) {/* nada q ver circulando jovenes... */}
                
            });
        }
        //
    }
 
    
    /**
     * Nuevo juegos
     */
    private void newGame(){
        characters.clear();
        
        //personajes
        characters.add("castulo");
        characters.add("bart");
        characters.add("homero");
        characters.add("lionel");
        characters.add("lisa");
        characters.add("maggie");
        characters.add("marge");
        characters.add("ned");
        
        characters.add("castulo");
        characters.add("bart");
        characters.add("homero");
        characters.add("lionel");
        characters.add("lisa");
        characters.add("maggie");
        characters.add("marge");
        characters.add("ned");
                
        //asigna los personajes a cada casilla
        for(int i=0;i<16;i++){
            ((JFlipButton) jPanel1.getComponent(i)).setNameCharacter(getCharacter());
            ((JFlipButton) jPanel1.getComponent(i)).setIndex(i);               

            if( !((JFlipButton) jPanel1.getComponent(i)).isFront )
                ((JFlipButton) jPanel1.getComponent(i)).flipAnimate();
        }
        //reinicia variables
        character1 = new Character();
        character2 = new Character();
        hits=0;
    }
    
    /**
     * desordena lista y retorna un personaje
     * @return String Nombre del personaje
     */
    private String getCharacter(){        
        Collections.shuffle(characters);
        return characters.remove(0);        
    }
    
    /**
     * clase privada para manejar las 2 figuras que deben ser comparadas
     */
    private class Character{
        
        private int key=-1;
        private String name="";        

        public int getKey() {
            return key;
        }

        public void setKey(int key) {
            this.key = key;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }    
        
        public boolean isEmpty(){
            if(key==-1 && name.equals(""))
               return true;
            else 
               return false;
        }
        
    }

Todo el proyecto se encuentra comentado hasta más no poder, cualquiera con un conocimiento intermedio de java podrá entenderlo, sino, abajo están los comentarios que responderé con gusto.

simpsons java

En el siguiente video un demo del juego en funcionamiento

Descarga el código desde este enlace pobre

enjoy!!!

Si te ha gustado podrías compartirlo o dejar un comentario. ¡Muchas gracias!

Sobre el autor y el sitio web

Yo soy yo :) Mouse o como algunos de ustedes me llaman 'El Cochinote', Soy orgullosamente boliviano soy fundador y CEO de la web jc-Mouse.net uno de las pocas web en emprendimiento y tecnología en Bolivia.

Toda la información que encuentres en este sitio es y sera completamente gratis siempre, puedes copiar, descargar y re-publicar si así lo deseas en otros blogs o sitios web, solo te pido a cambio que dejes una referencia a esta web. Esto nos ayuda a crecer y seguir aportando. Bye

Enjoy! :)

ENTRADAS QUE TE PUEDEN INTERESAR

1 comentario en “Juego de memoria para niños (Código Fuente)”

  1. Maria jose dice:

    tengo un proyecto en la universidad pero en vez de pares son trios debo hacerlo atraves de matrices y arreglos . lo unico es que el profe nos mostro como deberia funcionar el codigo y no lo hizo con Jframes . el cuando le daba run al codigo iba designando cooredenadas y asi por decirlo de alguna manera volteaba las cartas de esa manera. Me podrias explicar como hacerlo es para el curso de programacion basica . Utilizo java en netbeans

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *


*

Comparte lo que sabes

Categorias

Android Bolivia

Bandera en Alto

Ultimas entradas

En este oportunidad comparto una pequeña aplicación hecha en java para recortar partes de una imagen seleccionado con el...

En este post crearemos un componente que solo hay en android y que no esta disponible en la paleta de controles de Netbe...

Radio.Garden es un proyecto interactivo desarrollado por el Instituto Holandés para el Sonido y la Visión en cooperación...

Una cola doblemente terminada o deque es una estructura de datos lineal que permite insertar y eliminar elementos por am...

Web amigas