package Core;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
* Class that handles one iteration of the game
* and holds all informations of the current game
*/
public class Game {
/**
* Constants
*/
private final int PLAYER_RANGE = 1;
private final int MIN_FIELD = 0;
private final int INDEX_0 = 0;
/**
* Instance variables
*/
private Playboard playboard;
private Map<User, Player> users = new HashMap<User, Player>();
private List<User> usersList;
private int maxBoardIndex;
private LinkedList<Field> starting_fields = new LinkedList<>();
private Set<Field> explodedFields = new HashSet<>();
private int bombCounter;
private int explosionRadius;
private int boardSize;
private boolean gameOver = false;
private int maxSteps;
private long stepSleep;
/******* Constructor and Initializer *******/
/**
* Constructor
* @param usersList List of users that are playing the game
* @param boardSize Count of fields in X and Y direction of the playboard
* @param bombCounter Interations needed for a bomb to explode
* @param explosionRadius Count of fields a bomb causes to explode in every direction
* @param maxSteps Maximum amout of iteration till the game ends in a draw
* @param stepSleep Time to wait between each iteration
*/
public Game(List<User> usersList, int boardSize, int bombCounter, int explosionRadius, int maxSteps, long stepSleep) {
this.boardSize = boardSize;
this.maxBoardIndex = boardSize - PLAYER_RANGE;
this.bombCounter = bombCounter;
this.explosionRadius = explosionRadius;
this.maxSteps = maxSteps;
this.usersList = usersList;
this.stepSleep = stepSleep;
initializeBoard();
initializePlayers();
}
/**
* Initializes the player objects for the users
*/
private void initializePlayers() {
initializeStartingFields();
for (User user : usersList) {
this.users.put(user, new Player(user.getId(), starting_fields.pop()));
}
playboard.setPlayers(new HashSet<Player>(this.users.values()));
}
/**
* Initializes the fields where player start on
*/
private void initializeStartingFields() {
Field[][] board = playboard.getBoard();
starting_fields.add(board[MIN_FIELD][MIN_FIELD]);
starting_fields.add(board[maxBoardIndex][maxBoardIndex]);
starting_fields.add(board[maxBoardIndex][MIN_FIELD]);
starting_fields.add(board[MIN_FIELD][maxBoardIndex]);
}
/**
* Initializes the board the game will take place on
*/
private void initializeBoard() {
Field[][] board = new Field[boardSize][boardSize];
for (int i = 0; i < boardSize; i++) {
for (int j = 0; j < boardSize; j++) {
if (i % 2 == 1 && j % 2 == 1) {
board[i][j] = new Field(i, j, false, false);
} else {
board[i][j] = new Field(i, j);
}
}
}
this.playboard = new Playboard(board, maxSteps, explosionRadius, bombCounter);
}
/******* Getter *******/
/**
* Returns maximum amout of iteration till the game ends in a draw
* @return maxSteps
*/
public int getMaxSteps() {
return maxSteps;
}
/**
* Returns the amount of interations needed for a bomb to explode
* @return bombCounter
*/
public int getBombCounter() {
return bombCounter;
}
/**
* Returns the count of fields a bomb causes to explode in every direction
* @return explosionRadius
*/
public int getExplosionRadius() {
return explosionRadius;
}
/**
* Returns the count of fields in X and Y direction of the playboard
* @return explosionRadius
*/
public int getBoardSize() {
return boardSize;
}
/**
* Returns the list of users that are playing the game
* @return explosionRadius
*/
public List<User> getUsers(){
List<User> usersList = new ArrayList<>();
usersList.addAll(users.keySet());
return usersList;
}
/**
* Returns the playboard with every information about the current state of the game
* @return playboard
*/
public Playboard getPlayboard() {
return playboard;
}
/**
* Returns all fields that are affected by an explosion
* @return explodedFields
*/
public Set<Field> getExplodedFields() {
return explodedFields;
}
/**
* Is the game over?
* @return gameOver
*/
public boolean isGameOver() {
return gameOver;
}
/**
* Returns the time the game sleeps between every iteration
* @return stepSleep
*/
public long getStepSleep() {
return stepSleep;
}
/******* Public Methods *******/
/**
* Does a iteration of the game. Sleeps for a certain amount of time
* @throws InterruptedException
*/
public void doIteration() throws InterruptedException {
Thread.sleep(stepSleep);
playerActions();
updatePlayboard();
checkGameOver();
}
/******* Private Helpers *******/
/**
* Checks if the game is over
*/
private void checkGameOver() {
List<User> playersAlive = new ArrayList<>();
for (Entry<User, Player> entry : users.entrySet()) {
if (entry.getValue().isAlive()) {
playersAlive.add(entry.getKey());
}
}
if (playersAlive.size() == 1 && !gameOver) {
User player = playersAlive.get(INDEX_0);
player.won();
player.gameOver(true, playboard);
//gameOver(false) to everyone, who lost
for(Entry<User, Player> entry : users.entrySet()) {
if(entry.getKey() != player) {
entry.getKey().gameOver(false, playboard);
}
}
gameOver = true;
} else if (playersAlive.size() == 0 && !gameOver || playboard.getStepsLeft() == 0) {
for (User user : usersList) {
user.gameOver(false, playboard);
}
gameOver = true;
}
playboard.decreaseStepsLeft();
}
/**
* Executes all player actions
*/
private void playerActions() {
//Get the playboard only once
Playboard currentBoard = playboard.clone();
for (Entry<User, Player> entry : users.entrySet()) {
Player player = entry.getValue();
User user = entry.getKey();
switch (user.getAction(currentBoard)) {
case 1:
if (player.getY() - PLAYER_RANGE >= MIN_FIELD) {
setPlayerPosition(player.getX(), player.getY() - PLAYER_RANGE, player);
}
break;
case 2:
if (player.getY() + PLAYER_RANGE <= maxBoardIndex) {
setPlayerPosition(player.getX(), player.getY() + PLAYER_RANGE, player);
}
break;
case 3:
if (player.getX() - PLAYER_RANGE >= MIN_FIELD) {
setPlayerPosition(player.getX() - PLAYER_RANGE, player.getY(), player);
}
break;
case 4:
if (player.getX() + PLAYER_RANGE <= maxBoardIndex) {
setPlayerPosition(player.getX() + PLAYER_RANGE, player.getY(), player);
}
break;
case 5:
playboard.addBomb(bombCounter, player.getX(), player.getY(), explosionRadius, player.getId());
break;
default:
break;
}
user.resetMove();
}
}
/**
* Sets the position of a certain player to the coordinates x and y
* @param x
* @param y
* @param player
*/
private void setPlayerPosition(int x, int y, Player player) {
Field destination = playboard.getBoard()[x][y];
if (destination.isPassable()) {
player.setField(destination);
}
}
/**
* Updates the player isAlive status if a player is in an explosion
*/
private void updatePlayboard() {
explodedFields = explodingFields();
for (Player player : playboard.getPlayers()) {
for (Field field : explodedFields) {
if (player.getField().equals(field)) {
player.setAlive(false);
}
}
}
}
/**
* Calculates all fields that are exploding in this iteration and
* sets the counter of every bomb that is not exploding minus one
* @return
*/
private Set<Field> explodingFields() {
Set<Field> explodedFields = new HashSet<>();
Set<Bomb> bombs = playboard.getBombs();
explodedFields = chainExplosions(explodedFields);
Set<Bomb> bombsToRemove = new HashSet<>();
for (Bomb bomb : bombs) {
if (bomb.isExploded()) {
bomb.getField().setPassable(true);
bombsToRemove.add(bomb);
} else {
bomb.countDown();
}
}
bombs.removeAll(bombsToRemove);
playboard.setBombs(bombs);
return explodedFields;
}
/**
* Helper to calculate a chain explosion of a bomb
* @param explodedFields
* @return exploding fields from chainexplosion
*/
private Set<Field> chainExplosions(Set<Field> explodedFields) {
for (Bomb bomb : playboard.getBombs()) {
if (bomb.shouldExplode() || explodedFields.contains(bomb.getField()) && !bomb.isExploded()) {
explodedFields.addAll(bomb.explode(playboard.getBoard()));
return chainExplosions(explodedFields);
}
}
return explodedFields;
}
}
最近下载更多
adap12345 LV5
2023年6月8日
hkxyyz LV6
2023年3月2日
总有人间一两风 LV8
2022年12月12日
liangge2115 LV27
2022年11月7日
微信网友_6004879537377280 LV3
2022年6月22日
jytjyt LV1
2021年12月16日
ssssqweq LV1
2021年11月1日
此次东方 LV1
2021年10月20日
qliu0130 LV1
2021年10月10日
zpy123 LV1
2021年7月18日
最近浏览更多
chengjingjingjing
2025年6月19日
暂无贡献等级
微信网友_7556291372584960
2025年6月16日
暂无贡献等级
qqqww11 LV2
2024年6月26日
鬼屋报道 LV3
2024年6月4日
ClydeSon LV5
2023年12月27日
bangyiyang LV2
2023年12月21日
1112WHQ LV7
2023年11月3日
微信网友_6672184532766720 LV3
2023年10月6日
srrrrrr
2023年9月19日
暂无贡献等级
adap12345 LV5
2023年6月8日

