Jogo da Memória em Java

Neste post irei publicar os fontes de um jogo que fiz há um tempo atrás, quando ainda estava na faculdade.

Este jogo foi um pequeno desafio pessoal que me propus quando comecei a aprender Java e que depois acabou virando um trabalho de sala.

Na faculdade havíamos feito um jogo da memória em C, para console.Nesta época eu estava começando a aprender Java, e estava encantado com a possibilidade de criar interfaces gráficas sem a necessidade de uma IDE. Por esta razão, nenhuma IDE será necessária para criar este jogo.

Na ocasião eu utilizei o JCreator como editor de código, mas você poderá digitar as classes no bloco de notas e compilar no console se preferir, funciona também 😉

Basicamente é um jogo que utiliza pacotes do core de Java, e não é necessária a utilização de nenhuma biblioteca adicional às já encontradas na JRE para seu funcionamento.

São quatro classes e algumas imagens, que você deverá dispor da seguinte forma:

– Jogador.java
– MyButton.java
– TelaUm.java
– TelaJogo.java
– – imagens (diretório)
– – – duke (diretório)
– – – tux (diretório)
– – – jogo (diretório)

As imagens usadas, mais especificamente dos diretórios tux e duke, foram encontradas na internet. As demais, do diretório jogo, foram encontradas também na internet, e algumas são montagens que fiz.

Cada diretório de imagem, com exceção do diretório “jogo”, representam os possíveis jogos presentes para se escolher. Quando eu fiz esse jogo pela primeira vez, ele tinha 20 diretórios, ou seja, era possível escolher vários desenhos diferentes para os jogos.

Bom, depois de tanto falar, vamos aos fontes. Uma vez criados os arquivos .java citados acima, copie os conteúdos das classes abaixo para seus devidos arquivos:

Jogador.java


public class Jogador{

    private String nome;
    private int pontos;

    public Jogador(String nomeJogador){

        nome = (nomeJogador.equals("")? "Jogador sem nome...coitado! ": nomeJogador );
        pontos = 0;
    }

    public String obterNome(){

        return nome;
    }

    public int obterPontos(){

        return pontos;
    }

    public void incrementarPontos(){

        pontos += 5;
    }

    public void decrementarPontos(){

        pontos--;
    }

} // fim da classe pessoa

MyButton.java


import javax.swing.*;

public class MyButton extends JButton{

    private Icon imagemPadrao;
    private Icon imagemBotao;

    public MyButton(Icon imagemPadrao, Icon imagemBotao){

        super();

        this.imagemBotao = imagemBotao;
        this.imagemPadrao = imagemPadrao;

        setImagemPadrao();
    }

    public void setImagemPadrao(){

        this.setIcon(imagemPadrao);
    }

    public void setImagemBotao(){

        this.setIcon(imagemBotao);
    }    

    public Icon getImagemBotao(){

        return this.imagemBotao;
    }
}

