Fixes?
This commit is contained in:
parent
0b528baa8b
commit
bd0fc7edfd
|
@ -8,7 +8,7 @@
|
||||||
</list>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_18" default="true" project-jdk-name="11" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/out" />
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
|
@ -4,10 +4,20 @@
|
||||||
<option name="autoReloadType" value="SELECTIVE" />
|
<option name="autoReloadType" value="SELECTIVE" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="41395b4b-3252-492c-a869-5f4dab107186" name="Changes" comment="Small fixes">
|
<list default="true" id="41395b4b-3252-492c-a869-5f4dab107186" name="Changes" comment="AI">
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/IPawn.java" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/MovingBoard.java" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/MovingPawn.java" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/MovingPushed.java" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/MovingPusher.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/.idea/misc.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/main/java/laboratoire4/Client.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/Client.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/main/java/laboratoire4/Client.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/Client.java" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/main/java/laboratoire4/MiniMax.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/MiniMax.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/main/java/laboratoire4/MiniMax.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/MiniMax.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/main/java/laboratoire4/Pawn.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/Pawn.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/main/java/laboratoire4/Player.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/Player.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/main/java/laboratoire4/Pushed.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/Pushed.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/main/java/laboratoire4/Pusher.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/Pusher.java" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/main/java/laboratoire4/PusherBoard.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/PusherBoard.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/main/java/laboratoire4/PusherBoard.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/laboratoire4/PusherBoard.java" afterDir="false" />
|
||||||
</list>
|
</list>
|
||||||
<list id="98b8a79f-2f53-42bf-96da-7af322697a0d" name="Changes by acastonguay" comment="" />
|
<list id="98b8a79f-2f53-42bf-96da-7af322697a0d" name="Changes by acastonguay" comment="" />
|
||||||
|
@ -20,13 +30,14 @@
|
||||||
<option name="RECENT_TEMPLATES">
|
<option name="RECENT_TEMPLATES">
|
||||||
<list>
|
<list>
|
||||||
<option value="Class" />
|
<option value="Class" />
|
||||||
|
<option value="Interface" />
|
||||||
</list>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="Git.Settings">
|
<component name="Git.Settings">
|
||||||
<option name="RECENT_BRANCH_BY_REPOSITORY">
|
<option name="RECENT_BRANCH_BY_REPOSITORY">
|
||||||
<map>
|
<map>
|
||||||
<entry key="$PROJECT_DIR$" value="alexis" />
|
<entry key="$PROJECT_DIR$" value="master" />
|
||||||
</map>
|
</map>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
|
@ -43,6 +54,9 @@
|
||||||
</MavenImportingSettings>
|
</MavenImportingSettings>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
|
<component name="ProblemsViewState">
|
||||||
|
<option name="selectedTabId" value="ProjectErrors" />
|
||||||
|
</component>
|
||||||
<component name="ProjectId" id="2NFN0RGJNNJqiDmt34ixVwkIwEm" />
|
<component name="ProjectId" id="2NFN0RGJNNJqiDmt34ixVwkIwEm" />
|
||||||
<component name="ProjectLevelVcsManager" settingsEditedManually="true">
|
<component name="ProjectLevelVcsManager" settingsEditedManually="true">
|
||||||
<ConfirmationsSetting value="2" id="Add" />
|
<ConfirmationsSetting value="2" id="Add" />
|
||||||
|
@ -51,21 +65,21 @@
|
||||||
<option name="hideEmptyMiddlePackages" value="true" />
|
<option name="hideEmptyMiddlePackages" value="true" />
|
||||||
<option name="showLibraryContents" value="true" />
|
<option name="showLibraryContents" value="true" />
|
||||||
</component>
|
</component>
|
||||||
<component name="PropertiesComponent"><![CDATA[{
|
<component name="PropertiesComponent">{
|
||||||
"keyToString": {
|
"keyToString": {
|
||||||
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
||||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||||
"SHARE_PROJECT_CONFIGURATION_FILES": "true",
|
"SHARE_PROJECT_CONFIGURATION_FILES": "true",
|
||||||
"codeWithMe.voiceChat.enabledByDefault": "false",
|
"codeWithMe.voiceChat.enabledByDefault": "false",
|
||||||
"last_opened_file_path": "/home/william/Dev/Projects",
|
"last_opened_file_path": "/home/william/Dev/Projects",
|
||||||
"node.js.detected.package.eslint": "true",
|
"node.js.detected.package.eslint": "true",
|
||||||
"node.js.detected.package.tslint": "true",
|
"node.js.detected.package.tslint": "true",
|
||||||
"node.js.selected.package.eslint": "(autodetect)",
|
"node.js.selected.package.eslint": "(autodetect)",
|
||||||
"node.js.selected.package.tslint": "(autodetect)",
|
"node.js.selected.package.tslint": "(autodetect)",
|
||||||
"nodejs_package_manager_path": "npm",
|
"nodejs_package_manager_path": "npm",
|
||||||
"vue.rearranger.settings.migration": "true"
|
"vue.rearranger.settings.migration": "true"
|
||||||
}
|
}
|
||||||
}]]></component>
|
}</component>
|
||||||
<component name="RunManager" selected="Application.Main">
|
<component name="RunManager" selected="Application.Main">
|
||||||
<configuration name="Client" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
|
<configuration name="Client" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
|
||||||
<option name="MAIN_CLASS_NAME" value="laboratoire4.Client" />
|
<option name="MAIN_CLASS_NAME" value="laboratoire4.Client" />
|
||||||
|
@ -128,6 +142,8 @@
|
||||||
<workItem from="1679344371350" duration="4138000" />
|
<workItem from="1679344371350" duration="4138000" />
|
||||||
<workItem from="1679365557789" duration="21000" />
|
<workItem from="1679365557789" duration="21000" />
|
||||||
<workItem from="1679424430928" duration="11764000" />
|
<workItem from="1679424430928" duration="11764000" />
|
||||||
|
<workItem from="1679593788411" duration="10753000" />
|
||||||
|
<workItem from="1679672719638" duration="7700000" />
|
||||||
</task>
|
</task>
|
||||||
<task id="LOCAL-00001" summary="MiniMax">
|
<task id="LOCAL-00001" summary="MiniMax">
|
||||||
<created>1679263366439</created>
|
<created>1679263366439</created>
|
||||||
|
@ -164,13 +180,10 @@
|
||||||
</component>
|
</component>
|
||||||
<component name="XDebuggerManager">
|
<component name="XDebuggerManager">
|
||||||
<breakpoint-manager>
|
<breakpoint-manager>
|
||||||
<breakpoints>
|
<default-breakpoints>
|
||||||
<line-breakpoint enabled="true" type="java-line">
|
<breakpoint enabled="true" type="CidrExceptionBreakpoint" />
|
||||||
<url>file://$PROJECT_DIR$/src/main/java/laboratoire4/PusherBoard.java</url>
|
<breakpoint enabled="true" type="java-exception" />
|
||||||
<line>60</line>
|
</default-breakpoints>
|
||||||
<option name="timeStamp" value="7" />
|
|
||||||
</line-breakpoint>
|
|
||||||
</breakpoints>
|
|
||||||
</breakpoint-manager>
|
</breakpoint-manager>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
|
@ -76,7 +76,7 @@ public class Client {
|
||||||
board.move(previousMove);
|
board.move(previousMove);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Thread.sleep(1000);
|
Thread.sleep(500);
|
||||||
|
|
||||||
String nextMove = board.runNextMove();
|
String nextMove = board.runNextMove();
|
||||||
System.out.println("Prochain mouvement: " + nextMove);
|
System.out.println("Prochain mouvement: " + nextMove);
|
||||||
|
@ -85,15 +85,18 @@ public class Client {
|
||||||
output.flush();
|
output.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleInvalidMove() throws InterruptedException {
|
private void handleInvalidMove() throws InterruptedException, IOException {
|
||||||
System.err.println("Mouvement invalide!");
|
System.err.println("Mouvement invalide!");
|
||||||
Thread.sleep(500);
|
Thread.sleep(500);
|
||||||
board.printBoard();
|
|
||||||
|
PusherBoard.printBoard(board.getBoard());
|
||||||
|
|
||||||
|
// play();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stopGame() throws IOException {
|
private void stopGame() throws IOException {
|
||||||
System.out.println("GG well played!");
|
System.out.println("GG well played!");
|
||||||
socket.close();
|
// socket.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
package laboratoire4;
|
||||||
|
|
||||||
|
public interface IPawn {
|
||||||
|
boolean isMoveValid(IPawn[][] board, Pawn.PawnMovement movement);
|
||||||
|
void move(Pawn.PawnMovement movement);
|
||||||
|
boolean isPusher();
|
||||||
|
int getDirection();
|
||||||
|
Player getPlayer();
|
||||||
|
int getRow();
|
||||||
|
int getCol();
|
||||||
|
void setRow(int row);
|
||||||
|
void setCol(int col);
|
||||||
|
}
|
|
@ -1,125 +1,156 @@
|
||||||
package laboratoire4;
|
package laboratoire4;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
public class MiniMax {
|
public class MiniMax {
|
||||||
private static final int MAX_DEPTH = 2;
|
private static final int MAX_DEPTH = 1;
|
||||||
private static Random random = new Random();
|
|
||||||
|
|
||||||
public static MiniMaxResult miniMax(PusherBoard board) {
|
public static MiniMaxResult miniMax(PusherBoard board) {
|
||||||
return miniMax(board, true, 0, 0);
|
MovingBoard game = new MovingBoard(board.getBoard(), board.getPlayer());
|
||||||
|
return miniMax(game, true, 0, Integer.MIN_VALUE, Integer.MAX_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MiniMaxResult miniMax(PusherBoard board, boolean max, int depth, int alphaBeta) {
|
private static MiniMaxResult miniMax(MovingBoard game, boolean max, int depth, int alpha, int beta) {
|
||||||
int limScore = max ? Integer.MIN_VALUE : Integer.MAX_VALUE;
|
depth += 1;
|
||||||
List<Pawn> pawns = max ?
|
|
||||||
board.getMaxPawns() :
|
|
||||||
board.getMinPawns();
|
|
||||||
// Collections.shuffle(pawns);
|
|
||||||
|
|
||||||
List<MiniMaxResult> results = new ArrayList<>();
|
|
||||||
|
|
||||||
for (Pawn pawn : pawns) {
|
|
||||||
int originalRow = pawn.getRow();
|
|
||||||
int originalCol = pawn.getCol();
|
|
||||||
|
|
||||||
for (Pawn.PawnMovement movement : Pawn.PawnMovement.values()) {
|
|
||||||
if (pawn.isMoveValid(board, movement)) {
|
|
||||||
pawn.move(movement);
|
|
||||||
|
|
||||||
int nextAlphaBeta = max ? Math.max(limScore, alphaBeta) : Math.min(limScore, alphaBeta);
|
|
||||||
|
|
||||||
int score = evaluate(pawn, board, max);
|
|
||||||
if (depth < MAX_DEPTH) {
|
|
||||||
score = miniMax(board, !max, depth + 1, nextAlphaBeta).getScore();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((max && score > limScore) ||
|
|
||||||
(!max && score < limScore)) {
|
|
||||||
limScore = score;
|
|
||||||
}
|
|
||||||
|
|
||||||
MiniMaxResult result = new MiniMaxResult(limScore, pawn, movement);
|
|
||||||
|
|
||||||
//elagage alphaBeta
|
|
||||||
// if ((max && limScore > alphaBeta) ||
|
|
||||||
// (!max && limScore < alphaBeta)) {
|
|
||||||
// pawn.setRow(originalRow);
|
|
||||||
// pawn.setCol(originalCol);
|
|
||||||
//
|
|
||||||
// return result;
|
|
||||||
// }
|
|
||||||
|
|
||||||
results.add(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
pawn.setRow(originalRow);
|
|
||||||
pawn.setCol(originalCol);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Choisir aléatoirement
|
|
||||||
int index = random.nextInt(results.size());
|
|
||||||
return results.get(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int evaluate(Pawn pawn, PusherBoard board, boolean max) {
|
|
||||||
int score = didWin(pawn, max) + didCapture(pawn, board, max) + isPushed(pawn);
|
|
||||||
|
|
||||||
int homeRow = pawn.getPlayer() == Player.RED ? 0 : 7;
|
|
||||||
if (pawn.getRow() != homeRow) {
|
|
||||||
score += 50;
|
|
||||||
}
|
|
||||||
|
|
||||||
int direction = max ? 1 : -1;
|
|
||||||
return score * direction;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int isPushed(Pawn pawn) {
|
|
||||||
if (pawn instanceof Pushed) {
|
|
||||||
return 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int didWin(Pawn pawn, boolean max) {
|
|
||||||
int goal = pawn.getPlayer() == Player.RED ? 7 : 0;
|
|
||||||
|
|
||||||
if (pawn.getRow() == goal) {
|
|
||||||
return max ? 1000 : 100000;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int didCapture(Pawn pawn, PusherBoard board, boolean max) {
|
|
||||||
Pawn capturedPawn = board.getBoard()[pawn.getRow()][pawn.getCol()];
|
|
||||||
|
|
||||||
if (capturedPawn != null) {
|
|
||||||
if (capturedPawn.getPlayer() != pawn.getPlayer()) {
|
|
||||||
if (max) {
|
if (max) {
|
||||||
return capturedPawn instanceof Pusher ? 100 : 50;
|
return max(game, depth, alpha, beta);
|
||||||
} else {
|
}
|
||||||
return capturedPawn instanceof Pusher ? 10000 : 5000;
|
|
||||||
|
return min(game, depth, alpha, beta);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MiniMaxResult max(MovingBoard game, int depth, int alpha, int beta) {
|
||||||
|
int alphaT = Integer.MIN_VALUE;
|
||||||
|
MovingPawn lastPawn = null;
|
||||||
|
Pawn.PawnMovement lastMovement = null;
|
||||||
|
|
||||||
|
for (MovingPawn pawn : game.getMaxPawns()) {
|
||||||
|
for (Pawn.PawnMovement movement : Pawn.PawnMovement.values()) {
|
||||||
|
if (!pawn.isMoveValid(game.getBoard(), movement)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastPawn = pawn;
|
||||||
|
lastMovement = movement;
|
||||||
|
|
||||||
|
game.move(pawn, movement);
|
||||||
|
|
||||||
|
int score = evaluate(pawn, game, depth);
|
||||||
|
if (depth < MAX_DEPTH) {
|
||||||
|
score = miniMax(game, false, depth, Math.max(alpha, alphaT), beta).getScore();
|
||||||
|
}
|
||||||
|
|
||||||
|
game.revertMove();
|
||||||
|
|
||||||
|
if (score > alphaT) {
|
||||||
|
alphaT = score;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alphaT >= beta) {
|
||||||
|
return new MiniMaxResult(alphaT, pawn.getRow(), pawn.getCol(), movement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lastPawn == null) {
|
||||||
|
return new MiniMaxResult(alphaT, 0, 0, null);
|
||||||
|
}
|
||||||
|
return new MiniMaxResult(alphaT, lastPawn.getRow(), lastPawn.getCol(), lastMovement);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MiniMaxResult min(MovingBoard game, int depth, int alpha, int beta) {
|
||||||
|
int betaT = Integer.MAX_VALUE;
|
||||||
|
MovingPawn lastPawn = null;
|
||||||
|
Pawn.PawnMovement lastMovement = null;
|
||||||
|
|
||||||
|
for (MovingPawn pawn : game.getMinPawns()) {
|
||||||
|
for (Pawn.PawnMovement movement : Pawn.PawnMovement.values()) {
|
||||||
|
if (!pawn.isMoveValid(game.getBoard(), movement)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastPawn = pawn;
|
||||||
|
lastMovement = movement;
|
||||||
|
|
||||||
|
game.move(pawn, movement);
|
||||||
|
|
||||||
|
int score = evaluate(pawn, game, depth);
|
||||||
|
if (depth < MAX_DEPTH) {
|
||||||
|
score = miniMax(game, true, depth, alpha, Math.min(betaT, beta)).getScore();
|
||||||
|
}
|
||||||
|
|
||||||
|
game.revertMove();
|
||||||
|
|
||||||
|
if (score < betaT) {
|
||||||
|
betaT = score;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (betaT <= beta) {
|
||||||
|
return new MiniMaxResult(betaT, pawn.getRow(), pawn.getCol(), movement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastPawn == null) {
|
||||||
|
return new MiniMaxResult(betaT, 0, 0, null);
|
||||||
|
}
|
||||||
|
return new MiniMaxResult(betaT, lastPawn.getRow(), lastPawn.getCol(), lastMovement);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int evaluate(IPawn pawn, MovingBoard game, int depth) {
|
||||||
|
int score = didWin(pawn) + didCapture(pawn, game);
|
||||||
|
|
||||||
|
score += pawn.isPusher() ? 0 : 5;
|
||||||
|
|
||||||
|
int row = pawn.getRow();
|
||||||
|
int col = pawn.getCol();
|
||||||
|
int nextNextRow = row + pawn.getDirection() * 2;
|
||||||
|
|
||||||
|
// Attire nos pusher vers nos pushed
|
||||||
|
if (pawn.isPusher() && nextNextRow >= 0 && nextNextRow <= 7) {
|
||||||
|
for (Pawn.PawnMovement move : Pawn.PawnMovement.values()) {
|
||||||
|
int nextCol = col + move.getMove();
|
||||||
|
if (nextCol < 0 || nextCol > 7) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPawn nearPawn = game.getBoard()[nextNextRow][nextCol];
|
||||||
|
if (nearPawn != null && !nearPawn.isPusher() && nearPawn.getPlayer() == pawn.getPlayer()) {
|
||||||
|
score += 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return score * pawn.getDirection();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int didWin(IPawn pawn) {
|
||||||
|
if (pawn.getRow() == pawn.getPlayer().getGoal()) {
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int didCapture(IPawn pawn, MovingBoard game) {
|
||||||
|
IPawn capturedPawn = game.getBoard()[pawn.getRow()][pawn.getCol()];
|
||||||
|
|
||||||
|
if (capturedPawn != null && capturedPawn.getPlayer() != game.getPlayer()) {
|
||||||
|
return 500;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static class MiniMaxResult {
|
static class MiniMaxResult {
|
||||||
private final int score;
|
private final int score;
|
||||||
private final Pawn pawn;
|
private final int row;
|
||||||
|
private final int col;
|
||||||
private final Pawn.PawnMovement movement;
|
private final Pawn.PawnMovement movement;
|
||||||
|
|
||||||
public MiniMaxResult(int score, Pawn pawn, Pawn.PawnMovement movement) {
|
public MiniMaxResult(int score, int row, int col, Pawn.PawnMovement movement) {
|
||||||
this.score = score;
|
this.score = score;
|
||||||
this.pawn = pawn;
|
this.row = row;
|
||||||
|
this.col = col;
|
||||||
this.movement = movement;
|
this.movement = movement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,8 +158,12 @@ public class MiniMax {
|
||||||
return score;
|
return score;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Pawn getPawn() {
|
public int getRow() {
|
||||||
return pawn;
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCol() {
|
||||||
|
return col;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Pawn.PawnMovement getMovement() {
|
public Pawn.PawnMovement getMovement() {
|
||||||
|
@ -139,7 +174,8 @@ public class MiniMax {
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "MiniMaxResult{" +
|
return "MiniMaxResult{" +
|
||||||
"score=" + score +
|
"score=" + score +
|
||||||
", pawn=" + pawn +
|
", col=" + col +
|
||||||
|
", row=" + row +
|
||||||
", movement=" + movement +
|
", movement=" + movement +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
package laboratoire4;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Stack;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
public class MovingBoard {
|
||||||
|
private final MovingPawn[][] board;
|
||||||
|
private final Player player;
|
||||||
|
|
||||||
|
private final Stack<MovingPawn> removedPawns = new Stack<>();
|
||||||
|
private final Stack<MovingPawn> previousMovedPawns = new Stack<>();
|
||||||
|
|
||||||
|
public MovingBoard(Pawn[][] board, Player player) {
|
||||||
|
this.board = asMovingPawns(board);
|
||||||
|
this.player = player;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void move(MovingPawn pawn, Pawn.PawnMovement movement) {
|
||||||
|
int toRow = pawn.getRow() + pawn.getDirection();
|
||||||
|
int toCol = pawn.getCol() + movement.getMove();
|
||||||
|
MovingPawn capturedPawn = board[toRow][toCol];
|
||||||
|
|
||||||
|
previousMovedPawns.push(pawn);
|
||||||
|
removedPawns.push(capturedPawn);
|
||||||
|
|
||||||
|
board[pawn.getRow()][pawn.getCol()] = null;
|
||||||
|
board[toRow][toCol] = pawn;
|
||||||
|
pawn.move(movement);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void revertMove() {
|
||||||
|
MovingPawn pawn = previousMovedPawns.pop();
|
||||||
|
MovingPawn capturedPawn = removedPawns.pop();
|
||||||
|
|
||||||
|
board[pawn.getRow()][pawn.getCol()] = capturedPawn;
|
||||||
|
|
||||||
|
pawn.revertMove();
|
||||||
|
board[pawn.getRow()][pawn.getCol()] = pawn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MovingPawn[][] getBoard() {
|
||||||
|
return board;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Player getPlayer() {
|
||||||
|
return player;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<MovingPawn> getMaxPawns() {
|
||||||
|
return getPawns(p -> p.getPlayer() == player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<MovingPawn> getMinPawns() {
|
||||||
|
return getPawns(p -> p.getPlayer() != player);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Collection<MovingPawn> getPawns(Predicate<MovingPawn> predicate) {
|
||||||
|
List<MovingPawn> pawns = new ArrayList<>();
|
||||||
|
for (MovingPawn[] row : board) {
|
||||||
|
for (MovingPawn pawn : row) {
|
||||||
|
if (pawn != null && predicate.test(pawn)) {
|
||||||
|
pawns.add(pawn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pawns;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MovingPawn[][] asMovingPawns(Pawn[][] board) {
|
||||||
|
MovingPawn[][] to = new MovingPawn[board.length][board.length];
|
||||||
|
for (int row = 0; row < board.length; row++) {
|
||||||
|
for (int col = 0; col < board.length; col++) {
|
||||||
|
if (board[row][col] == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
MovingPawn pawn = MovingPawn.from(board[row][col]);
|
||||||
|
to[row][col] = pawn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package laboratoire4;
|
||||||
|
|
||||||
|
public interface MovingPawn extends IPawn {
|
||||||
|
void revertMove();
|
||||||
|
|
||||||
|
static MovingPawn from(Pawn pawn) {
|
||||||
|
if (pawn instanceof Pusher) {
|
||||||
|
return new MovingPusher(pawn.getPlayer(), pawn.getRow(), pawn.getCol());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new MovingPushed(pawn.getPlayer(), pawn.getRow(), pawn.getCol());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
package laboratoire4;
|
||||||
|
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
|
public class MovingPushed extends Pushed implements MovingPawn {
|
||||||
|
private final Stack<PawnMovement> previousMoves = new Stack<>();
|
||||||
|
|
||||||
|
public MovingPushed(Player player, int row, int col) {
|
||||||
|
super(player, row, col);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void move(PawnMovement movement) {
|
||||||
|
super.move(movement);
|
||||||
|
previousMoves.push(movement);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void revertMove() {
|
||||||
|
PawnMovement move = previousMoves.pop();
|
||||||
|
setRow(row - getDirection());
|
||||||
|
setCol(col - move.getMove());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package laboratoire4;
|
||||||
|
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
|
public class MovingPusher extends Pusher implements MovingPawn {
|
||||||
|
private final Stack<PawnMovement> previousMoves = new Stack<>();
|
||||||
|
|
||||||
|
public MovingPusher(Player player, int row, int col) {
|
||||||
|
super(player, row, col);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void move(PawnMovement movement) {
|
||||||
|
previousMoves.push(movement);
|
||||||
|
super.move(movement);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void revertMove() {
|
||||||
|
PawnMovement move = previousMoves.pop();
|
||||||
|
setRow(row - getDirection());
|
||||||
|
setCol(col - move.getMove());
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,20 +1,18 @@
|
||||||
package laboratoire4;
|
package laboratoire4;
|
||||||
|
|
||||||
public abstract class Pawn {
|
public abstract class Pawn implements IPawn {
|
||||||
protected final Player player;
|
protected final Player player;
|
||||||
protected int row;
|
protected int row;
|
||||||
protected int col;
|
protected int col;
|
||||||
protected int direction;
|
|
||||||
|
|
||||||
public Pawn(Player player, int row, int col) {
|
public Pawn(Player player, int row, int col) {
|
||||||
this.player = player;
|
this.player = player;
|
||||||
this.row = row;
|
this.row = row;
|
||||||
this.col = col;
|
this.col = col;
|
||||||
this.direction = player == Player.RED ? 1 : -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void move(PawnMovement movement) {
|
public void move(PawnMovement movement) {
|
||||||
setRow(row + direction);
|
setRow(row + player.getDirection());
|
||||||
setCol(col + movement.move);
|
setCol(col + movement.move);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,12 +42,10 @@ public abstract class Pawn {
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getDirection() {
|
public int getDirection() {
|
||||||
return direction;
|
return player.getDirection();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMoveValid(PusherBoard game, PawnMovement movement) {
|
public boolean isMoveValid(IPawn[][] board, PawnMovement movement) {
|
||||||
Pawn[][] board = game.getBoard();
|
|
||||||
|
|
||||||
int nextRow = row + getDirection();
|
int nextRow = row + getDirection();
|
||||||
if (nextRow < 0 || nextRow >= board.length) {
|
if (nextRow < 0 || nextRow >= board.length) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -60,10 +56,10 @@ public abstract class Pawn {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return isMoveValid(board, movement);
|
return isMoveReallyValid(board, movement);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract boolean isMoveValid(Pawn[][] board, PawnMovement movement);
|
protected abstract boolean isMoveReallyValid(IPawn[][] board, PawnMovement movement);
|
||||||
|
|
||||||
enum PawnMovement {
|
enum PawnMovement {
|
||||||
STRAIGHT(0),
|
STRAIGHT(0),
|
||||||
|
|
|
@ -1,6 +1,22 @@
|
||||||
package laboratoire4;
|
package laboratoire4;
|
||||||
|
|
||||||
public enum Player {
|
public enum Player {
|
||||||
BLACK,
|
BLACK(-1, 0),
|
||||||
RED
|
RED(1, 7);
|
||||||
|
|
||||||
|
private int direction;
|
||||||
|
private int goal;
|
||||||
|
|
||||||
|
Player(int direction, int goal) {
|
||||||
|
this.direction = direction;
|
||||||
|
this.goal = goal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDirection() {
|
||||||
|
return direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGoal() {
|
||||||
|
return goal;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,29 +6,31 @@ public class Pushed extends Pawn {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isMoveValid(Pawn[][] board, PawnMovement movement) {
|
public boolean isPusher() {
|
||||||
Pawn pusher = null;
|
return false;
|
||||||
Pawn to = board[row + direction][col + movement.getMove()];
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isMoveReallyValid(IPawn[][] board, PawnMovement movement) {
|
||||||
|
int direction = getDirection();
|
||||||
|
IPawn pusher = null;
|
||||||
|
IPawn to = board[row + direction][col + movement.getMove()];
|
||||||
|
|
||||||
if (col > 0 && movement == PawnMovement.RIGHT_DIAGONAL) {
|
if (col > 0 && movement == PawnMovement.RIGHT_DIAGONAL) {
|
||||||
pusher = board[row - direction][col - 1];
|
pusher = board[row - direction][col - movement.getMove()];
|
||||||
} else if (col < board.length - 1 && movement == PawnMovement.LEFT_DIAGONAL) {
|
} else if (col < board.length - 1 && movement == PawnMovement.LEFT_DIAGONAL) {
|
||||||
pusher = board[row - direction][col + 1];
|
pusher = board[row - direction][col - movement.getMove()];
|
||||||
} else if (movement == PawnMovement.STRAIGHT) {
|
} else if (movement == PawnMovement.STRAIGHT) {
|
||||||
pusher = board[row - direction][col];
|
pusher = board[row - direction][col];
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean pusherValid = pusher instanceof Pusher && pusher.player == player;
|
boolean pusherValid = pusher != null && pusher.isPusher() && pusher.getPlayer() == player;
|
||||||
boolean destinationValid = to == null || (movement != PawnMovement.STRAIGHT && to.player != this.player);
|
boolean destinationValid = to == null || (movement != PawnMovement.STRAIGHT && to.getPlayer() != this.player);
|
||||||
return pusherValid && destinationValid;
|
return pusherValid && destinationValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Pushed{" +
|
return String.format("Pushed{%s, %s}", player, getPosition());
|
||||||
player +
|
|
||||||
", " + col +
|
|
||||||
", " + row +
|
|
||||||
"} ";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,22 +6,27 @@ public class Pusher extends Pawn {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isMoveValid(Pawn[][] board, PawnMovement movement) {
|
public boolean isPusher() {
|
||||||
Pawn to = board[row + direction][col + movement.getMove()];
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isMoveReallyValid(IPawn[][] board, PawnMovement movement) {
|
||||||
|
IPawn to = board[getRow() + getDirection()][getCol() + movement.getMove()];
|
||||||
|
|
||||||
if (to == null) {
|
if (to == null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return to.player != this.player && movement != PawnMovement.STRAIGHT;
|
if (to.getPlayer() == player) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return movement != PawnMovement.STRAIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Pusher{" +
|
return String.format("Pusher{%s, %s}", player, getPosition());
|
||||||
player +
|
|
||||||
", " + col +
|
|
||||||
", " + row +
|
|
||||||
"} ";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,9 @@
|
||||||
package laboratoire4;
|
package laboratoire4;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class PusherBoard {
|
public class PusherBoard {
|
||||||
private final Player player;
|
private final Player player;
|
||||||
private Pawn[][] board;
|
private Pawn[][] board;
|
||||||
|
|
||||||
private final List<Pawn> maxPawns = new ArrayList<>();
|
|
||||||
private final List<Pawn> minPawns = new ArrayList<>();
|
|
||||||
|
|
||||||
public PusherBoard(Player player, String[] boardValues) {
|
public PusherBoard(Player player, String[] boardValues) {
|
||||||
this.player = player;
|
this.player = player;
|
||||||
|
|
||||||
|
@ -31,12 +25,6 @@ public class PusherBoard {
|
||||||
pawn = new Pushed(pawnPlayer, row, col);
|
pawn = new Pushed(pawnPlayer, row, col);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pawnPlayer == player) {
|
|
||||||
maxPawns.add(pawn);
|
|
||||||
} else {
|
|
||||||
minPawns.add(pawn);
|
|
||||||
}
|
|
||||||
|
|
||||||
board[row][col] = pawn;
|
board[row][col] = pawn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,89 +38,64 @@ public class PusherBoard {
|
||||||
|
|
||||||
public String runNextMove() {
|
public String runNextMove() {
|
||||||
MiniMax.MiniMaxResult result = MiniMax.miniMax(this);
|
MiniMax.MiniMaxResult result = MiniMax.miniMax(this);
|
||||||
Pawn pawn = result.getPawn();
|
Pawn pawn = board[result.getRow()][result.getCol()];
|
||||||
String initialPosition = pawn.getPosition();
|
|
||||||
|
|
||||||
System.out.println(result.getScore());
|
System.out.println(result.getScore());
|
||||||
|
|
||||||
|
String initialPosition = pawn.getPosition();
|
||||||
move(pawn, result.getMovement());
|
move(pawn, result.getMovement());
|
||||||
|
String nextPosition = pawn.getPosition();
|
||||||
|
|
||||||
|
return initialPosition + "-" + nextPosition;
|
||||||
return initialPosition + "-" + pawn.getPosition();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void move(String move) {
|
public void move(String move) {
|
||||||
//FORMAT ex : D2-D3
|
|
||||||
String[] split = move.trim().split(" - ");
|
String[] split = move.trim().split(" - ");
|
||||||
move(split[0], split[1]);
|
String from = split[0];
|
||||||
|
String to = split[1];
|
||||||
|
|
||||||
|
int fromCol = (int) from.charAt(0) - 65;
|
||||||
|
int fromRow = Integer.parseInt(String.valueOf(from.charAt(1))) - 1;
|
||||||
|
int toCol = (int) to.charAt(0) - 65;
|
||||||
|
|
||||||
|
Pawn.PawnMovement movement = Pawn.PawnMovement.from(toCol - fromCol);
|
||||||
|
move(fromRow, fromCol, movement);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void move(Pawn pawn, Pawn.PawnMovement movement) {
|
public void move(int row, int col, Pawn.PawnMovement movement) {
|
||||||
move(pawn.getCol(), pawn.getRow(), pawn.getCol() + movement.getMove(), pawn.getRow() + pawn.getDirection());
|
Pawn pawn = board[row][col];
|
||||||
}
|
if (pawn == null) {
|
||||||
|
|
||||||
public void move(String from, String to) {
|
|
||||||
//FORMAT ex : from {D2}, to {D3}
|
|
||||||
int from_col = (int) from.charAt(0) - 65;
|
|
||||||
int from_row = Integer.parseInt(String.valueOf(from.charAt(1))) - 1;
|
|
||||||
int to_col = (int) to.charAt(0) - 65;
|
|
||||||
int to_row = Integer.parseInt(String.valueOf(to.charAt(1))) - 1;
|
|
||||||
|
|
||||||
move(from_col, from_row, to_col, to_row);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void move(int from_col, int from_row, int to_col, int to_row) {
|
|
||||||
if (!isValid(from_col, from_row, to_col)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pawn pawn = board[from_row][from_col];
|
move(pawn, movement);
|
||||||
Pawn destPawn = board[to_row][to_col];
|
|
||||||
|
|
||||||
if (destPawn != null) {
|
|
||||||
if (destPawn.getPlayer() == player) {
|
|
||||||
maxPawns.remove(destPawn);
|
|
||||||
} else {
|
|
||||||
minPawns.remove(destPawn);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
board[from_row][from_col] = null;
|
private void move(Pawn pawn, Pawn.PawnMovement movement) {
|
||||||
board[to_row][to_col] = pawn;
|
// if (!pawn.isMoveValid(board, movement)) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
pawn.setRow(to_row);
|
int toRow = pawn.getRow() + pawn.getDirection();
|
||||||
pawn.setCol(to_col);
|
int toCol = pawn.getCol() + movement.getMove();
|
||||||
|
|
||||||
|
board[pawn.getRow()][pawn.getCol()] = null;
|
||||||
|
board[toRow][toCol] = pawn;
|
||||||
|
pawn.move(movement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Player getPlayer() {
|
||||||
private boolean isValid(int from_col, int from_row, int to_col) {
|
return player;
|
||||||
Pawn pawn = getBoard()[from_row][from_col];
|
|
||||||
Pawn.PawnMovement move = Pawn.PawnMovement.from(to_col - from_col);
|
|
||||||
|
|
||||||
if (pawn == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pawn.isMoveValid(this, move);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Pawn[][] getBoard() {
|
public Pawn[][] getBoard() {
|
||||||
return board;
|
return board;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Pawn> getMaxPawns() {
|
public static void printBoard(Pawn[][] board) {
|
||||||
return maxPawns;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Pawn> getMinPawns() {
|
|
||||||
return minPawns;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void printBoard() {
|
|
||||||
for (int i = 7; i >= 0; i--) {
|
for (int i = 7; i >= 0; i--) {
|
||||||
for (int j = 0; j < this.board.length; j++) {
|
for (int j = 0; j < board.length; j++) {
|
||||||
if (this.board[i][j] != null) {
|
if (board[i][j] != null) {
|
||||||
System.out.print(this.board[i][j] + " | ");
|
System.out.print(board[i][j] + " | ");
|
||||||
} else {
|
} else {
|
||||||
System.out.print(" | ");
|
System.out.print(" | ");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue