Othello.java (4805B) download
1package nl.isygameclient.models.games.othello;
2
3import java.util.*;
4import java.util.stream.Collectors;
5import nl.isygameclient.models.Game;
6import nl.isygameclient.models.Player;
7import nl.isygameclient.models.PlayerManager;
8import nl.isygameclient.models.board.HistoryBoard;
9import nl.isygameclient.util.Vector2D;
10
11public 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}