Tic-tac-toe - Implement logic

Asked

Viewed 4,619 times

2

Good people, my final work of the semester is to assemble a game of old in java, I did all the look of it, but the problem comes here: I need to make every mouse click it changes the icon of the buttons (first click an X, second click an O), and that when it repeats horizontally, vertical or diagonal, a Joptionpane appears with the message "you won" or the name of the winner, something like... how to do these actions ? I’m not succeeding, could anyone help ? Here’s the code:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Jogo extends JFrame{
    private JButton b1,b2,b3,b4,b5,b6,b7,b8,b9;
    private JLabel l1;
    private Dimension dim;
    private Font f;

        public Jogo(){
            dim = new Dimension (90,90);
            setTitle("Jogo da Velha");
            setBounds(300,160,400,450);
            setResizable(false);
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            getContentPane().setBackground(new Color (197,197,197));
            setLayout(null);

            f = new Font("Tahoma",Font.ITALIC,17);
            setFont(f);

            JMenuBar mbar = new JMenuBar();
            JMenu opcoes = new JMenu("Opções");
            JMenu sair = new JMenu("Sair");

            JMenuItem sMim = new JMenuItem("Sobre mim");
            JMenuItem sprogram = new JMenuItem("Sobre o Programa");

            opcoes.add(sMim);
            opcoes.add(sprogram);

            mbar.add(opcoes);
            mbar.add(sair);

            setJMenuBar(mbar);

            l1 = new JLabel();
            l1.setText("Gabriel Ozzy Santos");
            l1.setBounds(130,10,200,30);
            l1.setFont(f);
            this.add(l1);

                b1 = new JButton();
                b1.setSize(dim);
                b1.setLocation(30,50);
                this.add(b1);

                b2 = new JButton();
                b2.setSize(dim);
                b2.setLocation(150,50);
                this.add(b2);

                b3 = new JButton();
                b3.setSize(dim);
                b3.setLocation(270,50);
                this.add(b3);

                b4 = new JButton();
                b4.setSize(dim);
                b4.setLocation(30,170);
                this.add(b4);

                b5 = new JButton();
                b5.setSize(dim);
                b5.setLocation(150,170);
                this.add(b5);

                b6 = new JButton();
                b6.setSize(dim);
                b6.setLocation(270,170);
                this.add(b6);

                b7 = new JButton();
                b7.setSize(dim);
                b7.setLocation(30,290);
                this.add(b7);

                b8 = new JButton();
                b8.setSize(dim);
                b8.setLocation(150,290);
                this.add(b8);

                b9 = new JButton();
                b9.setSize(dim);
                b9.setLocation(270,290);
                this.add(b9);
        }
        public static void main (String [] args){
            new Jogo().setVisible(true);
        }
}

2 answers

6

since it is a school work, there is no more opportune time to learn.

Some suggestions regarding your code:

1. Separation of Reponsabilities

I’ve noticed that there’s still no business logic in your code, which is a good sign. I understand that there is a natural will to put the business code mixed with the vision, but avoid it at all costs.

In other words, you must assemble the logic of the old game outside the Game class. Assemble a class called Old Game and include the attributes and methods necessary for an old game to happen from start to finish. Once you have the class ready and tested, then yes you will worry about the vision.

Separating the business vision is something of paramount importance. Basically, it can be said that it is one of the pillars that underpin the really great software that is made today. Within this context, study the MVC (Model-Controller-Vision) standard, because it is something designed exactly to separate these responsibilities.

Always think about responsibilities. What is the role of your old Jogodavelha class? Do you agree that this class should simply control the instance of a particular game? In other words, this class doesn’t care if the game is played by the Web, the Desktop or even the Console. It doesn’t matter to them. In fact, she’s not even "knowing" where she’s being played.

2. Vision

I’m not getting into the controller’s merit here, let’s go straight to the vision to make it easier for you to understand how everything connects.

In the Game class above, one of the attributes will be of the type of your Old Game class. You must instantiate this object and work with it in each event generated by its buttons. Working with it means calling methods and changing their state (changing the value of attributes) as the game takes place.

In order for you to take action when the user clicks a button, you must implement an Actionlistener. Basically, it’s the most common way to do an event handler. It is an event because it is triggered by an extenuating entity, in which case your user will click on the button and this will generate an event.

Example:

b1 = new JButton();
b1.setSize(dim);
b1.setLocation(30,50);
this.add(b1);
b1.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
       System.out.println("You clicked the button");
    });

The above code, although verbose, is not difficult to understand. What is being done is to add an Actionlistener to the list of Actionlisteners on the B1 button. Thus, when the button is clicked, it will notify the objects that are in this list, calling, for each one, the actionPerformed method.

See an example with two Actionlisteners:

    b1 = new JButton();
    b1.setSize(dim);
    b1.setLocation(30,50);
    this.add(b1);
    b1.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("OI");
        }
    });

    b1.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("OI2");
        }
    });

So, when you click, the two actionPerformed above will run.

Note that the Actionlistener type objects created are anonymous. Anonyms, because the object does not have a variable from which you can refer it in the "outside world".

In the above case, we are just printing a message on the console. For the tic-tac-toe, the idea is to do two things: Change the state of your tic-tac-toe and check if the game is over. Changing the state means marking on the internal game data structure that a certain cell has been marked with X or O.

Of course at the time of implementing difficulties will appear and you can take another path, but the idea of separating responsibilities should always be your biggest concern.

  • Right, I could understand but I had two difficulties ! To create the other class, I know the logic of the Game of Old perfectly, however, I can not in any way make the game understand that, if for example the "X" repeats 3 times horizontally or diagonally, ends the game... And also I can’t get every click the buttons to have a different actionlistener (a click from player X, and a click from player O).

  • @Gabriel, have you created the data structure to store the marked values? A matrix[3][3] would be the most basic structure. You could even make a String matrix that would start with the null positions and could receive X or O. Once that’s done, you make algorithms that go through this matrix by checking if in any row, column or diagonal there are 3 X or 3 O. But like every computation problem, There are many ways to solve. This is the one I think you can develop more quickly.

  • I’ve faced this "problem" too :) What I ended up doing is how @Cantoni did -- that is, create an array (a multi-dimentional array). The detail is that instead of X or O, each member of the array was worth certain points. Then when X cliquou in the top left corner, for example, he got points. I did it in a way that, at the end, I got the points and then I knew who won.

  • It turns out I made a solution with math, but there are several other solutions.

1

On the button: In Click Event you check the text. If the text is "" set it "X", if it is "X" set it to "O", if it is "O" set it to "". Several if or a switch solve this.

About the win: With each finished move you check all the buttons, checking their content and seeing if each of the winning possibilities is met. And then display the message. For this, you can check in the button text or use variables that are also set in the backend to control this data.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.