-
-
Save kdridi/eeab9c28378b52a646fe11a65a46b7ea to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package matchstick; | |
import java.io.PrintWriter; | |
import java.io.StringWriter; | |
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.Scanner; | |
import competitive.programming.gametheory.ICancellableMove; | |
import competitive.programming.gametheory.IGame; | |
import competitive.programming.gametheory.IMoveGenerator; | |
import competitive.programming.gametheory.minimax.Minimax; | |
import competitive.programming.timemanagement.Timer; | |
import matchstick.Application.Game.Generator; | |
import matchstick.Application.Game.Move; | |
public class Application { | |
public static class Game implements IGame { | |
private final int[] values; | |
private final int max; | |
private final int players; | |
private final int player; | |
private Game(int[] values, int max, int players, int player) { | |
super(); | |
this.values = values; | |
this.max = max; | |
this.players = players; | |
this.player = player; | |
} | |
public void writeTo(PrintWriter s) { | |
final int size = 3 + 2 * values.length; | |
s.print(repeatChar(' ', 4)); | |
s.println(repeatChar('*', size)); | |
for (int i = 0; i < values.length; i++) { | |
final int length = values[i]; | |
final int half = (size - (length + 1)) / 2; | |
s.print(String.format("[%02d]", i + 1)); | |
s.print(repeatChar('*', 1)); | |
s.print(repeatChar(' ', half)); | |
s.print(repeatChar('|', length)); | |
s.print(repeatChar(' ', size - half - length - 2)); | |
s.print(repeatChar('*', 1)); | |
s.println(String.format("[%02d]", length)); | |
} | |
s.print(repeatChar(' ', 4)); | |
s.println(repeatChar('*', size)); | |
} | |
private String repeatChar(char c, int n) { | |
final StringBuffer buffer = new StringBuffer(); | |
while (n > 0) { | |
buffer.append(c); | |
n -= 1; | |
} | |
return buffer.toString(); | |
} | |
@Override | |
public String toString() { | |
final StringWriter w = new StringWriter(); | |
final PrintWriter writer = new PrintWriter(w); | |
writeTo(writer); | |
writer.close(); | |
return w.toString(); | |
} | |
public static Game createGame(int height, int max, int players) { | |
int values[] = new int[height]; | |
for (int i = 0; i < values.length; i++) | |
values[i] = 2 * i + 1; | |
return new Game(values, max, players, 0); | |
} | |
public static class Move implements ICancellableMove<Game> { | |
private final int line; | |
private final int count; | |
public Move(int line, int count) { | |
super(); | |
this.line = line; | |
this.count = count; | |
} | |
@Override | |
public Game execute(Game game) { | |
return next(game, 0 + 1); | |
} | |
private Game next(Game game, int direction) { | |
int values[] = new int[game.values.length]; | |
for (int i = 0; i < values.length; i++) { | |
values[i] = game.values[i]; | |
if (i == line) | |
values[i] -= count * direction; | |
if (values[i] < 0) | |
throw new RuntimeException("ERROR TOO LESS"); | |
if (values[i] > 2 * i + 1) | |
throw new RuntimeException("ERROR TOO MUCH"); | |
} | |
int max = game.max; | |
int players = game.players; | |
int player = (players + game.player + direction) % players; | |
return new Game(values, max, players, player); | |
} | |
@Override | |
public Game cancel(Game game) { | |
return next(game, 0 - 1); | |
} | |
} | |
public static class Generator implements IMoveGenerator<Move, Game> { | |
@Override | |
public List<Move> generateMoves(Game game) { | |
final List<Move> result = new ArrayList<>(); | |
for (int line = 0; line < game.values.length; line++) | |
for (int count = 1; count <= game.max && count <= game.values[line]; count++) | |
result.add(new Move(line, count)); | |
return result; | |
} | |
} | |
@Override | |
public int currentPlayer() { | |
return player; | |
} | |
@Override | |
public double[] evaluate(int depth) { | |
int count = 0; | |
for (int i = 0; i < values.length; i++) | |
count += values[i]; | |
double[] result = new double[players]; | |
for (int i = 0; i < result.length; i++) | |
result[i] = (count != 1) ? 0 : (i == player ? 0 - 1 : 0 + 1); | |
return result; | |
} | |
} | |
public static void main(String[] args) { | |
Scanner in = new Scanner(System.in); | |
Timer timer = new Timer(); | |
Game.Generator generator = new Generator(); | |
Game game = Game.createGame(5, 3, 2); | |
while (generator.generateMoves(game).isEmpty() == false) { | |
System.out.println(game.toString()); | |
Game.Move move = nextMove(in, timer, generator, game, game.currentPlayer() != 0); | |
game = move.execute(game); | |
} | |
} | |
private static Move nextMove(Scanner in, Timer timer, Generator generator, Game game, boolean ai) { | |
if (ai) { | |
timer.startTimer(1000 * 3600); | |
final Minimax<Move, Game> minimax = new Minimax<Game.Move, Game>(timer); | |
return minimax.best(game, generator, 0, 100); | |
} | |
Game.Move result = null; | |
final List<Move> moves = generator.generateMoves(game); | |
while (result == null) { | |
System.out.println("CHOOSE LINE: "); | |
final int line = in.nextInt() - 1; | |
System.out.println("CHOOSE COUNT: "); | |
final int count = in.nextInt(); | |
for (Game.Move move : moves) { | |
if (move.line == line && move.count == count) { | |
result = move; | |
break; | |
} | |
} | |
} | |
return result; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment