Разделение написанного кода на два класса (JAVA)

#java

#java

Вопрос:

Я пишу игру в крестики-нолики для своей Java, пока у меня это плохо получается, но я научился работать с примерами, которые он дал нам на занятиях. Проблема, с которой я сталкиваюсь сейчас, заключается в том, что я понял, что нам нужно иметь по крайней мере ДВА класса для этой программы. Я понятия не имею, что он имеет в виду под этим или как я преобразовываю код, который я уже собрал вместе, в «Два класса». Из инструкций похоже, что он хочет, чтобы доска была в одном классе, а игра — в другом.

Есть ли способ разделить это на два класса без полного переписывания всего этого?

 /* Standard applet template
*/

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


public class TicTacToeGame implements ActionListener {
    /*Instance Variables*/
    private JFrame window = new JFrame("Tic-Tac-Toe Game");
    private JButton btn1 = new JButton("");
    private JButton btn2 = new JButton("");
    private JButton btn3 = new JButton("");
    private JButton btn4 = new JButton("");
    private JButton btn5 = new JButton("");
    private JButton btn6 = new JButton("");
    private JButton btn7 = new JButton("");
    private JButton btn8 = new JButton("");
    private JButton btn9 = new JButton("");
    private JLabel lblTitle = new JLabel("Tic Tac Toe Game");
    private JLabel lblBlank = new JLabel(" ");
    private String letter = "";
    private int count = 0;
    private boolean win = false;

    public TicTacToeGame(){
    /*Create Window*/
    window.setSize(400,300);
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    window.setLayout(new GridLayout(3,3));

    /*Add Buttons To The Window*/
    window.add(btn1);
    window.add(btn2);
    window.add(btn3);
    window.add(btn4);
    window.add(btn5);
    window.add(btn6);
    window.add(btn7);
    window.add(btn8);
    window.add(btn9);

    /*Add The Action Listener To The Buttons*/
    btn1.addActionListener(this);
    btn2.addActionListener(this);
    btn3.addActionListener(this);
    btn4.addActionListener(this);
    btn5.addActionListener(this);
    btn6.addActionListener(this);
    btn7.addActionListener(this);
    btn8.addActionListener(this);
    btn9.addActionListener(this);

    /*Make The Window Visible*/
    window.setVisible(true);
    }

    public void actionPerformed(ActionEvent a) {
        count  ;

        /*Calculate Who's Turn It Is*/
        if(count == 1 || count == 3 || count == 5 || count == 7 || count == 9){
        letter = "<HTML><font color=blue>X</font></HTML>";
        } else if(count == 2 || count == 4 || count == 6 || count == 8 || count == 10){
        letter = "<HTML><font color=red>O</font></HTML>";
        }

        /*Display X's or O's on the buttons*/
        if(a.getSource() == btn1){
            btn1.setText(letter);
            btn1.setEnabled(false);
        } else if(a.getSource() == btn2){
            btn2.setText(letter);
            btn2.setEnabled(false);
        } else if(a.getSource() == btn3){
            btn3.setText(letter);
            btn3.setEnabled(false);
        } else if(a.getSource() == btn4){
            btn4.setText(letter);
            btn4.setEnabled(false);
        } else if(a.getSource() == btn5){
            btn5.setText(letter);
            btn5.setEnabled(false);
        } else if(a.getSource() == btn6){
            btn6.setText(letter);
            btn6.setEnabled(false);
        } else if(a.getSource() == btn7){
            btn7.setText(letter);
            btn7.setEnabled(false);
        } else if(a.getSource() == btn8){
            btn8.setText(letter);
            btn8.setEnabled(false);
        } else if(a.getSource() == btn9){
            btn9.setText(letter);
            btn9.setEnabled(false);
        }

        /*Checks to See Who Won*/
        //horizontal win
        if( btn1.getText() == btn2.getText() amp;amp; btn2.getText() == btn3.getText() amp;amp; btn1.getText() != ""){
            win = true;
        }
        else if(btn4.getText() == btn5.getText() amp;amp; btn5.getText() == btn6.getText() amp;amp; btn4.getText() != ""){
            win = true;
        }
        else if(btn7.getText() == btn8.getText() amp;amp; btn8.getText() == btn9.getText() amp;amp; btn7.getText() != ""){
            win = true;
        }

        //virticle win
        else if(btn1.getText() == btn4.getText() amp;amp; btn4.getText() == btn7.getText() amp;amp; btn1.getText() != ""){
            win = true;
        }
        else if(btn2.getText() == btn5.getText() amp;amp; btn5.getText() == btn8.getText() amp;amp; btn2.getText() != ""){
            win = true;
        }
        else if(btn3.getText() == btn6.getText() amp;amp; btn6.getText() == btn9.getText() amp;amp; btn3.getText() != ""){
            win = true;
        }

        //diagonal wins
        else if(btn1.getText() == btn5.getText() amp;amp; btn5.getText() == btn9.getText() amp;amp; btn1.getText() != ""){
            win = true;
        }
        else if(btn3.getText() == btn5.getText() amp;amp; btn5.getText() == btn7.getText() amp;amp; btn3.getText() != ""){
            win = true;
        }
        else {
            win = false;
        }

        /*Show a dialog if someone wins or the game is tie*/
        if(win == true){
            JOptionPane.showMessageDialog(null, letter   " WINS!");
        } else if(count == 9 amp;amp; win == false){
            JOptionPane.showMessageDialog(null, "Tie Game!");
        }
    }

