package murex.pop.dojo.solitaire; import static com.google.common.collect.FluentIterable.from; import java.util.ArrayList; import java.util.List; import com.google.common.base.Predicate; import com.google.common.collect.FluentIterable; public class IA { public static boolean hasSolution(final Boolean[] line) { return hasSolution(new Boolean[][] { line }); } public static boolean hasSolution(final Boolean[][] lines) { if (isSolved(lines)) { return true; } FluentIterable<Move> moves = getMoves(lines); if (moves.isEmpty()) { return false; } return moves.anyMatch(new Predicate<Move>() { @Override public boolean apply(Move move) { return hasSolution(move.applyTo(lines)); } }); } private static FluentIterable<Move> getMoves(Boolean[] line) { List<Move> moves = new ArrayList<Move>(); for (int i = 0; i < line.length - 2; i++) { if (canMoveRight(line, i)) { moves.add(new Move(i, i + 2)); } } for (int i = 2; i < line.length; i++) { if (canMoveLeft(line, i)) { moves.add(new Move(i, i - 2)); } } return from(moves); } private static boolean canMoveLeft(Boolean[] line, int i) { return line[i] && line[i - 1] && !line[i - 2]; } private static boolean canMoveRight(Boolean[] line, int i) { return line[i] && line[i + 1] && !line[i + 2]; } private static boolean isSolved(Boolean[][] lines) { int nbOfMarbles = 0; for (int i = 0; i < lines.length; i++) { for (int j = 0; j < lines[i].length; j++) { if(lines[i][j]) { nbOfMarbles++; } } } return nbOfMarbles <= 1; } private static class Move { final int startIndex; final int endIndex; public Move(int startIndex, int endIndex) { this.startIndex = startIndex; this.endIndex = endIndex; } private Boolean[] applyTo(Boolean[][] lines) { final Boolean[][] result = lines.clone(); final int jumpedIndex = (startIndex + endIndex) / 2; result[startIndex] = false; result[jumpedIndex] = false; result[endIndex] = true; return result; } } }