TicTacToe - weryfikacja wygranej

0

Hej. Po przerobieniu sobie tutoriali Dereka Banasa, zrobieniu kilku projektów na ich bazie postanowiłem zrobić coś w 100% swojego. Napisałem już część gry 'Kółko i Krzyżyk' ale w utknąłem w miejscu sprawdzania wyniku gry. Podejrzewam że to coś z moją drabinką if'ów (na pewno jest źle wywoływana, ale w jej umieszczenie i wywołanie z myButon tez nie działa), ale nie jestem pewien, więc proszę o jakieś wskazówki jak to rozwiązać. Jeśli ktoś miałby też chęci to poprosiłbym o jakąś krytykę dotychczasowego kodu.

Podrzucam tez kod i zasoby na githubie: https://github.com/hergerr/TicTacToe

Klasa Field

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


public class Field extends JFrame{
	
	public static MyButton button1, button2, button3, button4, button5, button6, button7, button8, button9;
	public static MyButton[] buttonTab = {button1, button2, button3, button4, button5, button6, button7, button8, button9};

	public static void main(String[] args){
		new Field();
	}
	
	Field(){
		this.setSize(400, 400);
		this.setTitle("Game");
		this.setLocationRelativeTo(null);
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		this.setResizable(false);
		GridLayout gridLayout = new GridLayout(3,3);
		setLayout(gridLayout);
		for(int i = 0; i < 9; ++i){
			buttonTab[i] = new MyButton();
			add(buttonTab[i]);
		}		
		this.setVisible(true);
		win();
	}
	
	public void win(){
		if(((Field.button1.getIcon() == MyButton.xImg) && (Field.button2.getIcon() == MyButton.xImg) && (Field.button3.getIcon() == MyButton.xImg)) 
		|| ((Field.button4.getIcon() == MyButton.xImg) && (Field.button5.getIcon() == MyButton.xImg) && (Field.button6.getIcon() == MyButton.xImg))
		|| ((Field.button7.getIcon() == MyButton.xImg) && (Field.button8.getIcon() == MyButton.xImg) && (Field.button9.getIcon() == MyButton.xImg))
		|| ((Field.button1.getIcon() == MyButton.xImg) && (Field.button5.getIcon() == MyButton.xImg) && (Field.button9.getIcon() == MyButton.xImg))
		|| ((Field.button3.getIcon() == MyButton.xImg) && (Field.button5.getIcon() == MyButton.xImg) && (Field.button7.getIcon() == MyButton.xImg))
		|| ((Field.button1.getIcon() == MyButton.xImg) && (Field.button4.getIcon() == MyButton.xImg) && (Field.button7.getIcon() == MyButton.xImg))
		|| ((Field.button2.getIcon() == MyButton.xImg) && (Field.button5.getIcon() == MyButton.xImg) && (Field.button8.getIcon() == MyButton.xImg))
		|| ((Field.button3.getIcon() == MyButton.xImg) && (Field.button6.getIcon() == MyButton.xImg) && (Field.button9.getIcon() == MyButton.xImg))){
			JOptionPane.showMessageDialog(Field.this, "You won", "You won", JOptionPane.INFORMATION_MESSAGE);
			// player won				  
		}
		else if(((Field.button1.getIcon() == MyButton.oImg) && (Field.button2.getIcon() == MyButton.oImg) && (Field.button3.getIcon() == MyButton.oImg)) 
		|| ((Field.button4.getIcon() == MyButton.oImg) && (Field.button5.getIcon() == MyButton.oImg) && (Field.button6.getIcon() == MyButton.oImg))
		|| ((Field.button7.getIcon() == MyButton.oImg) && (Field.button8.getIcon() == MyButton.oImg) && (Field.button9.getIcon() == MyButton.oImg))
		|| ((Field.button1.getIcon() == MyButton.oImg) && (Field.button5.getIcon() == MyButton.oImg) && (Field.button9.getIcon() == MyButton.oImg))
		|| ((Field.button3.getIcon() == MyButton.oImg) && (Field.button5.getIcon() == MyButton.oImg) && (Field.button7.getIcon() == MyButton.oImg))
		|| ((Field.button3.getIcon() == MyButton.oImg) && (Field.button5.getIcon() == MyButton.oImg) && (Field.button7.getIcon() == MyButton.oImg))
		|| ((Field.button1.getIcon() == MyButton.oImg) && (Field.button4.getIcon() == MyButton.oImg) && (Field.button7.getIcon() == MyButton.oImg))
		|| ((Field.button2.getIcon() == MyButton.oImg) && (Field.button5.getIcon() == MyButton.oImg) && (Field.button8.getIcon() == MyButton.oImg))
		|| ((Field.button3.getIcon() == MyButton.oImg) && (Field.button6.getIcon() == MyButton.oImg) && (Field.button9.getIcon() == MyButton.oImg))){
			JOptionPane.showMessageDialog(Field.this, "Computer won", "Computer won", JOptionPane.INFORMATION_MESSAGE);
			// computer won
		}
		
		//else JOptionPane.showMessageDialog(Field.this, "Draw", "Draw", JOptionPane.INFORMATION_MESSAGE);
		
		
	}
} 

