/* * This file is part of JGAP. * * JGAP offers a dual license model containing the LGPL as well as the MPL. * * For licensing information please see the file license.txt included with JGAP * or have a look at the top of class org.jgap.Chromosome which representatively * includes the JGAP license policy applicable for any file delivered with JGAP. */ package examples.gp.tictactoe; import java.util.*; /** * A Tic Tac Toe board (3x3). * * @author Klaus Meffert * @since 3.2 */ public class Board { private int[][] m_board; private int m_lastColor; public static int WIDTH = 2; public static int HEIGHT = WIDTH; private int movesInRound; private int movesInTurn; private Map m_readPositions; private int m_readPositionCount; public Board() { m_board = new int[WIDTH][HEIGHT]; m_readPositions = new Hashtable(); startNewRound(); } public void resetBoard() { for (int x = 0; x < WIDTH; x++) { for (int y = 0; y < HEIGHT; y++) { m_board[x][y] = 0; } } } public void startNewRound() { m_lastColor = 0; movesInRound = 0; resetBoard(); } public void beginTurn() { movesInTurn = 0; m_readPositionCount = 0; m_readPositions.clear(); } public void endTurn() { if (movesInTurn != 1) { throw new IllegalStateException("One stone must be set by player!"); } } public void endRound() { if (m_lastColor == 0) { throw new IllegalStateException("No stone set within the round!"); } if (movesInRound != 2) { throw new IllegalStateException("Both players have to move." + " Moves registered: " + movesInRound); } System.out.println("*** Valid round!"); } public boolean putStone(int x, int y, int a_color) throws IllegalArgumentException { if (x < 1 || y < 1 || x > WIDTH || y > HEIGHT) { throw new IllegalArgumentException("x and y must be between 1..3"); } if (m_board[x - 1][y - 1] != 0) { throw new IllegalArgumentException("Position already occupied"); } if (a_color != 1 && a_color != 2) { throw new IllegalArgumentException("Color must be 1 or 2"); } if (m_lastColor == a_color) { throw new IllegalArgumentException("Oponent must move first"); } m_lastColor = a_color; m_board[x - 1][y - 1] = a_color; movesInTurn++; movesInRound++; if (isEndOfGame()) { return true; } return false; } public int readField(int x, int y) throws IllegalArgumentException { if (x < 1 || y < 1 || x > WIDTH || y > HEIGHT) { throw new IllegalArgumentException("x and y must be between 1.." + WIDTH); } if (m_readPositions.get(x+"_"+y) == null) { m_readPositionCount++; m_readPositions.put(x + "_" + y, "jgap"); } return m_board[x - 1][y - 1]; } public int getReadPositionCount() { return m_readPositionCount; } public int readField(int a_index) throws IllegalArgumentException { if (a_index < 1 || a_index > (WIDTH * HEIGHT)) { throw new IllegalArgumentException("Index must be between 1.." + (WIDTH * HEIGHT)); } int x = (a_index - 1) / WIDTH; int y = (a_index - 1) % WIDTH; return m_board[x][y]; } public boolean isEndOfGame() { for (int y = 0; y < HEIGHT; y++) { if (isWinner(0, WIDTH-1, y, y)) { return true; } } for (int x = 0; x < HEIGHT; x++) { if (isWinner(x, x, 0, HEIGHT-1)) { return true; } } if (isWinnerDiag(0, 0, 1)) { return true; } if (isWinnerDiag(WIDTH-1, 0, -1)) { return true; } return false; } private boolean isWinner(int a_firstX, int a_lastX, int a_firstY, int a_lastY) { int count = 0; int lastcolor = -1; for (int x = a_firstX; x <= a_lastX; x++) { for (int y = a_firstY; y <= a_lastY; y++) { int color = m_board[x][y]; if (color == 0) { return false; } if (lastcolor == -1) { lastcolor = color; count++; } else { if (lastcolor != color) { return false; } else { count++; } } } } return true; } private boolean isWinnerDiag(int a_startX, int a_startY, int a_increment) { int count = 0; int lastcolor = -1; int x = a_startX; int y = a_startY; while (count < WIDTH) { int color = m_board[x][y]; if (color == 0) { return false; } if (lastcolor == -1) { lastcolor = color; count++; } else { if (lastcolor != color) { return false; } else { count++; } } x = x + a_increment; y = y + 1; } return true; } public int getLastColor() { return m_lastColor; } }