Othello.java (4797B)
1 package nl.isygameclient.models.games; 2 3 import java.util.*; 4 import java.util.stream.Collectors; 5 import nl.isygameclient.models.Game; 6 import nl.isygameclient.models.Player; 7 import nl.isygameclient.models.PlayerManager; 8 import nl.isygameclient.models.board.HistoryBoard; 9 import nl.isygameclient.util.Vector2D; 10 11 public class Othello extends Game { 12 13 public Othello(PlayerManager playerManager) { 14 super(playerManager, new HistoryBoard<>(8, 8)); 15 initializeBoard(); 16 } 17 18 @Override 19 public void restart() { 20 playerManager.restart(); 21 board.clear(); 22 initializeBoard(); 23 } 24 25 public void initializeBoard() { 26 board.set(playerManager.getCurrentPlayer(), new Vector2D<>(3, 4)); 27 board.set(playerManager.getCurrentPlayer(), new Vector2D<>(4, 3)); 28 playerManager.nextPlayer(); 29 board.set(playerManager.getCurrentPlayer(), new Vector2D<>(3, 3)); 30 board.set(playerManager.getCurrentPlayer(), new Vector2D<>(4, 4)); 31 playerManager.nextPlayer(); 32 } 33 34 @Override 35 public boolean isDraw() { 36 var scores = getScores(); 37 return scores.values().stream().distinct().count() == 1; 38 } 39 40 @Override 41 public boolean isGameOver() { 42 for (Player player : playerManager.getPlayers()) { 43 if (getValidMoves(player).size() > 0) { 44 return false; 45 } 46 } 47 return true; 48 } 49 50 @Override 51 public boolean isWinner(Player player) { 52 Player winner = null; 53 int score = 0; 54 for (Map.Entry<Player, Integer> entry : getScores().entrySet()) { 55 if (entry.getValue() > score) { 56 winner = entry.getKey(); 57 score = entry.getValue(); 58 } 59 } 60 return Objects.equals(player, winner); 61 } 62 63 64 @Override 65 public boolean move(Player player, Vector2D<Integer, Integer> pos) { 66 if (!isMoveValid(player, pos)) { 67 return false; 68 } 69 70 var flippable = checkNeighbours(player, pos); 71 72 Map<Vector2D<Integer, Integer>, Player> changes = flippable.stream().collect(Collectors.toMap(e -> e, e -> player)); 73 board.add(player, changes); 74 playerManager.nextPlayer(); 75 return true; 76 } 77 78 79 @Override 80 public boolean isMoveValid(Player player, Vector2D<Integer, Integer> pos) { 81 if (board.get(pos) != null) 82 return false; 83 84 var flippable = checkNeighbours(player, pos); 85 return !flippable.isEmpty(); 86 } 87 88 89 private List<Vector2D<Integer, Integer>> rangeContains(Player player, Vector2D<Integer, Integer> pos, Vector2D<Integer, Integer> dir) { 90 List<Vector2D<Integer, Integer>> flippable = new ArrayList<>(); 91 int x = pos.getX() + dir.getX(); 92 int y = pos.getY() + dir.getY(); 93 while (x >= 0 && x < board.getWidth() && y >= 0 && y < board.getHeight()) { 94 var newPos = new Vector2D<>(x, y); 95 flippable.add(newPos); 96 if (Objects.equals(board.get(newPos), player)) { 97 return flippable; 98 } else if (board.get(newPos) == null) { 99 return null; 100 } 101 x += dir.getX(); 102 y += dir.getY(); 103 } 104 return null; 105 } 106 107 108 private Set<Vector2D<Integer, Integer>> checkNeighbours(Player player, Vector2D<Integer, Integer> pos) { 109 Set<Vector2D<Integer, Integer>> flippable = new HashSet<>(); 110 for (int dx = -1; dx <= 1; dx++) { 111 if ((pos.getX() + dx) < 0 || (pos.getX() + dx) >= board.getWidth()) 112 continue; 113 114 for (int dy = -1; dy <= 1; dy++) { 115 if ((pos.getY() + dy) < 0 || (pos.getY() + dy) >= board.getHeight()) 116 continue; 117 118 if (dx == 0 && dy == 0) 119 continue; 120 121 var checkPos = board.get(new Vector2D<>(pos.getX() + dx, pos.getY() + dy)); 122 if (checkPos != null && checkPos != player) { 123 List<Vector2D<Integer, Integer>> flip = rangeContains(player, pos, new Vector2D<>(dx, dy)); 124 if (flip != null) 125 flippable.addAll(flip); 126 } 127 } 128 } 129 if (!flippable.isEmpty()) { 130 flippable.add(pos); 131 } 132 return flippable; 133 } 134 135 @Override 136 public List<Vector2D<Integer, Integer>> getValidMoves(Player player) { 137 List<Vector2D<Integer, Integer>> valid = new ArrayList<>(); 138 for (int y = 0; y < board.getHeight(); y++) { 139 for (int x = 0; x < board.getWidth(); x++) { 140 if (isMoveValid(player, new Vector2D<>(x, y))) { 141 valid.add(new Vector2D<>(x, y)); 142 } 143 } 144 } 145 return valid; 146 } 147 148 @Override 149 public List<Player> getWinners() { 150 ArrayList<Player> winners = new ArrayList<>(); 151 for (Player player : playerManager.getPlayers()) { 152 if (isWinner(player)) { 153 winners.add(player); 154 } 155 } 156 return winners; 157 } 158 159 @Override 160 public int getPlayerScore(Player player) { 161 int score = 0; 162 for (int y = 0; y < board.getHeight(); y++) { 163 for (int x = 0; x < board.getWidth(); x++) { 164 if (Objects.equals(player, board.get(new Vector2D<>(x, y)))) { 165 score += 1; 166 } 167 } 168 } 169 return score; 170 } 171 172 private HashMap<Player, Integer> getScores() { 173 HashMap<Player, Integer> scores = new HashMap<>(); 174 for (Player player : playerManager.getPlayers()) { 175 int score = getPlayerScore(player); 176 scores.put(player, score); 177 } 178 return scores; 179 } 180 }