hanze/game-client

src/main/java/nl/isygameclient/models/games/Othello.java in modern-design
Repositories | Summary | Log | Files

Othello.java (5525B) download


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