diff --git a/src/jtictactoe/GameBoard.java b/src/jtictactoe/GameBoard.java index 32cbf22..9fd32fa 100644 --- a/src/jtictactoe/GameBoard.java +++ b/src/jtictactoe/GameBoard.java @@ -1,117 +1,117 @@ -package jtictactoe; - -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Point; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.image.BufferedImage; -import javax.swing.JPanel; - -/** - * - * @author aNNiMON - */ -public class GameBoard extends JPanel { - private static final int CELL_SIZE = 150; - private static final int OFFSET = 15; - - private BufferedImage strikedHor, strikedVer, strikedDiag, strikedDiagRev; - private BufferedImage background, figureX, figureO; - private Table table; - private TitlePanel title; - private int imgWidth, imgHeight; - - public GameBoard(TitlePanel title) { - this.title = title; - initImages(); - imgWidth = background.getWidth(); - imgHeight = background.getHeight(); - setPreferredSize( new Dimension(imgWidth, imgHeight) ); - addMouseListener(new MouseAdapter() { - @Override - public void mousePressed(MouseEvent evt) { - gameBoardMousePressed(evt); - } - }); - table = new Table(); - table.resetTable(); - } - - @Override - protected void paintComponent(Graphics g) { - super.paintComponent(g); - g.drawImage(background, 0, 0, null); - drawTable(g); - drawStrike(g); - } - - private void drawTable(Graphics g) { - Figure[][] figures = table.getFiguresArray(); - for (int i = 0; i < figures.length; i++) { - for (int j = 0; j < figures[0].length; j++) { - char figure = figures[i][j].getFigure(); - if (figure != Figure.EMPTY) { - BufferedImage image = ( (figure == Figure.X) ? figureX : figureO ); - int x = j * CELL_SIZE + OFFSET + (CELL_SIZE - image.getWidth()) / 2; - int y = i * CELL_SIZE + OFFSET + (CELL_SIZE - image.getHeight()) / 2; - g.drawImage(image, x, y, null); - } - } - } - } - - private void drawStrike(Graphics g) { - int strikeMode = table.getStrikedMode(); - if (strikeMode != Table.MODE_NOT_STRIKED) { - final int strikedSize = strikedHor.getHeight(); - int coord = OFFSET + (CELL_SIZE - strikedSize) / 2; - int strikePos = strikeMode & 0x03; - - if ( (strikeMode & Table.MODE_STRIKE_DIAGONAL) != 0 ) { - g.drawImage(strikedDiag, coord, coord, null); - } else if ( (strikeMode & Table.MODE_STRIKE_DIAGONAL_REVERSE) != 0 ) { - g.drawImage(strikedDiagRev, coord - OFFSET / 2, coord - OFFSET / 2, null); - } else if ( (strikeMode & Table.MODE_STRIKE_HORIZONTAL) != 0 ) { - g.drawImage(strikedHor, coord, coord + strikePos * CELL_SIZE, null); - } else if ( (strikeMode & Table.MODE_STRIKE_VERTICAL) != 0 ) { - g.drawImage(strikedVer, coord + strikePos * CELL_SIZE, coord, null); - } - } - } - - private void gameBoardMousePressed(MouseEvent evt) { - Point id = convertToID( evt.getPoint() ); - //table.computerMove(); - table.setFigure(id.x, id.y); - - if (table.getStrikedMode() == Table.MODE_NOT_STRIKED) title.setMessage(""); - - if (!table.hasMoreMoves()) { - char winner = table.checkWinner(); - if (winner != Figure.EMPTY) { - int winX = (winner == Figure.X) ? 1 : 0; - title.updateWin(winX, 1 - winX); - title.setMessage(winner + " is win"); - } else title.setMessage("Drow"); - } - repaint(); - } - - private void initImages() { - background = Util.getImage("/res/table_bg.jpg"); - figureX = Util.getImage("/res/x.png"); - figureO = Util.getImage("/res/o.png"); - strikedHor = Util.getImage("/res/striked.png"); - strikedVer = Util.getImage("/res/striked_ver.png"); - strikedDiag = Util.getImage("/res/striked_diagonal.png"); - strikedDiagRev = Util.getImage("/res/striked_diagonal_rev.png"); - } - - private Point convertToID(Point point) { - point.x /= imgWidth / 3; - point.y /= imgHeight / 3; - - return point; - } -} +package jtictactoe; + +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; +import javax.swing.JPanel; + +/** + * + * @author aNNiMON + */ +public class GameBoard extends JPanel { + private static final int CELL_SIZE = 150; + private static final int OFFSET = 15; + + private BufferedImage strikedHor, strikedVer, strikedDiag, strikedDiagRev; + private BufferedImage background, figureX, figureO; + private final Table table; + private final TitlePanel title; + private final int imgWidth, imgHeight; + + public GameBoard(TitlePanel title) { + this.title = title; + initImages(); + imgWidth = background.getWidth(); + imgHeight = background.getHeight(); + setPreferredSize( new Dimension(imgWidth, imgHeight) ); + addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent evt) { + gameBoardMousePressed(evt); + } + }); + table = new Table(); + table.resetTable(); + } + + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + g.drawImage(background, 0, 0, null); + drawTable(g); + drawStrike(g); + } + + private void drawTable(Graphics g) { + final Figure[][] figures = table.getFiguresArray(); + for (int i = 0; i < figures.length; i++) { + for (int j = 0; j < figures[0].length; j++) { + final char figure = figures[i][j].getFigure(); + if (figure != Figure.EMPTY) { + BufferedImage image = ( (figure == Figure.X) ? figureX : figureO ); + int x = j * CELL_SIZE + OFFSET + (CELL_SIZE - image.getWidth()) / 2; + int y = i * CELL_SIZE + OFFSET + (CELL_SIZE - image.getHeight()) / 2; + g.drawImage(image, x, y, null); + } + } + } + } + + private void drawStrike(Graphics g) { + final int strikeMode = table.getStrikedMode(); + if (strikeMode != Table.MODE_NOT_STRIKED) { + final int strikedSize = strikedHor.getHeight(); + final int coord = OFFSET + (CELL_SIZE - strikedSize) / 2; + final int strikePos = strikeMode & 0x03; + + if ( (strikeMode & Table.MODE_STRIKE_DIAGONAL) != 0 ) { + g.drawImage(strikedDiag, coord, coord, null); + } else if ( (strikeMode & Table.MODE_STRIKE_DIAGONAL_REVERSE) != 0 ) { + g.drawImage(strikedDiagRev, coord - OFFSET / 2, coord - OFFSET / 2, null); + } else if ( (strikeMode & Table.MODE_STRIKE_HORIZONTAL) != 0 ) { + g.drawImage(strikedHor, coord, coord + strikePos * CELL_SIZE, null); + } else if ( (strikeMode & Table.MODE_STRIKE_VERTICAL) != 0 ) { + g.drawImage(strikedVer, coord + strikePos * CELL_SIZE, coord, null); + } + } + } + + private void gameBoardMousePressed(MouseEvent evt) { + final Point id = convertToID( evt.getPoint() ); + //table.computerMove(); + table.setFigure(id.x, id.y); + + if (table.getStrikedMode() == Table.MODE_NOT_STRIKED) title.setMessage(""); + + if (!table.hasMoreMoves()) { + final char winner = table.checkWinner(); + if (winner != Figure.EMPTY) { + final int winX = (winner == Figure.X) ? 1 : 0; + title.updateWin(winX, 1 - winX); + title.setMessage(winner + " is win"); + } else title.setMessage("Drow"); + } + repaint(); + } + + private void initImages() { + background = Util.getImage("/res/table_bg.jpg"); + figureX = Util.getImage("/res/x.png"); + figureO = Util.getImage("/res/o.png"); + strikedHor = Util.getImage("/res/striked.png"); + strikedVer = Util.getImage("/res/striked_ver.png"); + strikedDiag = Util.getImage("/res/striked_diagonal.png"); + strikedDiagRev = Util.getImage("/res/striked_diagonal_rev.png"); + } + + private Point convertToID(Point point) { + point.x /= imgWidth / 3; + point.y /= imgHeight / 3; + + return point; + } +} diff --git a/src/jtictactoe/Main.java b/src/jtictactoe/Main.java index 4a3df15..f949253 100644 --- a/src/jtictactoe/Main.java +++ b/src/jtictactoe/Main.java @@ -1,32 +1,32 @@ -package jtictactoe; - -import java.awt.BorderLayout; -import javax.swing.JFrame; - -/** - * - * @author aNNiMON - */ -public class Main extends JFrame { - - public static void main(String[] args) { - new Main().setVisible(true); - - } - - public Main() { - super("JTicTacToe"); - setResizable(false); - setUndecorated(true); - setAlwaysOnTop(true); - setBounds(300, 120, 0, 0); - setDefaultCloseOperation(EXIT_ON_CLOSE); - setLayout(new BorderLayout(0, 0)); - - TitlePanel title = new TitlePanel(this); - add(title, BorderLayout.NORTH); - add(new GameBoard(title)); - - pack(); - } -} +package jtictactoe; + +import java.awt.BorderLayout; +import javax.swing.JFrame; + +/** + * + * @author aNNiMON + */ +public class Main extends JFrame { + + public static void main(String[] args) { + new Main().setVisible(true); + + } + + public Main() { + super("JTicTacToe"); + setResizable(false); + setUndecorated(true); + setAlwaysOnTop(true); + setBounds(300, 120, 0, 0); + setDefaultCloseOperation(EXIT_ON_CLOSE); + setLayout(new BorderLayout(0, 0)); + + final TitlePanel title = new TitlePanel(this); + add(title, BorderLayout.NORTH); + add(new GameBoard(title)); + + pack(); + } +} diff --git a/src/jtictactoe/Table.java b/src/jtictactoe/Table.java index 4ebe3df..b12f027 100644 --- a/src/jtictactoe/Table.java +++ b/src/jtictactoe/Table.java @@ -1,201 +1,201 @@ -package jtictactoe; - -import java.util.Random; - -/** - * - * @author aNNiMON - */ -public class Table { - - public static final int - MODE_NOT_STRIKED = 0, - MODE_STRIKE_HORIZONTAL = 0x04, - MODE_STRIKE_VERTICAL = 0x08, - MODE_STRIKE_DIAGONAL = 0x10, - MODE_STRIKE_DIAGONAL_REVERSE = 0x20; - - private boolean nextMoveIsX; - private Figure[][] table; - private Random random; - private int strikedMode; - - public Table() { - table = new Figure[3][3]; - random = new Random(); - } - - public void resetTable() { - for (int i = 0; i < table.length; i++) { - for (int j = 0; j < table[0].length; j++) { - table[i][j] = new Figure(); - } - } - strikedMode = MODE_NOT_STRIKED; - nextMoveIsX = true; - } - - public int getStrikedMode() { - return strikedMode; - } - - public Figure[][] getFiguresArray() { - return table; - } - - public void setFigure(int x, int y) { - if( (checkWinner() != Figure.EMPTY) || (!hasMoreMoves()) ) { - resetTable(); - return; - } - - boolean xIsNorm = ( (0 <= x) && (x < 3) ); - boolean yIsNorm = ( (0 <= y) && (y < 3) ); - if (xIsNorm && yIsNorm && table[y][x].isEmpty()) { - table[y][x].setFigure(nextMoveIsX ? Figure.X : Figure.O); - nextMoveIsX = !nextMoveIsX; - computerMove(); - } - } - - public void computerMove() { - if( (checkWinner() != Figure.EMPTY) || (!hasMoreMoves()) ) { - //resetTable(); - return; - } - - computerAI(); - nextMoveIsX = !nextMoveIsX; - } - - private void computerAI() { - final Figure[][] array = new Figure[][] { - // Horizontal check - table[0], - table[1], - table[2], - - // Vertical check - { table[0][0], table[1][0], table[2][0] }, - { table[0][1], table[1][1], table[2][1] }, - { table[0][2], table[1][2], table[2][2] }, - - // Diagonal check - { table[0][0], table[1][1], table[2][2] }, - { table[0][2], table[1][1], table[2][0] } - }; - char[] maybeWinnerArray = new char[array.length]; - // Calculate winning situations for computer (zeroes). - for (int i = 0; i < array.length; i++) { - Figure[] figures = array[i]; - char maybeWinner = maybeWinnerComboIs(figures); - maybeWinnerArray[i] = maybeWinner; - if (maybeWinner == Figure.O) { - if (setCompFigure(figures)) return; - } - } - // Calculate winning situations for the player (crosses). - for (int i = 0; i < array.length; i++) { - Figure[] figures = array[i]; - char maybeWinner = maybeWinnerArray[i]; - if (maybeWinner == Figure.X) { - if (setCompFigure(figures)) return; - } - } - - // Trying to put figure to the center. - int x = 1, y = 1; - if(!table[y][x].isEmpty() || (random.nextInt(5) <= 3) ) { - // If it's busy, put to the corners. - int count = 0; - do { - x = random.nextBoolean() ? 0 : 2; - y = random.nextBoolean() ? 0 : 2; - count++; - } while ( (!table[y][x].isEmpty()) && (count < 10)); - - if (count > 9) { - // Put to the remaining cells. - int[][] pair = {{0, 1}, {1, 0}, {1, 2}, {2, 1}}; - count = 0; - do { - x = pair[random.nextInt(pair.length)][0]; - y = pair[random.nextInt(pair.length)][1]; - count++; - } while ( (!table[y][x].isEmpty()) && (count < 10)); - } - } - table[y][x].setFigure(nextMoveIsX ? Figure.X : Figure.O); - } - - public char checkWinner() { - // Horizontal check - for (int y = 0; y < 3; y++) { - if (isWinnerCombo(table[y][0], table[y][1], table[y][2])) { - strikedMode = MODE_STRIKE_HORIZONTAL | y; - return table[y][0].getFigure(); - } - } - // Vertical check - for (int x = 0; x < 3; x++) { - if (isWinnerCombo(table[0][x], table[1][x], table[2][x])) { - strikedMode = MODE_STRIKE_VERTICAL | x; - return table[0][x].getFigure(); - } - } - // Diagonal check - if (isWinnerCombo(table[0][0], table[1][1], table[2][2])) { - strikedMode = MODE_STRIKE_DIAGONAL; - return table[0][0].getFigure(); - } - if (isWinnerCombo(table[0][2], table[1][1], table[2][0])) { - strikedMode = MODE_STRIKE_DIAGONAL_REVERSE; - return table[0][2].getFigure(); - } - // No winner - return Figure.EMPTY; - } - - public boolean hasMoreMoves() { - if (checkWinner() != Figure.EMPTY) return false; - - int emptyFiguresCount = 0; - for (int i = 0; i < table.length; i++) { - for (int j = 0; j < table[0].length; j++) { - if (table[i][j].isEmpty()) emptyFiguresCount++; - } - } - - return (emptyFiguresCount != 0); - } - - private boolean isWinnerCombo(Figure f1, Figure f2, Figure f3) { - if (f1.isEmpty()) return false; - char figure = f1.getFigure(); - return ( (figure == f2.getFigure()) && - (figure == f3.getFigure()) ); - } - - private char maybeWinnerComboIs(Figure[] array) { - int numX = 0, numO = 0; - for (int i = 0; i < array.length; i++) { - if (!array[i].isEmpty()) { - if (array[i].getFigure() == Figure.X) numX++; - else numO++; - } - } - if (numX == 2) return Figure.X; - if (numO == 2) return Figure.O; - return Figure.EMPTY; - } - - private boolean setCompFigure(Figure[] array) { - for (int i = 0; i < array.length; i++) { - if (array[i].isEmpty()) { - array[i].setFigure(Figure.O); - return true; - } - } - return false; - } -} +package jtictactoe; + +import java.util.Random; + +/** + * + * @author aNNiMON + */ +public class Table { + + public static final int + MODE_NOT_STRIKED = 0, + MODE_STRIKE_HORIZONTAL = 0x04, + MODE_STRIKE_VERTICAL = 0x08, + MODE_STRIKE_DIAGONAL = 0x10, + MODE_STRIKE_DIAGONAL_REVERSE = 0x20; + + private final Figure[][] table; + private final Random random; + private int strikedMode; + private boolean nextMoveIsX; + + public Table() { + table = new Figure[3][3]; + random = new Random(); + } + + public void resetTable() { + for (int i = 0; i < table.length; i++) { + for (int j = 0; j < table[0].length; j++) { + table[i][j] = new Figure(); + } + } + strikedMode = MODE_NOT_STRIKED; + nextMoveIsX = true; + } + + public int getStrikedMode() { + return strikedMode; + } + + public Figure[][] getFiguresArray() { + return table; + } + + public void setFigure(int x, int y) { + if( (checkWinner() != Figure.EMPTY) || (!hasMoreMoves()) ) { + resetTable(); + return; + } + + boolean xIsNorm = ( (0 <= x) && (x < 3) ); + boolean yIsNorm = ( (0 <= y) && (y < 3) ); + if (xIsNorm && yIsNorm && table[y][x].isEmpty()) { + table[y][x].setFigure(nextMoveIsX ? Figure.X : Figure.O); + nextMoveIsX = !nextMoveIsX; + computerMove(); + } + } + + public void computerMove() { + if( (checkWinner() != Figure.EMPTY) || (!hasMoreMoves()) ) { + //resetTable(); + return; + } + + computerAI(); + nextMoveIsX = !nextMoveIsX; + } + + private void computerAI() { + final Figure[][] array = new Figure[][] { + // Horizontal check + table[0], + table[1], + table[2], + + // Vertical check + { table[0][0], table[1][0], table[2][0] }, + { table[0][1], table[1][1], table[2][1] }, + { table[0][2], table[1][2], table[2][2] }, + + // Diagonal check + { table[0][0], table[1][1], table[2][2] }, + { table[0][2], table[1][1], table[2][0] } + }; + final char[] maybeWinnerArray = new char[array.length]; + // Calculate winning situations for computer (zeroes). + for (int i = 0; i < array.length; i++) { + Figure[] figures = array[i]; + char maybeWinner = maybeWinnerComboIs(figures); + maybeWinnerArray[i] = maybeWinner; + if (maybeWinner == Figure.O) { + if (setCompFigure(figures)) return; + } + } + // Calculate winning situations for the player (crosses). + for (int i = 0; i < array.length; i++) { + Figure[] figures = array[i]; + char maybeWinner = maybeWinnerArray[i]; + if (maybeWinner == Figure.X) { + if (setCompFigure(figures)) return; + } + } + + // Trying to put figure to the center. + int x = 1, y = 1; + if(!table[y][x].isEmpty() || (random.nextInt(5) <= 3) ) { + // If it's busy, put to the corners. + int count = 0; + do { + x = random.nextBoolean() ? 0 : 2; + y = random.nextBoolean() ? 0 : 2; + count++; + } while ( (!table[y][x].isEmpty()) && (count < 10)); + + if (count > 9) { + // Put to the remaining cells. + int[][] pair = {{0, 1}, {1, 0}, {1, 2}, {2, 1}}; + count = 0; + do { + x = pair[random.nextInt(pair.length)][0]; + y = pair[random.nextInt(pair.length)][1]; + count++; + } while ( (!table[y][x].isEmpty()) && (count < 10)); + } + } + table[y][x].setFigure(nextMoveIsX ? Figure.X : Figure.O); + } + + public char checkWinner() { + // Horizontal check + for (int y = 0; y < 3; y++) { + if (isWinnerCombo(table[y][0], table[y][1], table[y][2])) { + strikedMode = MODE_STRIKE_HORIZONTAL | y; + return table[y][0].getFigure(); + } + } + // Vertical check + for (int x = 0; x < 3; x++) { + if (isWinnerCombo(table[0][x], table[1][x], table[2][x])) { + strikedMode = MODE_STRIKE_VERTICAL | x; + return table[0][x].getFigure(); + } + } + // Diagonal check + if (isWinnerCombo(table[0][0], table[1][1], table[2][2])) { + strikedMode = MODE_STRIKE_DIAGONAL; + return table[0][0].getFigure(); + } + if (isWinnerCombo(table[0][2], table[1][1], table[2][0])) { + strikedMode = MODE_STRIKE_DIAGONAL_REVERSE; + return table[0][2].getFigure(); + } + // No winner + return Figure.EMPTY; + } + + public boolean hasMoreMoves() { + if (checkWinner() != Figure.EMPTY) return false; + + int emptyFiguresCount = 0; + for (int i = 0; i < table.length; i++) { + for (int j = 0; j < table[0].length; j++) { + if (table[i][j].isEmpty()) emptyFiguresCount++; + } + } + + return (emptyFiguresCount != 0); + } + + private boolean isWinnerCombo(Figure f1, Figure f2, Figure f3) { + if (f1.isEmpty()) return false; + final char figure = f1.getFigure(); + return ( (figure == f2.getFigure()) && + (figure == f3.getFigure()) ); + } + + private char maybeWinnerComboIs(Figure[] array) { + int numX = 0, numO = 0; + for (int i = 0; i < array.length; i++) { + if (!array[i].isEmpty()) { + if (array[i].getFigure() == Figure.X) numX++; + else numO++; + } + } + if (numX == 2) return Figure.X; + if (numO == 2) return Figure.O; + return Figure.EMPTY; + } + + private boolean setCompFigure(Figure[] array) { + for (int i = 0; i < array.length; i++) { + if (array[i].isEmpty()) { + array[i].setFigure(Figure.O); + return true; + } + } + return false; + } +}