game-client

Play TicTacToe and Reversi
Log | Files | Refs

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 }