Skip to content

Commit d1bc359

Browse files
committed
Brute force algorithm implemented
1 parent 7325479 commit d1bc359

File tree

1 file changed

+198
-0
lines changed

1 file changed

+198
-0
lines changed
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
package main.java.codingame.TicTacToe;
2+
3+
import java.io.BufferedReader;
4+
import java.io.IOException;
5+
import java.io.InputStreamReader;
6+
7+
public class TicTacToe {
8+
public static void main(String args[]) throws IOException {
9+
final BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
10+
final BruteForceAlgorithm bruteForceAlgorithm = new BruteForceAlgorithm();
11+
final Board[][] boards = new Board[3][3];
12+
for (int i = 0; i < boards.length; i++) {
13+
for (int j = 0; j < boards[i].length; j++) {
14+
boards[i][j] = new Board();
15+
}
16+
}
17+
while (true) {
18+
String line[] = in.readLine().split(" ");
19+
final int opponentRow = Integer.parseInt(line[0]), opponentCol = Integer.parseInt(line[1]);
20+
if (opponentCol >= 0) {
21+
Board opponentBoard = boards[opponentRow / 3][opponentCol / 3];
22+
opponentBoard.play(0, (opponentRow % 3) * 3 + opponentCol % 3);
23+
System.err.println(opponentBoard);
24+
System.err.println((opponentRow / 3) + " " + (opponentCol / 3));
25+
}
26+
final int validActionCount = Integer.parseInt(in.readLine());
27+
Board board = boards[0][0];
28+
int bRow = 0, bCol = 0;
29+
for (int i = 0; i < validActionCount; i++) {
30+
line = in.readLine().split(" ");
31+
bRow = Integer.parseInt(line[0]);
32+
bCol = Integer.parseInt(line[1]);
33+
board = boards[bRow / 3][bCol / 3];
34+
}
35+
final int bestMove = bruteForceAlgorithm.findBestMove(board);
36+
final int row = bestMove / 3, col = bestMove % 3;
37+
board.play(1, bestMove);
38+
System.out.println(((bRow / 3) * 3 + row) + " " + ((bCol / 3) * 3 + col));
39+
System.err.println(board);
40+
}
41+
}
42+
}
43+
44+
class BruteForceAlgorithm {
45+
public int findBestMove(Board board) {
46+
for (int i = 0; i < 9; i++) {
47+
if ((board.occupied & (1 << i)) == 0) {
48+
board.play(1, i);
49+
final boolean result = board.result(1);
50+
board.undo(1, i);
51+
if (result) {
52+
return i;
53+
}
54+
}
55+
}
56+
for (int i = 0; i < 9; i++) {
57+
if ((board.occupied & (1 << i)) == 0) {
58+
board.play(0, i);
59+
final boolean result = board.result(0);
60+
board.undo(0, i);
61+
if (result) {
62+
return i;
63+
}
64+
}
65+
}
66+
for (int i = 0; i < 9; i++) {
67+
if ((board.occupied & (1 << i)) == 0) {
68+
board.play(1, i);
69+
int waysToWin = 0;
70+
for (int j = 0; j < 9; j++) {
71+
if ((board.occupied & (1 << j)) == 0) {
72+
board.play(1, j);
73+
if (board.result(1)) {
74+
waysToWin++;
75+
}
76+
board.undo(1, j);
77+
}
78+
}
79+
board.undo(1, i);
80+
if (waysToWin > 1) {
81+
return i;
82+
}
83+
}
84+
}
85+
int forks = 0;
86+
int block = -1;
87+
for (int i = 0; i < 9; i++) {
88+
if ((board.occupied & (1 << i)) == 0) {
89+
board.play(1, i);
90+
int waysToWin = 0;
91+
for (int j = 0; j < 9; j++) {
92+
if ((board.occupied & (1 << j)) == 0) {
93+
board.play(0, j);
94+
if (board.result(0)) {
95+
waysToWin++;
96+
}
97+
board.undo(0, j);
98+
}
99+
}
100+
board.undo(1, i);
101+
if (waysToWin > 1) {
102+
forks++;
103+
block = i;
104+
}
105+
}
106+
}
107+
if (forks > 1) {
108+
for (int i = 0; i < 9; i++) {
109+
if ((board.occupied & (1 << i)) == 0) {
110+
board.play(1, i);
111+
int waysToWin = 0;
112+
for (int j = 0; j < 9; j++) {
113+
if ((board.occupied & (1 << j)) == 0) {
114+
board.play(1, j);
115+
if (board.result(1)) {
116+
waysToWin++;
117+
}
118+
board.undo(1, j);
119+
}
120+
}
121+
board.undo(1, i);
122+
if (waysToWin == 1) {
123+
return i;
124+
}
125+
}
126+
}
127+
} else if (forks == 1) {
128+
return block;
129+
}
130+
if ((board.occupied & 16) == 0) {
131+
return 4;
132+
}
133+
int bestMove = -1;
134+
int bestValue = Integer.MIN_VALUE;
135+
for (int i = 0; i < 9; i++) {
136+
if ((board.occupied & (1 << i)) == 0) {
137+
final int result = i / 3 == 2 || i % 3 == 2 ? 1 : 2;
138+
if (result > bestValue) {
139+
bestValue = result;
140+
bestMove = i;
141+
}
142+
}
143+
}
144+
return bestMove;
145+
}
146+
}
147+
148+
class Board {
149+
int occupied;
150+
int board;
151+
final int winningStates[] = new int[]{
152+
0b111_000_000,
153+
0b000_111_000,
154+
0b000_000_111,
155+
0b100_100_100,
156+
0b010_010_010,
157+
0b001_001_001,
158+
0b100_010_001,
159+
0b001_010_100
160+
};
161+
162+
public void play(final int player, final int p) {
163+
final int position = 1 << p;
164+
if ((occupied & position) != 0) {
165+
throw new IllegalStateException("Already occupied!" + p);
166+
}
167+
if (player == 1) {
168+
board = board | position;
169+
}
170+
occupied = occupied | position;
171+
}
172+
173+
public void undo(final int player, final int p) {
174+
final int position = 1 << p;
175+
if ((occupied & position) == 0) {
176+
throw new IllegalStateException("Not occupied!" + p);
177+
}
178+
if (player == 1) {
179+
board = board ^ position;
180+
}
181+
occupied = occupied ^ position;
182+
}
183+
184+
public boolean result(final int player) {
185+
final int boardForPlayer = player == 1 ? board : ~board;
186+
for (final int winningState : winningStates) {
187+
if (winningState == (boardForPlayer & occupied & winningState)) {
188+
return true;
189+
}
190+
}
191+
return false;
192+
}
193+
194+
@Override
195+
public String toString() {
196+
return "Occupied:" + Integer.toBinaryString(occupied) + "\nBoard:" + Integer.toBinaryString(board);
197+
}
198+
}

0 commit comments

Comments
 (0)