Aprende Java Aprende Php Aprende C++ Aprende HTML 5 Aprende JavaScript Aprende JSON Aprende MySQL Aprende SQLServer Aprende Visual Basic 6 Aprende PostgreSQL Aprende SQLite Aprende Redis Aprende Kotlin Aprende XML Aprende Linux VSC Aprende Wordpress Aprende Laravel Aprende VueJS Aprende JQuery Aprende Bootstrap Aprende Netbeans Aprende Android
Sigueme en Facebook Sigueme en Twitter Sigueme en Instagram Sigueme en Youtube Sigueme en TikTok Sigueme en Whatsapp
Home / Java / Juego de memoria para niños (Código Fuente)

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

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 https://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 [https://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!!!

Tags

Artículos similares

Generador de códigos QR (Quick Response)

En este tutorial aprenderemos a crear nuestra propia aplicación java para generar códigos QR. ¿Que es un Código QR? «Un[...]

Obtener Metadatos de un ResultSet

En este post mostramos un ejemplo de uso de la interface ResultSetMetaData el cual se extiende Wrapper que es una interf[...]

Actualizar JComboBox al cambiar valor de otro JComboBox

Cuando se trabaja con base de datos, estos datos son dinámicos, cambian con el tiempo y es necesario que esos cambios se[...]

Introducción a SQLite

Android hace uso de la base de datos SQLite para el manejo de registros en las aplicaciones. Según Santa Wikipedia defin[...]

Ejecutar función de postgreSQL desde Java

Este es una continuación de un tutorial pasado [Funciones en PostgreSQL y pgAdmin], así que si quieres entenderlo mucho[...]

Como capturar cambios del Slider en JavaFX

En este tutorial veremos como usar el componente Slider de JavaFX , capturas los cambios que realice el usuario y con es[...]