TelaUm.java


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class TelaUm extends JFrame implements ActionListener, ItemListener{    

    private Container container;
    private JButton botaoSair, botaoIniciarJogo;
    private JPanel painelBotoes, painelDados, painelCabecalho;
    private JPanel painelCentro, painelRodape, painelImagem;
    private Icon imagemPainel, imagemRodape, imagemJogar, titulo;
    private Icon imagemJogarRoll, imagemSair, imagemSairRoll;
    private JLabel labelImagemPainel, nomeJogador, temaJogada;
    private JLabel texto1, desenvolvimento, autor;
    private GridLayout gridBotoes, gridDados, gridCabecalho, gridRodape;
    private JComboBox temasJogada;
    private int indiceTema = 1;
    private Jogador objJogador;
    private TelaJogo objTelaJogo;
    private JTextField fieldNomeJogador;
    private Font fonte18, fonte10;
    private JTextArea telaSaida = new JTextArea();
    private boolean jogoFacil = false;
    private ButtonGroup dificuldadeGroup;
    private JMenu menuDificuldade;
    private JMenuBar barraMenu;
    private JRadioButtonMenuItem facil, dificil;
    private JLabel nivelDificuldade;

    String nomeObjJogador;

    // os temas para os jogos
    private String nomesTemas[] =
    { "Duke", "Tux"};    

    // índices dos temas para os jogos
    private int indiceTemas[] =
    { 1, 2 };    

    public TelaUm(){                   

        super( "Bem-vindo ao Jogo da Memória!" );                

        // adiciona um listener à janela
        addWindowListener(            

            // classe interna anônima
            new WindowAdapter(){

                // trata o evento de quando o usuário fecha a janela
                public void windowClosing( WindowEvent windowEvent ){

                    saidaPrograma();
                }
            }// fim da classe interna anônima    

        );

        nivelDificuldade = new JLabel("Nível de dificuldade: DIFÍCIL");
        nivelDificuldade.setForeground(Color.red);

        // gerenciadores de layout
        gridBotoes = new GridLayout( 1, 2, 5, 5 );
        gridDados = new GridLayout( 6, 1, 10, 10 );
        gridCabecalho = new GridLayout( 1, 1, 10, 10 );
        gridRodape = new GridLayout( 1, 1, 10, 10 );

        // painel da imagem (esquerda)
        imagemPainel = new ImageIcon(getClass().getResource("/imagens/jogo/painel.gif"));
        labelImagemPainel = new JLabel( imagemPainel );
        painelImagem = new JPanel();
        painelImagem.add( labelImagemPainel );
        painelImagem.setBackground( Color.white );

        fonte10 = new Font( "Verdana", Font.ITALIC, 10 );

        // imagens dos botões
        imagemJogar = new ImageIcon(getClass().getResource("/imagens/jogo/jogar.gif"));
        imagemJogarRoll = new ImageIcon(getClass().getResource("/imagens/jogo/jogarRoll.gif")); // imagem Rollover
        imagemSair = new ImageIcon(getClass().getResource("/imagens/jogo/sair.gif"));
        imagemSairRoll = new ImageIcon(getClass().getResource("/imagens/jogo/sairRoll.gif")); // imagem Rollover        

        // botão Iniciar Jogo
        botaoIniciarJogo = new JButton( "Iniciar Jogo", imagemJogar );
        botaoIniciarJogo.setRolloverIcon( imagemJogarRoll );
        botaoIniciarJogo.addActionListener( this );
        botaoIniciarJogo.setSize( 250, 15 );
        botaoIniciarJogo.setHorizontalAlignment( SwingConstants.LEFT );

        // botão Sair
        botaoSair = new JButton( "Abandonar o Jogo", imagemSair );
        botaoSair.setRolloverIcon( imagemSairRoll );
        botaoSair.addActionListener( this );
        botaoSair.setSize( 250, 15 );
        botaoSair.setHorizontalAlignment( SwingConstants.RIGHT );
        botaoSair.setHorizontalTextPosition( SwingConstants.LEFT );

        // painel de botões (inferior)
        painelBotoes = new JPanel();
        painelBotoes.setBackground( Color.lightGray );
        painelBotoes.setLayout( gridBotoes );
        painelBotoes.add( botaoSair );
        painelBotoes.add( botaoIniciarJogo );        

        //cabeçalho
        titulo = new ImageIcon(getClass().getResource("/imagens/jogo/titulo.gif"));
        texto1 = new JLabel( titulo );
        texto1.setHorizontalAlignment( SwingConstants.CENTER );        

        // painel de cabeçalho
        painelCabecalho = new JPanel();
        painelCabecalho.setLayout( gridCabecalho );
        painelCabecalho.setBackground( Color.lightGray );
        painelCabecalho.add( texto1 );

        // label do nome do jogador
        nomeJogador = new JLabel("Informe seu nome:");
        nomeJogador.setHorizontalAlignment( SwingConstants.LEFT );

        // campo do nome do jogador
        fieldNomeJogador = new JTextField( 15 );
        fieldNomeJogador.setHorizontalAlignment( SwingConstants.LEFT );

        // label do tema da jogada
        temaJogada = new JLabel( "Escolha o tema:" );
        temaJogada.setHorizontalAlignment( SwingConstants.LEFT );

        // ComboBox do tema da jogada
        temasJogada = new JComboBox( nomesTemas );
        temasJogada.addItemListener( this );
        temasJogada.setMaximumRowCount( 4 );

        // configuração do painel central
        painelCentro = new JPanel();
        painelCentro.setLayout( gridDados );
        painelCentro.setBackground( Color.lightGray );
        painelCentro.add( temaJogada );
        painelCentro.add( temasJogada );
        painelCentro.add( nomeJogador );
        painelCentro.add( fieldNomeJogador );
        //painelCentro.add( som );
        painelCentro.add(nivelDificuldade);

        menuDificuldade = new JMenu("Nível de Dificuldade");
        menuDificuldade.setBackground( Color.lightGray );

        dificuldadeGroup = new ButtonGroup();

        dificil = new JRadioButtonMenuItem("Difícil (6X6)");
        dificil.setSelected(true);

        dificil.addActionListener(new ActionListener(){

            public void actionPerformed(ActionEvent evt){
                jogoFacil = false;
                nivelDificuldade.setText("Nível de dificuldade: DIFÍCIL");
                nivelDificuldade.setForeground(Color.red);
            }
        });

        facil = new JRadioButtonMenuItem("Fácil (4X4)");

        facil.addActionListener(new ActionListener(){

            public void actionPerformed(ActionEvent evt){
                jogoFacil = true;
                nivelDificuldade.setText("Nível de dificuldade: FÁCIL");
                nivelDificuldade.setForeground(Color.blue);
            }
        });

        dificuldadeGroup.add(dificil);
        dificuldadeGroup.add(facil);

        menuDificuldade.add(dificil);
        menuDificuldade.add(facil);

        barraMenu = new JMenuBar();
        setJMenuBar(barraMenu);
        barraMenu.setBackground( Color.lightGray );

        barraMenu.add(menuDificuldade);        

        // imagem do rodapé
        imagemRodape = new ImageIcon(getClass().getResource("/imagens/jogo/java.gif"));

        // texto do rodapé
        desenvolvimento = new JLabel(
        "Desenvolvido em Java",
        imagemRodape, SwingConstants.CENTER );
        desenvolvimento.setFont( fonte10 );        

        // configuração do painel de rodapé
        painelRodape = new JPanel();
        painelRodape.setLayout( gridRodape );
        painelRodape.setBackground( Color.white );
        painelRodape.add( desenvolvimento );        

        // configuração do painel de dados (que possui o painel de cabeçalho,
        // o painel central e o painel de botões
        painelDados = new JPanel();
        painelDados.setLayout( new BorderLayout( 10, 10 ));
        painelDados.setBackground( Color.lightGray );
        painelDados.add( painelCabecalho, BorderLayout.NORTH);
        painelDados.add( painelCentro );
        painelDados.add( painelBotoes, BorderLayout.SOUTH );        

        // configuração do container (que tem toda essa bagunça aí!!! =)
        container = getContentPane();
        container.setLayout( new BorderLayout( 5, 5 ) );
        container.setBackground( Color.lightGray );
        container.add( painelRodape, BorderLayout.SOUTH );
        container.add( painelImagem, BorderLayout.WEST );
        container.add( painelDados );        

        setSize( 550, 380 );
        setVisible( true );
        setResizable( false );

    }

    private void saidaPrograma(){

        telaSaida.setText(

            "tJogo da Memória - 2005nn"+
            "tDesenvolvido por: Luiz Gustavo Stábile de Souzan"+
            "tGraduando em Análise de Sistemas pela "+
            "Faculdade de Ciências e Tecnologia de Birigui  n"+
            "tContato: luizgustavoss@gmail.comnn"+
            "tLinguagem de Desenvolvimento: Java (TM) 2 Standard Edition nn"+
            "tRequisitos: J2RE - Java(TM) 2 Runtime Environmentnn"+
            "tEste jogo foi desenvolvido com fins educacionais, portanto sem nenhum tipo de garantia.nn"

        );

        JOptionPane.showMessageDialog(null, telaSaida,
        "Informações sobre o Jogo", JOptionPane.PLAIN_MESSAGE);
        System.exit( 0 );
    }

    public void actionPerformed( ActionEvent event ){

            // se o evento for do botão sair
            if ( event.getSource() == botaoSair ){

                saidaPrograma();

            }

            // senão é do botão iniciar jogo
            else if ( event.getSource() == botaoIniciarJogo ){                

                nomeObjJogador = fieldNomeJogador.getText();
                objJogador = new Jogador( nomeObjJogador );

                if(jogoFacil)
                    objTelaJogo = new TelaJogo( objJogador, indiceTema, 4 );
                else
                    objTelaJogo = new TelaJogo( objJogador, indiceTema, 6 );
            }
    }

    public void itemStateChanged( ItemEvent event ){

        if ( event.getSource() == temasJogada ){

            if ( event.getStateChange() == ItemEvent.SELECTED )

                indiceTema = indiceTemas[ temasJogada.getSelectedIndex() ];
        }
    }

    public static void main( String args[] ){

        TelaUm application = new TelaUm();

        application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        application.setLocationRelativeTo( null );
    }

} // fim da classe TelaUm

