
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

/**
 * @author Korbinian Schmid
 */

public class TicTacToe extends JFrame implements ActionListener {
	
	Player o;
	Player x;
	Player current;
	JLabel label;
	JButton reset;
	JButton[][] button;
	int count;
	
	public TicTacToe() {
		super("Tic Tac Toe");
		setLayout( new FlowLayout(FlowLayout.CENTER, 8, 8) );
		setSize(180, 220);
		setLocation(200, 200);
		setResizable(false);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		/* Initialisierung der beiden Spieler */
		o = new Player("o");
		x = new Player("x");
		current = o;
				
		/* Initialisierung Spieleranzeige */
		label = new JLabel("Nächster Zug: Spieler " + current.getName());
	
		/* Initialisierung Spielfeld */
		JPanel panel = new JPanel( new GridLayout(3, 3, 3, 3) );
		panel.setBackground(Color.BLACK);
		panel.setPreferredSize( new Dimension(150, 120) );
		button = new JButton[3][3];
		for(int i = 0; i < 3; i++) {
			for(int j = 0; j < 3; j++) {
				button[i][j] = new JButton("");
				button[i][j].setBackground(Color.WHITE);
				button[i][j].setPreferredSize( new Dimension(48, 38) );
				button[i][j].setActionCommand("b" + i + j);
				button[i][j].addActionListener(this);
				panel.add(button[i][j]);
			}
		}
		
		/* Initialisierung Reset-Button */
		reset = new JButton("Zurücksetzen");
		reset.setPreferredSize( new Dimension(130, 20) );
		reset.setActionCommand("reset");
		reset.addActionListener(this);
		
		/* Komponenten dem Frame hinzufügen */
		add(label);
		add(panel);
		add(reset);
		
		setVisible(true);
		count = 0;
	}
	
	public void changePlayers() {
		if( current.equals(o) ) {
			current = x;
			label.setText("Nächster Zug: Spieler x");
		} else {
			current = o;
			label.setText("Nächster Zug: Spieler o");
		}
	}
	
	public void clear(boolean enabled) {
		for(int i = 0; i < 3; i++) {
			for(int j = 0; j < 3; j++) {
				if(enabled) {
					button[i][j].setEnabled(true);
					button[i][j].setText("");
				} else {
					button[i][j].setEnabled(false);
				}
			}
		}
	}

	public void actionPerformed(ActionEvent e) {
		String cmd = e.getActionCommand();
		int i, j;
		
		/* reset */
		if( cmd.equals("reset") ) {
			clear(true);
			o.reset();
			x.reset();
			current = o;
			label.setText("Nächster Zug: Spieler " + current.getName());
			reset.setText("Zurücksetzen");
			count = 0;
		} 

		
		/* buttons */
		else {
			for(i = 0; i < 3; i++) {
				for(j = 0; j < 3; j++) {
					if( cmd.equals("b" + i + j) ) {
						current.add(i, j);
						button[i][j].setText( current.getName() );
						count++;
						/* check win */
						if( current.checkWin() ) {
							clear(false);
							label.setText("Spieler " + current.getName() + " gewinnt!");
							reset.setText("Nochmal >>");
						} else {
							button[i][j].setEnabled(false);
							/* check draw */
							if(count == 9) {
								label.setText("Unentschieden");
								reset.setText("Nochmal >>");
							} else {
								changePlayers();
							}
						}
					}
				}
			}
		}
	}
				
	public static void main(String[] args) {
		new TicTacToe();
	}
}

class Player {
	String name;
	/* 8 Möglichkeiten zu gewinnen */
	int row0, row1, row2;
	int col0, col1, col2;
	int dia1, dia2;

	public Player(String name) {
		this.name = name;
		reset();
	}
	
	public void reset() {
		row0 = 0; row1 = 0; row2 = 0;
		col0 = 0; col1 = 0; col2 = 0;
		dia1 = 0; dia2 = 0;
	}
	
	public String getName() {
		return name;
	}
	
	public void add(int row, int col) {
		
		/* Zeilen */
		switch(row) {
			case 0 : row0++; break;
			case 1 : row1++; break;
			case 2 : row2++; break;
		}
		
		/* Spalten */
		switch(col) {
			case 0 : col0++; break;
			case 1 : col1++; break;
			case 2 : col2++; break;
		}
		
		/* Spezialfall Diagonale */
		if( (row == 0) && (col == 0) ) dia1++;
		if( (row == 1) && (col == 1) ) { dia1++; dia2++; }
		if( (row == 2) && (col == 2) ) dia1++;
		if( (row == 2) && (col == 0) ) dia2++;
		if( (row == 0) && (col == 2) ) dia2++;
	}
			
	public boolean checkWin() {
		return ( (row0 == 3) || (row1 == 3) || (row2 == 3) ||
			 (col0 == 3) || (col1 == 3) || (col2 == 3) ||
			 (dia1 == 3) || (dia2 == 3) );
	}
}