import java.awt.*; import java.awt.event.*; import java.awt.geom.*; import java.io.File; import java.net.URL; import java.util.*; import javax.imageio.ImageIO; import javax.swing.*; /* * To change this template, choose Tools | Templates and open the template in * the editor. */ /** * * @author lubo */ public class TicTacToe extends JApplet { private ArrayList squares = new ArrayList<>(); private Image xImage, oImage; public void initBoard() { squares = new ArrayList<>(); Dimension d = getSize(); double dx = d.getWidth() / 3.0; double dy = d.getHeight() / 3.0; for (int x = 0; x < 3; x++) { for (double y = 0; y < 3; y++) { squares.add(new Square(x * dx, y * dy, dx, dy)); } } repaint(); } public void init() { URL urlX = null; URL urlO = null; try { urlX = new URL(getCodeBase(), "images/x.jpg"); urlO = new URL(getCodeBase(), "images/o.jpg"); xImage = ImageIO.read(urlX); oImage = ImageIO.read(urlO); } catch (Exception exception) { } initBoard(); addMouseListener(new MyMouseListener()); } public void paint(Graphics g) { super.paint(g); Graphics2D g2 = (Graphics2D) g; g2.setColor(Color.RED); for (Square r : squares) { r.draw(g2, xImage, oImage); } } public void computerMove() { if (!squares.get(4).hasValue()) { // if middle is empty squares.get(4).placeCharacter('o'); return; } Square bestRectangle = squares.get(0); int best = computeScore(bestRectangle); for (Square r : squares) { if (computeScore(r) > best) { best = computeScore(r); bestRectangle = r; } } bestRectangle.placeCharacter('o'); } public boolean isLine(int i, int j, int k, char c) { return (squares.get(i).isCharacter(c) && squares.get(j).isCharacter(c) && squares.get(k).isCharacter(c)); } public boolean wins(char c) { for (int i = 0; i < 3; i++) { if (isLine(3 * i, 3 * i + 1, 3 * i + 2, c) || // horizontal line (isLine(i, i + 3, i + 6, c))) { //vertical line return true; } } if (isLine(0, 4, 8, c) || isLine(2, 4, 6, c)) { //diagonal return true; } return false; } public boolean winsWithNextMove(Square r, char c) { r.placeCharacter(c); if (wins(c)) { r.clear(); return true; } r.clear(); return false; } public int computeScore(Square r) { if (r.hasValue()) { return 0; } if (winsWithNextMove(r, 'o')) { return 4; } if (winsWithNextMove(r, 'x')) { return 3; } return 2; } public boolean isGameOver() { if (wins('o')) { JOptionPane.showMessageDialog(this, "I win!"); initBoard(); return true; } if (wins('x')) { JOptionPane.showMessageDialog(this, "You win!"); initBoard(); return true; } if (isBoardFull()) { JOptionPane.showMessageDialog(this, "It's a tie!"); initBoard(); return true; } return false; } public boolean isBoardFull() { for (Square r : squares) { if (!r.hasValue()) { return false; } } return true; } class MyMouseListener extends MouseAdapter { public void mousePressed(MouseEvent e) { for (Square r : squares) { if (r.contains(e.getPoint())) { if (!r.hasValue()) { r.placeCharacter('x'); repaint(); if (isGameOver()) { return; } computerMove(); repaint(); if (isGameOver()) { return; } } } } } } } class Square extends Rectangle2D.Double { private boolean isX = false; private boolean isO = false; public boolean isCharacter(char c) { if (c == 'x') { return isX; } if (c == 'o') { return isO; } return false; } public void placeCharacter(char c) { if (c == 'x') { isX = true; } if (c == 'o') { isO = true; } } public void clear() { isX = false; isO = false; } public boolean hasValue() { return (isX || isO); } public Square(double x, double y, double dx, double dy) { super(x, y, dx, dy); } public void draw(Graphics2D g2, Image xImage, Image oImage) { g2.draw(super.getBounds2D()); if (isX) { g2.drawImage(xImage, (int) x + 1, (int) y + 1, (int) getWidth() - 2, (int) getHeight() - 2, null); } if (isO) { g2.drawImage(oImage, (int) getX() + 1, (int) y + 1, (int) getWidth() - 2, (int) getHeight() - 2, null); } } }