TelaJogo.java


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class TelaJogo extends JFrame implements ActionListener{

    /**
     * Construtor da classe
     * @Param jog - Objeto jogador, com os dados do jogador
     * @Param codJog - O tema escolhido
     * @Param fatorJogo - Inteiro que determina se o jogo é 4X4 ou 6X6
     */    

         //ClassLoader cl = this.getClass().getClassLoader();
         public TelaJogo( Jogador jog, int codJog, int fatorJogo ){        

        super( "Jogo da Memória" );    

        setLocation( 200, 10 );            

        addWindowListener(new WindowAdapter(){

                public void windowClosing( WindowEvent windowEvent ){

                    mostrarResumoJogo();
                }
        });        

        fator = fatorJogo;

        objJogadorJogada = jog;
        temaJogada( codJog );
        preparaArrayImagens();
        container = getContentPane();

        labelPontosJogador = new JLabel( "Jogador: " + objJogadorJogada.obterNome() + " >> Pontos: " );

        pontosJogador = new JLabel( ""+objJogadorJogada.obterPontos() );

        imagemSair = new ImageIcon(getClass().getResource("/imagens/jogo/sair.gif"));
        imagemSairRoll = new ImageIcon(getClass().getResource("/imagens/jogo/sairRoll.gif"));        

        // configura o botão sair
        botaoSair = new JButton(" Sair do Jogo ", imagemSair);
        botaoSair.setRolloverIcon( imagemSairRoll );
        botaoSair.addActionListener( this );        

        painelImagens = new JPanel();
        painelPontos = new JPanel();        

        // configurando o painel superior
        painelPontos.setBackground( Color.white );
        painelPontos.add( labelPontosJogador );
        painelPontos.add( pontosJogador );        

        grid = new GridLayout( fator, fator, 5, 5 );

        painelImagens.setLayout( grid );                

        imagemPadrao = new ImageIcon(getClass().getResource("/imagens/jogo/standard.gif"));

        posicoesFiguras = new MyButton[( fator * fator )];                

        for ( int cont = 0; cont < ( fator * fator ); cont++ ){

            posicoesFiguras[ cont ] = new MyButton(imagemPadrao, imagens[cont]);
            posicoesFiguras[ cont ].addActionListener( this );
            painelImagens.add( posicoesFiguras[ cont ] );
        }

        container.add( painelPontos, BorderLayout.NORTH);
        container.add( botaoSair, BorderLayout.SOUTH );
        container.add( painelImagens );

        double d_largura = (fator == 4?82.5:80);

        d_largura *= fator;

        int i_largura = (int) d_largura;

        setSize( i_largura, i_largura+70 );
        setVisible( true );
        setResizable( false );
    }

    /**
     * Prepara o Array de Imagens
     *
     */
    private void preparaArrayImagens(){

        int posicaoNoArray, x, y;

        this.imagens8 = new Icon[(fator * fator)/2];

        for ( x = 0; x < ((fator*fator)/2); x++ ){

            this.imagens8[ x ] = new ImageIcon(getClass().getResource(tema + ( x + 1 ) + ".GIF"));
        }

        this.imagens = new Icon[ (fator*fator) ];

        for ( x = 0; x < 2; x++ ){

            for ( y = 0; y < ((fator*fator)/2); y++ ){

                do{
                    posicaoNoArray = ( int ) ( Math.random() * (fator*fator) );        

                }while( this.imagens[ posicaoNoArray ] != null );

                this.imagens[ posicaoNoArray ] = imagens8[ y ];

            }
        }
    }

    /**
     * Descobre o tema escolhido
     * @Param codTema - Código do tema escolhido
     */
    private void temaJogada( int codTema ){

        switch( codTema ){

                case 1: this.tema = "/imagens/duke/";
            break;

            case 2: this.tema = "/imagens/tux/";
            break;

        }
    } 

    /**
     * Mostra o resumo do jogo ao sair
     *
     */
    private void mostrarResumoJogo(){

        resumoJogo = "Jogador: " + objJogadorJogada.obterNome() + "nn" +
        "Pontos: " + objJogadorJogada.obterPontos() + "nn" +
        "Quantidade de tentativas: " + qtdeTentativas;

        JOptionPane.showMessageDialog( null, ""+resumoJogo, "Resumo do Jogo",
        JOptionPane.INFORMATION_MESSAGE ); 

        setVisible( false );
        System.gc();
    }

    public void actionPerformed( ActionEvent event ){        

        // Se o evento for do botão Sair...
        if ( event.getSource() == botaoSair ){

            mostrarResumoJogo();
        }

        // Caso contrário é evento de botões de imagem
        else{

            // testa se é o primeiro clique
            if( primeiroClique ){

                qtdeTentativas++; 

                // testa se o jogador errou na jogada anterior
                if ( !acertou ){

                    botaoUm = (MyButton) botaoClicadoUm;
                    botaoDois = (MyButton) botaoClicadoDois;

                    botaoUm.setImagemPadrao();
                    botaoDois.setImagemPadrao();
                }

                botaoClicadoUm = event.getSource();

                botaoUm = (MyButton) botaoClicadoUm;
                botaoUm.setImagemBotao();                

                // indica que este foi o primeiro clique
                primeiroClique = !primeiroClique;
            }

            // se não for o primeiro clique
            else{                

                botaoClicadoDois = event.getSource();
                botaoDois = (MyButton) botaoClicadoDois;                                

                // verifica se o jogador clicou no mesmo botão
                if ( botaoClicadoDois == botaoClicadoUm ){

                    acertou = false;

                    JOptionPane.showMessageDialog( null, "Ação não permitida!",
                    "Ação Não Permitida", JOptionPane.WARNING_MESSAGE );
                }

                // se não for o mesmo botão...
                else{            

                    // coloca a imagem no botão
                    botaoDois.setImagemBotao();

                    // compara com o primeiro botão clicado
                    if ( botaoUm.getImagemBotao().equals( botaoDois.getImagemBotao())){

                        acertou = true;
                        qtdeAcerto++;                            

                        // Desabilita os botões
                        botaoUm.setEnabled( false );
                        botaoDois.setEnabled( false );                            

                        // incrementar pontos
                        objJogadorJogada.incrementarPontos();

                        pontosJogador.setText( ""+objJogadorJogada.obterPontos() );                            

                        // se foi o último par encontrado, apresenta resumo do jogo e fecha a janela
                        if ( qtdeAcerto == ((fator*fator)/2) ){

                            mostrarResumoJogo();
                            setVisible( false );
                            System.gc();
                        }
                    }

                    // se não for o mesmo botão
                    else{

                        acertou = false;                            

                        //decrementar pontos
                        objJogadorJogada.decrementarPontos();

                        pontosJogador.setText( ""+objJogadorJogada.obterPontos() );
                    }                    

                    // indica que este foi o segundo clique
                    primeiroClique = !primeiroClique;
                }
            }
        }
    } 

    private Object botaoClicadoUm = new Object();
    private Object botaoClicadoDois = new Object();
    private JLabel pontosJogador, labelPontosJogador;
    private JPanel painelImagens, painelPontos;
    private JButton botaoSair;
    private Icon imagemSair, imagemSairRoll, imagens[], imagemPadrao, imagens8[];
    private GridLayout grid;
    private Container container;
    private String tema, resumoJogo = "";
    private Jogador objJogadorJogada;
    private int fator, qtdeAcerto, qtdeTentativas = 0;
    private boolean primeiroClique = true;
    private boolean acertou = true;
    private MyButton botaoUm, botaoDois, posicoesFiguras[];    

} // fim TelaJogo

