Java tutorial
/* * Copyright (C) 2010 Gregor Trefs, Dominique Ritze * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package de.gtrefs.ai.ludo.model; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; import com.google.common.base.Throwables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import de.gtrefs.ai.ludo.model.Game.Color; /** * Represents the board of the ludo game. * <p> * It consists * further enables the {@link de.gtrefs.ai.ludo.model.Game Game} to introduce * new players to the board. After introduction, a player has a path and pawns, * which then can be used by the {@link de.gtrefs.ai.ludo.model.Player Player} * to play Ludo. * * @author gtrefs */ public class Board { private static final int NUMBER_OF_BOARD_FIELDS = 36; private static final int NUMBER_OF_BOARD_FIELDS_PER_CORNER = 9; private Map<Game.Color, List<StartField>> startFieldsByColor; private Map<Game.Color, BeginField> beginFieldsByColor; private Map<Game.Color, List<EndField>> endFieldsByColor; private Map<Game.Color, List<Field>> fieldsSortedByColor; private List<Field> boardFields; private Map<Game.Color, List<Pawn>> pawnsByColor; private Map<Game.Color, Player> playersByColor; public Board() { playersByColor = Maps.newEnumMap(Game.Color.class); buildBoard(); } private void buildBoard() { startFieldsByColor = buildFieldsByType(StartField.class); endFieldsByColor = buildFieldsByType(EndField.class); beginFieldsByColor = buildBeginFields(); fieldsSortedByColor = Maps.newEnumMap(Game.Color.class); boardFields = Lists.newArrayList(); buildFieldsSortedByColor(); createPawnsPerColor(); } private void createPawnsPerColor() { pawnsByColor = Arrays.stream(Game.Color.values()).collect(Collectors.toMap(color -> color, color -> Stream.generate(Pawn::new).limit(4).collect(Collectors.toList()))); } private Map<Color, BeginField> buildBeginFields() { return Arrays.stream(Game.Color.values()) .collect(Collectors.toMap(color -> color, color -> new BeginField())); } private void buildFieldsSortedByColor() { buildBoardFieldsInterleavedByBeginFields(); sortBoardFieldsSpecificToEachColor(); } private void buildBoardFieldsInterleavedByBeginFields() { int colorIndex = 0; for (int i = 0; i < NUMBER_OF_BOARD_FIELDS; i++) { if (i % NUMBER_OF_BOARD_FIELDS_PER_CORNER == 0) { boardFields.add( beginFieldsByColor.get(Game.Color.values()[colorIndex++ % Game.Color.values().length])); } boardFields.add(new BoardField()); } } private void sortBoardFieldsSpecificToEachColor() { int offset = 0; for (Game.Color color : Game.Color.values()) { List<Field> listSpecificToColor = Lists.newArrayList(); IntStream.range(offset, offset + boardFields.size()) .forEach(i -> listSpecificToColor.add(boardFields.get(i % boardFields.size()))); fieldsSortedByColor.put(color, listSpecificToColor); offset += (NUMBER_OF_BOARD_FIELDS_PER_CORNER + 1); } } private <T> Map<Game.Color, List<T>> buildFieldsByType(Class<T> clazz) { return Arrays.stream(Game.Color.values()).collect(Collectors.toMap(color -> color, color -> Stream.generate(generate(clazz)).limit(4).collect(Collectors.toList()))); } private <T> Supplier<T> generate(Class<T> clazz) { return () -> { try { return clazz.newInstance(); } catch (Exception e) { throw Throwables.propagate(e); } }; } /** * Returns the pawns of a specific color. * @param color color of the pawns * @return the pawns of the provided color */ public List<Pawn> getPawnsByColor(Game.Color color) { return pawnsByColor.get(color); } /** * Registers a player to the board. If the color was previously chosen by * another player or the player's color property is null, a * {@link de.uni_mannheim.informatik.ai.ludo.exceptions.ColorException * ColorException} is thrown. After introduction, the player has a path, * pawns and is able to play the game. * * @param player * Player which wants to be introduced to this board. * @throws ColorException * if another player was previously introduced with the same * color or the the player's color property is null */ public void introducePlayer(Player player) { Game.Color playerColor = Optional.ofNullable(player.getColor()).orElseThrow(IllegalArgumentException::new); if (playersByColor.get(playerColor) != null) { throw new IllegalArgumentException( String.format("Player %s uses same color as another player.", player.getName())); } createAndAddPath(player, playerColor); addPawns(player, playerColor); placePawnsOnStartField(playerColor); playersByColor.put(playerColor, player); } private void createAndAddPath(Player owner, Game.Color color) { Path playerPath = new Path(fieldsSortedByColor.get(color), startFieldsByColor.get(color), endFieldsByColor.get(color)); owner.setPath(playerPath); playerPath.setOwner(owner); } private void addPawns(Player owner, Game.Color playerColor) { List<Pawn> colorPawns = getPawnsByColor(playerColor); colorPawns.forEach(pawn -> pawn.setOwner(owner)); owner.setPawns(colorPawns); } /** * Returns the player with the specific color. * @param color of the player * @return Player instance with the provided color */ public Player getPlayerByColor(Game.Color color) { return playersByColor.get(color); } /** * Sets all pawns of the participating players back on the start fields. */ public void reset() { clearBoardFields(); playersByColor.keySet().forEach(playerColor -> { clearStartAndEndFieldsOfColorFromPawns(playerColor); placePawnsOnStartField(playerColor); }); } private void clearBoardFields() { boardFields.forEach(f -> f.takePawnFromField()); } private void clearStartAndEndFieldsOfColorFromPawns(Game.Color color) { clearStartFields(color); clearEndFields(color); } private void clearEndFields(Game.Color color) { endFieldsByColor.get(color).forEach(e -> e.takePawnFromField()); } private void clearStartFields(Game.Color color) { startFieldsByColor.get(color).forEach(s -> s.takePawnFromField()); } private void placePawnsOnStartField(Game.Color color) { List<Pawn> pawns = pawnsByColor.get(color); List<StartField> startFields = startFieldsByColor.get(color); IntStream.range(0, 4).forEach(i -> startFields.get(i).placePawnOnField(pawns.get(i))); } }