Я делаю игру Tic-Tac-Toe на Java. У меня четыре класса: TicTacTester просто вызывает (создает объект) класс TicTacToe. Класс TicTacToe предоставляет графический интерфейс игры (это подкласс JFrame). Он также создает 9 кнопок для отображения в JPanel и для нажатия пользователями. Класс XOButton определяет, что могут делать кнопки, и метод actionPerformed. Наконец, класс GameEnd определяет, что происходит, когда игра заканчивается (создается новый JFrame для отображения счета и предоставления пользователю двух кнопок: выхода и перезапуска).
Проблема в том, что когда я пытаюсь закодировать содержимое того, что происходит, когда пользователь нажимает «перезагрузка». Предполагается вызвать метод resetBoard(), который определен в классе TicTacToe. Проблема в том, что я не знаю имени объекта, созданного из класса TicTacToe (в методе static void main класса тестера я просто набрал «новый TicTacToe», не нужно было определять имя). Я не могу вызвать resetBoard со статической точки зрения (т.е. я не могу сделать TicTacToe.resetBoard(); ), потому что resetBoard должен быть нестатическим.
Что я пробовал: Я попытался включить в конструктор класса GameEnd объект TicTacToe. Если я это сделаю, создатель объекта GameEnd должен перейти в класс TicTacToe, поэтому я могу использовать ключевое слово this. Это не работает, потому что объект GameEnd необходимо создать при выполнении условия WinCondition, которое проверяется при нажатии кнопки в классе XOButton.
Но если я поместил создатель объекта GameEnd в класс XOButton (где он находится сейчас и, якобы, там, где он должен быть), в конструкторе для GameEnd(String s, TicTacToe a), я не могу использовать ключевое слово this для Объект Крестики-нолики.
Это мой класс кнопок. Большая часть кода не актуальна, поэтому она скрыта.
public class XOButton extends JButton implements ActionListener {
//Hidden code
private void winCheck() {
for(int j = 0; j < 3; j++) {
if (board[j][0] == 1 && board[j][1] == 1 && board[j][2] == 1 || board[0][j] == 1 && board[1][j] == 1 && board[2][j] == 1) {
player1Score++;
GameEnd end = new GameEnd("X wins this round!");
finished = true;
break;
}
else if (board[j][0] == 2 && board[j][1] == 2 && board[j][2] == 2 || board[0][j] == 2 && board[1][j] == 2 && board[2][j] == 2) {
player2Score++;
GameEnd end = new GameEnd("O wins this round!");
finished = true;
break;
}
}
if (board[0][0] == 1 && board[1][1] == 1 && board[2][2] == 1 || board[0][2] == 1 && board[1][1] == 1 && board[2][0] == 1) {
player1Score++;
GameEnd end = new GameEnd("X wins this round!");
finished = true;
}
else if (board[0][0] == 2 && board[1][1] == 2 && board[2][2] == 2 || board[0][2] == 2 && board[1][1] == 2 && board[2][0] == 2) {
player2Score++;
GameEnd end = new GameEnd("O wins this round!");
finished = true;
}
if (turn == 9 && !finished) {
GameEnd end = new GameEnd("This round is a Draw");
finished = true;
}
}
public void resetButton() {
this.setIcon(null);
markSpot(0);
this.clicked = false;
}
public static void resetStatics() {
turn = 0;
finished = false;
}
}
Это класс TicTacToe. Большая часть кода не актуальна, поэтому она скрыта.
public class TicTacToe extends JFrame {
//Hidden code
public void resetBoard() {
for(int j = 0; j < 3; j++) {
for(int i = 0; i < 3; i++) {
buttons[j][i].resetButton();
}
}
XOButton.resetStatics();
}
}
Это класс GameEnd. Объект этого создается при выполнении условия WinCondition. Большая часть кода не актуальна, поэтому она скрыта.
public class GameEnd extends JFrame implements ActionListener {
//Hidden code
public void actionPerformed(ActionEvent e) {
if (e.getSource() == exit) {
System.exit(0);
}
else if (e.getSource() == retry) {
TicTacToe.resetBoard();
}
}
}
//This is the Tester class
public class TicTacTester {
public static void main(String[] args) {
new TicTacToe();
}
}
Я ожидаю, что произойдет перезапуск игрового поля.
.. frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
6) GameEnd
Сомневаюсь, что это вообще должен быть класс. Вместо того, чтобы называть это, покажите соответствующий JOptionPane
.
@AndrewThompson Я немного сбит с толку. Если бы я использовал JOptionPane вместо класса GameEnd, где бы использовался JOptionPane? Буду ли я инициализировать и настраивать/разрабатывать его в классе XOButton, где находится WinCondition, или в классе TicTacToe?
new GameEnd(..);
Похоже, вы слишком сильно разбиваете проект. Если у вас есть класс для игры, держите все его методы внутри этого класса. Единственный раз, когда я могу использовать отдельные классы, это если вы пытаетесь создать это с использованием архитектуры Model-View-Controller (MVC) или тому подобного. Это распространенный подход для приложений, использующих графический интерфейс, доступ к данным и контроллеры.
Может быть и в другое время, но это все, что приходит мне в голову.
Из того, что вы показываете, я не думаю, что это применимо.
Я думаю, что это был бы лучший подход:
public class TicTacToe extends JFrame {
private int scorePlayer1;
private int scorePlayer2;
private boolean initialized; // default = false
// Reset the board
// Reset the markers, etc.
public void resetGame() {}
// Check to see if there is a winner
// If so, announce the winner and return true
// Otherwise, return false.
public boolean winCheck() {}
// Set up frame, buttons, score, etc.
public void newGame(){
// Create however many JPanels you need
// Add it to a single JFrame
// When you're ready...
// and this game has not been initialized for the first time.
// In this example jframe is an instance of JFrame
if (!this.initialized)
jframe.setVisible(true);
}
// Play the game
public void play(){
// For each round,
// a player chooses where to put their "X" or "O"
// add scores, etc.
// Then at the end of each round
if (this.winCheck())
this.resetGame();
}
}
public class TicTacToeTester {
public static void main(String[] args){
TicTacToe game = new TicTacToe();
game.play();
}
}
Надеюсь, это поможет!
Дайте знать, если у вас появятся вопросы. :)
Мне все равно нужен класс кнопки, верно? Кроме того, как мне отобразить экран Win без другого JFrame?
@DhruvPatel, вы можете создать класс XOButton
, если хотите, чтобы он делал определенные вещи ... Я сомневаюсь, что в этом случае это будет необходимо, если он только помещает маркер, а вы используете логику для управления счетом игрока. Если вы решите использовать класс для кнопки, вы можете это сделать. Но проверка выигрышной игры должна оставаться в основном классе TicTacToe
, потому что она определяет, есть ли победитель игра, а не кнопка. Это помогает?
Что касается JFrame, JFrame достаточно для отображения окна. Я обновлю свой ответ.
@DhruvPatel Я обновил свой ответ ... Дайте мне знать, если это поможет или вам нужна дополнительная помощь :)
Итак, если бы у меня был метод в TicTacToe для winChecking, как бы я смог его вызвать? Мне нужно запускать «winCheck» каждый раз, когда выполняется ActionPerformed (т.е. каждый раз, когда пользователь выбирает квадрат). Я не могу вызвать метод из класса TicTacToe в методе ActionPerformed, потому что метод actionperformed принадлежит классу Button, а winCheck принадлежит классу TicTacToe.
@DhruvPatel Это не сработает ... Как я уже сказал в своем первом комментарии, winCheck
должен быть внутри класса Крестики-нолики, а не XOButton. Вот почему я добавил метод play()
в класс TicTacToe.
@DhruvPatel Подожди... Кажется, я вижу способ добавить XOButton. Секунду.
@DhruvPatel Если вы хотите поместить winCheck()
в XOButton, вы действительно можете это сделать. Вот как. gist.github.com/sometowngeek/5f0de509a1c93bb87dffcb3f06918a95
Если вы хотите, чтобы я обновил свой ответ этим кодом, дайте мне знать.
1) Чтобы быстрее получить помощь, редактировать добавить минимальный воспроизводимый пример или Короткий, автономный, правильный пример. 2) Одна пустая строка пробела в исходном коде — это все, что нужно для Когда-либо. Пустые строки после
{
или перед}
также обычно избыточны. 3) См. Использование нескольких JFrames, хорошая/плохая практика? 4) Но не расширяйтеJFrame
или другие компоненты графического интерфейса, если только *специфический не требуется изменить существующее поведение! 5)if (e.getSource() == exit) { System.exit(0);
Самый простой способ..