001: /*
002: * This file is part of JGAP.
003: *
004: * JGAP offers a dual license model containing the LGPL as well as the MPL.
005: *
006: * For licensing information please see the file license.txt included with JGAP
007: * or have a look at the top of class org.jgap.Chromosome which representatively
008: * includes the JGAP license policy applicable for any file delivered with JGAP.
009: */
010: package examples.gp.tictactoe;
011:
012: import java.util.*;
013:
014: /**
015: * A Tic Tac Toe board (3x3).
016: *
017: * @author Klaus Meffert
018: * @since 3.2
019: */
020: public class Board {
021: private int[][] m_board;
022:
023: private int m_lastColor;
024:
025: public static int WIDTH = 2;
026:
027: public static int HEIGHT = WIDTH;
028:
029: private int movesInRound;
030: private int movesInTurn;
031: private Map m_readPositions;
032: private int m_readPositionCount;
033:
034: public Board() {
035: m_board = new int[WIDTH][HEIGHT];
036: m_readPositions = new Hashtable();
037: startNewRound();
038: }
039:
040: public void resetBoard() {
041: for (int x = 0; x < WIDTH; x++) {
042: for (int y = 0; y < HEIGHT; y++) {
043: m_board[x][y] = 0;
044: }
045: }
046: }
047:
048: public void startNewRound() {
049: m_lastColor = 0;
050: movesInRound = 0;
051: resetBoard();
052: }
053:
054: public void beginTurn() {
055: movesInTurn = 0;
056: m_readPositionCount = 0;
057: m_readPositions.clear();
058: }
059:
060: public void endTurn() {
061: if (movesInTurn != 1) {
062: throw new IllegalStateException(
063: "One stone must be set by player!");
064: }
065: }
066:
067: public void endRound() {
068: if (m_lastColor == 0) {
069: throw new IllegalStateException(
070: "No stone set within the round!");
071: }
072: if (movesInRound != 2) {
073: throw new IllegalStateException(
074: "Both players have to move."
075: + " Moves registered: " + movesInRound);
076: }
077: System.out.println("*** Valid round!");
078: }
079:
080: public boolean putStone(int x, int y, int a_color)
081: throws IllegalArgumentException {
082: if (x < 1 || y < 1 || x > WIDTH || y > HEIGHT) {
083: throw new IllegalArgumentException(
084: "x and y must be between 1..3");
085: }
086: if (m_board[x - 1][y - 1] != 0) {
087: throw new IllegalArgumentException(
088: "Position already occupied");
089: }
090: if (a_color != 1 && a_color != 2) {
091: throw new IllegalArgumentException("Color must be 1 or 2");
092: }
093: if (m_lastColor == a_color) {
094: throw new IllegalArgumentException(
095: "Oponent must move first");
096: }
097: m_lastColor = a_color;
098: m_board[x - 1][y - 1] = a_color;
099: movesInTurn++;
100: movesInRound++;
101: if (isEndOfGame()) {
102: return true;
103: }
104: return false;
105: }
106:
107: public int readField(int x, int y) throws IllegalArgumentException {
108: if (x < 1 || y < 1 || x > WIDTH || y > HEIGHT) {
109: throw new IllegalArgumentException(
110: "x and y must be between 1.." + WIDTH);
111: }
112: if (m_readPositions.get(x + "_" + y) == null) {
113: m_readPositionCount++;
114: m_readPositions.put(x + "_" + y, "jgap");
115: }
116: return m_board[x - 1][y - 1];
117: }
118:
119: public int getReadPositionCount() {
120: return m_readPositionCount;
121: }
122:
123: public int readField(int a_index) throws IllegalArgumentException {
124: if (a_index < 1 || a_index > (WIDTH * HEIGHT)) {
125: throw new IllegalArgumentException(
126: "Index must be between 1.." + (WIDTH * HEIGHT));
127: }
128: int x = (a_index - 1) / WIDTH;
129: int y = (a_index - 1) % WIDTH;
130: return m_board[x][y];
131: }
132:
133: public boolean isEndOfGame() {
134: for (int y = 0; y < HEIGHT; y++) {
135: if (isWinner(0, WIDTH - 1, y, y)) {
136: return true;
137: }
138: }
139: for (int x = 0; x < HEIGHT; x++) {
140: if (isWinner(x, x, 0, HEIGHT - 1)) {
141: return true;
142: }
143: }
144: if (isWinnerDiag(0, 0, 1)) {
145: return true;
146: }
147: if (isWinnerDiag(WIDTH - 1, 0, -1)) {
148: return true;
149: }
150: return false;
151: }
152:
153: private boolean isWinner(int a_firstX, int a_lastX, int a_firstY,
154: int a_lastY) {
155: int count = 0;
156: int lastcolor = -1;
157: for (int x = a_firstX; x <= a_lastX; x++) {
158: for (int y = a_firstY; y <= a_lastY; y++) {
159: int color = m_board[x][y];
160: if (color == 0) {
161: return false;
162: }
163: if (lastcolor == -1) {
164: lastcolor = color;
165: count++;
166: } else {
167: if (lastcolor != color) {
168: return false;
169: } else {
170: count++;
171: }
172: }
173: }
174: }
175: return true;
176: }
177:
178: private boolean isWinnerDiag(int a_startX, int a_startY,
179: int a_increment) {
180: int count = 0;
181: int lastcolor = -1;
182: int x = a_startX;
183: int y = a_startY;
184: while (count < WIDTH) {
185: int color = m_board[x][y];
186: if (color == 0) {
187: return false;
188: }
189: if (lastcolor == -1) {
190: lastcolor = color;
191: count++;
192: } else {
193: if (lastcolor != color) {
194: return false;
195: } else {
196: count++;
197: }
198: }
199: x = x + a_increment;
200: y = y + 1;
201: }
202: return true;
203: }
204:
205: public int getLastColor() {
206: return m_lastColor;
207: }
208: }
|