    public static void main(String[] args){
        new TicTacToeGame();
    }
}
  

Комментарии:

1. Вы собираетесь мне помочь или нет?

2. вы должны пометить это как домашнее задание, если это так (что я очень подозреваю). Это не означает, что вы не получите никакой помощи.

3. «хочет, чтобы у нас было по крайней мере ДВА класса для этой программы». Именно что заставило вас осознать это? Как уже отмечалось, существует множество способов разделить код на большее количество классов, но не мы ставим отметки за ваше домашнее задание .

Ответ №1:

Существует несколько способов разделить этот класс, но поскольку он не очень большой, большинство из них в конечном итоге перепишут большую его часть.

Самым чистым способом было бы разделить логику и пользовательский интерфейс на (по крайней мере) два отдельных класса:

  • Класс TicTacToeGame реализовал бы логику: у него есть метод для запроса, чья очередь, несколько методов для запроса состояния игрового поля, метод для ввода следующего хода, метод для запроса состояния игры (игра, окончание), метод для запроса, кто выиграл и, вероятно, способ регистрации некоторых слушателей
  • Класс TicTacToeUI просто берет информацию экземпляра другого класса и отображает ее. Он также вызывает соответствующие методы при нажатии одной кнопки.

Конечным результатом, вероятно, будет больше кода (поскольку для взаимодействия между двумя классами потребуется некоторый код), но код будет намного чище, и игровой класс можно будет тестировать независимо от пользовательского интерфейса.

Комментарии:

1. Также вы могли бы создать отдельный класс, представляющий состояние игры. Тогда вы получите что-то вроде этого: java.sun.com/blueprints/patterns/images /… .

2. Я бы расширил JComponent и создал TicTacToeComponent, который вы добавляете в JFrame, TicTacToeUI 🙂 TicTacToeComponent будет считывать состояние TicTacToe всякий раз, когда ему нужно выполнить рендеринг.

Ответ №2:

Простая вещь, которую вы можете сделать, это создать второй класс, который реализует ActionListener, а затем использовать этот класс для прослушивания всех событий action в вашей программе. Это не тот способ, который вы хотите, это один для доски и один для игры, но это может быть один для работы и один для презентации.

Ответ №3:

Иоахим дал хороший ответ. Я просто хочу добавить это вместо того, чтобы делать это:

 /*Display X's or O's on the buttons*/
if(a.getSource() == btn1){
  btn1.setText(letter);
  btn1.setEnabled(false);
...
} else if(a.getSource() == btn9){
  btn9.setText(letter);
  btn9.setEnabled(false);
}
  

Вы можете сделать это:

 JButton btn = (JButton) a.getSource();
btn.setText(letter);
btn.setEnabled(false);
  

Ответ №4:

Я думаю, что ваши комментарии — хороший намек на логическое разделение. Поместите каждый раздел в отдельный метод, чтобы ваш actionPerformed метод был чем-то вроде следующего.

 public void actionPerformed(ActionEvent a) {
    count  ;
    letter = calculateCurrentPlayer(count);
    displayLetterOnButton(a.getSource());
    win = checkForWin();
    displayGameOver(win, count);
}
  

Каждый из методов, вызываемых из actionPerformed , тогда будет иметь небольшую строго определенную единицу работы для выполнения. Эти методы в значительной степени могут быть скопированы и вставлены из разделов вашего текущего actionsPerformed метода.