// Returns true if B wins public static boolean tryFirstMove(GridChar grid, int aKingLoc, int bKingLoc) { grid.setEntry(aKingLoc, '#'); grid.setEntry(bKingLoc, 'K'); boolean r = true; while (r) { // r = findLoserSquares(input.grid); r = reduceGrid(grid, bKingLoc); } for (Direction dir : Direction.values()) { Integer childIdx = grid.getIndex(bKingLoc, dir); if (childIdx == null) continue; char sq = grid.getEntry(childIdx); if (sq == 'V') { return true; } if (sq == '#' || sq == 'T') { continue; } // int size = 1 + getConnectedSquareCount(grid, childIdx); if (getConnectedSquareCount(grid, childIdx)) return true; // if (size % 2 == 0) { // return true; // } } return false; }
public static boolean reduceGrid(GridChar grid, final int kingLoc) { // Create a graph corresponding to grid GraphInt graph = new GraphInt(); int startingLoc = kingLoc; // getOpenNodeNextToKing(grid, kingLoc); Set<Integer> visitedNodes = Sets.newHashSet(); LinkedList<Integer> toVisit = new LinkedList<>(); toVisit.add(startingLoc); while (!toVisit.isEmpty()) { Integer loc = toVisit.poll(); if (visitedNodes.contains(loc)) continue; visitedNodes.add(loc); for (Direction dir : Direction.values()) { Integer childIdx = grid.getIndex(loc, dir); if (childIdx == null) continue; char sq = grid.getEntry(childIdx); if (sq == '#' || sq == 'K' || sq == 'V' || sq == 'T') continue; if (loc == kingLoc) // graph.addOneWayConnection(loc,childIdx); graph.addConnection(loc, childIdx); else graph.addConnection(loc, childIdx); toVisit.add(childIdx); } } ArticulationPoint ap = new ArticulationPoint(graph); // Find bridges List<Integer> artPoints = ap.getArticulationPoints(); for (Integer aPoint : artPoints) { if (aPoint == kingLoc) continue; Set<Integer> adjNodes = graph.getNeighbors(aPoint); Set<Integer> isolatedNodes = Sets.newHashSet(); Set<Integer> nonIsolatedNodes = Sets.newHashSet(); adjNodeLoop: for (Integer adjNode : adjNodes) { if (isolatedNodes.contains(adjNode) || nonIsolatedNodes.contains(adjNode)) continue; Set<Integer> nodes = GraphIntAlgorithms.getConnectedNodesWithoutNode(graph, adjNode, aPoint); // Isolated set must not contain other articulation points for (Integer aPointToTest : artPoints) { if (nodes.contains(aPointToTest)) { nonIsolatedNodes.addAll(nodes); continue adjNodeLoop; } } if (!nodes.contains(startingLoc)) { isolatedNodes = nodes; break; } } // No suitable isolated set found, continue to next articulation point if (isolatedNodes == null || isolatedNodes.isEmpty()) continue; if (isolatedNodes.size() % 2 == 0) { // All the isolated nodes are traps for (Integer isoNode : isolatedNodes) { grid.setEntry(isoNode, 'T'); } return true; } else { // The articulation point itself is a trap, as moving to it means // the other player can move into an odd numbered field, which is always // losing grid.setEntry(aPoint, 'T'); return true; } } return false; }