Klasa myButton

import javax.swing.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;


public class MyButton extends JButton {
	int imgCounter = 0;
	int[] tabOfIndexes = new int[9];
	ImageIcon whiteImg = new ImageIcon("resources/white.jpg");
	public static ImageIcon xImg = new ImageIcon("resources/x.png");
	public static ImageIcon oImg = new ImageIcon("resources/o.png");
	
	
	public MyButton(ImageIcon img){
		this.addActionListener(new ListenForButton());
		this.setIcon(img);
	}
	
	public void markFieldwithO(){
		int i = 0;
		while(!Field.buttonTab[i].isEmpty()){
			++i;
		}
		Field.buttonTab[i].setIcon(oImg);
	}
	
	public boolean isEmpty(){
		if(this.getIcon() == whiteImg) return true; //TODO why it doesn't work with imgCounter 
		else return false;
	}
	
	public MyButton(){
		this.addActionListener(new ListenForButton());
		this.setIcon(whiteImg);
	}
	
	
private class ListenForButton implements ActionListener{
	public void actionPerformed(ActionEvent e) {
		++imgCounter;
		imgCounter %= 3;	
			switch(imgCounter){
			case 0: setIcon(whiteImg);
			break;
			case 1: setIcon(xImg);
			break;
			case 2: setIcon(oImg);
			break;
			}
			markFieldwithO();
			
		}
	
	}
} 

PS: wiem że ruchy komputera są słabe, ale jak przejdę przez problem sprawdzania wygranych, to zaimplementuję algorytm minMax

1
  1. Zacznij od utworzenia reprezentacji mapy jako tablicy dwuwymiarowej, tak abyś mógł sprawdzić, kto zajmuje pole, odnosząc się poprzez map[x][y] (lekcja do poczytania: typy enumeracyjne).
  2. Usuń także całą metodę win - napiszemy ją co najmniej kilkaset razy ładniej.
  3. MyButton jest okropnie złą nazwą komponentu + łamiesz tam zasadę pojedynczej odpowiedzialności; zrób sobie po prostu jakiś ImageButton.
0

Zamień te ify na coś innego chociażby kilka przykładów:
http://stackoverflow.com/questions/18548265/testing-tic-tac-toe-win-condition

0

Mam też problem z tym w której klasie napisać tę metodę. Z jednej strony wygodnie byłoby ją umieścić w MyButton, bo można by sprawdzać wygraną po każdym naciśnięciu guzika, zaś z drugiej strony w klasie Field mogę zastosować JOptionPane.showMessageDialog(Field.this, "Computer won", "Computer won", JOptionPane.INFORMATION_MESSAGE); z motherObject Field.

1
classongrass napisał(a)

Czy ta tablica dwuwymiarowa nie jest trochę na wyrost? Trochę nie rozumiem dlaczego miałbym sprawdzać wygraną w ten sposób, skoro mogę sprawdzać po ikonach
W jaki sposób na wyrost? Dzięki temu rozdzielisz poszczególne warstwy aplikacji.
Aktualnie masz połączoną warstwę prezentacji (przyciski / ikony) z warstwą logiki (przetwarzanie działania gry), ponieważ sprawdzanie wygranej (logika) odnosi się bezpośrednio do ikon (prezentacji). Gdy wykorzystasz tablicę dwuwymiarową, będziesz miał stan gry zapisany w sposób jednoznaczny.

Poza tym, podając bardziej rzeczowy argument (o ile te wyżej można określić nierzeczowymi) - będziesz w stanie iterować po mapie za pomocą pętli, bez konieczności bawienia się w szukanie komponentów czy tworzenie mapy Point -> Component.

Z jednej strony wygodnie byłoby ją umieścić w MyButton, bo można by sprawdzać wygraną po każdym naciśnięciu guzika (...)
Mówisz o metodzie win?
Pamiętaj o zasadzie jednej odpowiedzialności - przycisk nie powinien być nawet świadom stanu gry. Wyrzuć tę metodę do jakiejś klasy w stylu GameEngine, to będzie dobre na początek.

1 użytkowników online, w tym zalogowanych: 0, gości: 1