hanze/game-client

src/main/java/nl/isygameclient/models/games/othello/Othello.java in tournament
Repositories | Summary | Log | Files

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}