Os arquivos de imagem necessários estarão disponíveis para download ao final do post.

Não vou explicar o jogo passo-a-passo (ahhhhhhh) mas se você está começando a aprender Java, esse pequeno jogo é uma boa oportunidade para aprender a usar componentes de tela básicos, assim como aprender a usar tratamento de eventos desses componentes.

Depois de compiladas as classes (com o comando javac [nome-da-classe.java], pelo console), basta executar a classe TelaUm.java (java TelaUm, pelo console).

Jogo em execução

Jogo em execução

Imagens para o Jogo

Queria colocar todas as imagens compactadas para download, mas não é possível (até onde eu sei). Portanto, colocarei aqui as imagens referentes a cada diretório. No caso das imagens dos diretórios “tux” e “duke”, que eram muitas, eu dei um printscreen na tela e postarei uma imagem só, com todas (separadas, uma única imagem para o diretório “tux” e uma única imagem para o diretório “duke”). Vocês terão o trabalho de recortar cada uma, no tamanho de 70×70 pixels. Aproveitem para renomear cada uma de acordo com o que se vê nas imagens.

No caso das imagens do jogo (imagens de tela, botões…), por apresentarem tamanhos diversos optei por colocar uma a uma. Vamos a elas:

(importante 1: clique sobre as imagens para que elas sejam abertas no tamanho original, para só depois salvarem as mesmas)

Imagens do diretório “duke”

imagens-duke

Imagens do diretório “tux”

imagens-tux

Imagens do diretório “jogo”

titulo standard sairroll sair painel jogarroll jogar java

Se tiverem dúvidas, fique à vontade para postar comentários!