@Test public void testIsFull() { Board board = new Board(); // Board is empty assertFalse(board.isFull()); // Fill the board with moves for (int i = 0; i < 9; i++) { board.addMove(i, true); } // Board is full assertTrue(board.isFull()); }
@Test public void testIfBoardIsFull() { Board testBoard = new Board(); testBoard.mark(0, 0, 'x'); testBoard.mark(0, 1, 'x'); testBoard.mark(0, 2, 'x'); testBoard.mark(1, 0, 'x'); testBoard.mark(1, 1, 'x'); testBoard.mark(1, 2, 'x'); testBoard.mark(2, 0, 'x'); testBoard.mark(2, 1, 'x'); testBoard.mark(2, 2, 'x'); assertEquals(true, testBoard.isFull()); }
@Test public void testN() { Queens q = new Queens(); for (Board board : q.findSolution(8).all()) { if (!board.isFull()) continue; int arr[] = board.pos; System.out.println(board); for (int y = 0; y < arr.length; y++) { for (int x = 0; x < arr.length; x++) { System.out.print((arr[x] == y) ? "Q " : "_ "); } System.out.println(); } System.out.println(); } }
// MF Re-enable all this once you have the AJAX working // LV That would be now. Took some time to get all the errors out. Sure it could be implemented // better and more Java-like. public static Integer[] minMax(int p, Board b, int d) { // p: player designation // b: current board state // d: iteration depth Integer score = getScore(b, p); // some game states do not require any thinking (e.g. already lost or won) if (d == 0) return new Integer[] {null, score}; // max depth reached. just return the score. if (score == -WIN_SCORE) return new Integer[] {null, score}; // we lose, not good. if (score == WIN_SCORE) return new Integer[] {null, score}; // we win, good. if (b.isFull()) return new Integer[] {null, 8888}; // board is full, pretty good, but not as good as winning. if (moveCache == null) { System.out.println("moveCache was null."); moveCache = new Hashtable<String, Integer[]>(); } // LV See if we can get the next move from the cache. // System.out.println(d+": "+b.getHash()); if (moveCache.containsKey(b.getHash())) { Integer[] c = moveCache.get(b.getHash()); // System.out.println("cache possible for hash = " + b.getHash()); if (c[0] >= (Integer) d) { // System.out.println("cache hit!"); return new Integer[] {c[1], c[2]}; } } // LV No cache. /* // simple optimization attempt. look ahead two moves to see if win or lose possible. // this prevents the algorithm from exploring parts of the state space that are unrealistic to occur. if (d > 2) { for (int q = 0; q < b.getSize(); ++q) { // for each possible move. Board n = b.clone(); // copy current state. if (n.playColumn(q)) { // make move. Integer[] qs = minMax(p,n,2); // look ahead one move. if (qs[1] == WIN_SCORE || qs[1] == -WIN_SCORE) { return new Integer[] {q,qs[1]}; // if I win or lose, stop exploring. }}}} */ // algorithm considers best and worst possible moves in one loop to save lines of code. Integer maxv = 0; // best score. Integer maxc = -1; // column where best score occurs. Integer minv = 999999; // worst score. Integer minc = -1; // colum where worst score occurs. for (int q = 0; q < b.getSize(); ++q) { // for each possible move. Board n = b.clone(); // copy current state. if (n.playColumn(q)) { // make move. Integer[] next = minMax(p, n, d - 1); // look ahead d-1 moves. if (maxc == -1 || next[1] > maxv) { maxc = q; maxv = next[1]; } // compare to previous best. if (minc == -1 || next[1] < minv) { minc = q; minv = next[1]; } // compare to previous worst. } } if (b.getTurn() == p) { // if it is our turn. moveCache.put(b.getHash(), new Integer[] {d, maxc, maxv / 2 + score / 2}); return new Integer[] {maxc, maxv / 2 + score / 2}; // make best possible move. } else { // otherwise. moveCache.put(b.getHash(), new Integer[] {d, minc, minv / 2 + score / 2}); return new Integer[] {minc, minv / 2 + score / 2}; // make worst possible move. } }
@Test public void testIfBoardIsFull2() { Board testBoard = new Board(); assertEquals(false, testBoard.isFull()); }