188 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			188 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| package fr.iut_fbleau.HexGame;
 | |
| 
 | |
| import fr.iut_fbleau.GameAPI.*;
 | |
| import java.util.*;
 | |
| 
 | |
| /**
 | |
|  * Plateau du jeu de Hex.
 | |
|  *
 | |
|  * Joueur 1 relie la gauche et la droite.
 | |
|  * Joueur 2 relie le haut et le bas.
 | |
|  */
 | |
| public class HexBoard extends AbstractBoard {
 | |
| 
 | |
|     private final int size;
 | |
|     private Player[][] cells;
 | |
|     private Deque<AbstractPly> historyLocal;
 | |
| 
 | |
|     private static final int[][] NEIGHBORS = {
 | |
|         {-1,  0}, {+1,  0},
 | |
|         { 0, -1}, { 0, +1},
 | |
|         {-1, +1}, {+1, -1}
 | |
|     };
 | |
| 
 | |
|     public HexBoard(int size) {
 | |
|         super();
 | |
|         this.size = size;
 | |
|         this.cells = new Player[size][size];
 | |
|         this.historyLocal = new ArrayDeque<>();
 | |
|         this.currentPlayer = Player.PLAYER1;
 | |
|     }
 | |
| 
 | |
|     private boolean inBounds(int r, int c) {
 | |
|         return r >= 0 && r < size && c >= 0 && c < size;
 | |
|     }
 | |
| 
 | |
|     private Player getCell(int r, int c) {
 | |
|         return cells[r][c];
 | |
|     }
 | |
| 
 | |
|     private void setCell(int r, int c, Player p) {
 | |
|         cells[r][c] = p;
 | |
|     }
 | |
| 
 | |
|     private boolean hasPlayer1Won() {
 | |
|         boolean[][] visited = new boolean[size][size];
 | |
|         Deque<int[]> stack = new ArrayDeque<>();
 | |
|         for (int r = 0; r < size; r++) {
 | |
|             if (getCell(r, 0) == Player.PLAYER1) {
 | |
|                 visited[r][0] = true;
 | |
|                 stack.push(new int[]{r, 0});
 | |
|             }
 | |
|         }
 | |
|         while (!stack.isEmpty()) {
 | |
|             int[] cur = stack.pop();
 | |
|             int cr = cur[0];
 | |
|             int cc = cur[1];
 | |
|             if (cc == size - 1) return true;
 | |
|             for (int[] d : NEIGHBORS) {
 | |
|                 int nr = cr + d[0], nc = cc + d[1];
 | |
|                 if (inBounds(nr, nc) && !visited[nr][nc] && getCell(nr, nc) == Player.PLAYER1) {
 | |
|                     visited[nr][nc] = true;
 | |
|                     stack.push(new int[]{nr, nc});
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     private boolean hasPlayer2Won() {
 | |
|         boolean[][] visited = new boolean[size][size];
 | |
|         Deque<int[]> stack = new ArrayDeque<>();
 | |
|         for (int c = 0; c < size; c++) {
 | |
|             if (getCell(0, c) == Player.PLAYER2) {
 | |
|                 visited[0][c] = true;
 | |
|                 stack.push(new int[]{0, c});
 | |
|             }
 | |
|         }
 | |
|         while (!stack.isEmpty()) {
 | |
|             int[] cur = stack.pop();
 | |
|             int cr = cur[0];
 | |
|             int cc = cur[1];
 | |
|             if (cr == size - 1) return true;
 | |
|             for (int[] d : NEIGHBORS) {
 | |
|                 int nr = cr + d[0], nc = cc + d[1];
 | |
|                 if (inBounds(nr, nc) && !visited[nr][nc] && getCell(nr, nc) == Player.PLAYER2) {
 | |
|                     visited[nr][nc] = true;
 | |
|                     stack.push(new int[]{nr, nc});
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public boolean isLegal(AbstractPly move) {
 | |
|         if (!(move instanceof HexPly)) return false;
 | |
|         HexPly hp = (HexPly) move;
 | |
|         int r = hp.getRow(), c = hp.getCol();
 | |
|         return inBounds(r, c)
 | |
|                 && getCell(r, c) == null
 | |
|                 && hp.getPlayer() == this.getCurrentPlayer();
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public void doPly(AbstractPly move) {
 | |
|         if (!(move instanceof HexPly))
 | |
|             throw new IllegalArgumentException("Coup invalide: " + move);
 | |
|         HexPly hp = (HexPly) move;
 | |
|         if (!isLegal(hp))
 | |
|             throw new IllegalStateException("Coup illégal: " + hp);
 | |
|         setCell(hp.getRow(), hp.getCol(), hp.getPlayer());
 | |
|         historyLocal.push(hp);
 | |
|         setNextPlayer();
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public boolean isGameOver() {
 | |
|         return hasPlayer1Won() || hasPlayer2Won();
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public Result getResult() {
 | |
|         if (hasPlayer1Won()) return Result.WIN;
 | |
|         if (hasPlayer2Won()) return Result.LOSS;
 | |
|         return Result.DRAW;
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public Iterator<AbstractPly> getPlies() {
 | |
|         Player me = this.getCurrentPlayer();
 | |
|         List<AbstractPly> moves = new ArrayList<>();
 | |
|         for (int r = 0; r < size; r++) {
 | |
|             for (int c = 0; c < size; c++) {
 | |
|                 if (getCell(r, c) == null) moves.add(new HexPly(me, r, c));
 | |
|             }
 | |
|         }
 | |
|         return moves.iterator();
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public Iterator<AbstractPly> getHistory() {
 | |
|         return historyLocal.iterator();
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public void undoLastPly() {
 | |
|         if (historyLocal.isEmpty()) return;
 | |
|         HexPly last = (HexPly) historyLocal.pop();
 | |
|         setCell(last.getRow(), last.getCol(), null);
 | |
|         this.currentPlayer = last.getPlayer();
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public IBoard safeCopy() {
 | |
|         HexBoard copy = new HexBoard(this.size);
 | |
|         copy.currentPlayer = this.currentPlayer;
 | |
|         for (int r = 0; r < size; r++) {
 | |
|             for (int c = 0; c < size; c++) {
 | |
|                 copy.cells[r][c] = this.cells[r][c];
 | |
|             }
 | |
|         }
 | |
|         copy.historyLocal = new ArrayDeque<>(this.historyLocal);
 | |
|         return copy;
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public String toString() {
 | |
|         StringBuilder sb = new StringBuilder();
 | |
|         for (int r = 0; r < size; r++) {
 | |
|             for (int k = 0; k < r; k++) sb.append(" ");
 | |
|             for (int c = 0; c < size; c++) {
 | |
|                 Player p = getCell(r, c);
 | |
|                 char ch = '.';
 | |
|                 if (p == Player.PLAYER1) ch = '1';
 | |
|                 else if (p == Player.PLAYER2) ch = '2';
 | |
|                 sb.append(ch).append(" ");
 | |
|             }
 | |
|             sb.append("\n");
 | |
|         }
 | |
|         sb.append("Current player: ").append(getCurrentPlayer()).append("\n");
 | |
|         return sb.toString();
 | |
|     }
 | |
| 
 | |
|     public int getSize() {
 | |
|         return size;
 | |
|     }
 | |
| }
 |