A java snake game for A.U.TH. Data structures class
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

311 lines
10 KiB

  1. package net.hoo2.auth.dsproject.snake;
  2. /**
  3. * @mainpage
  4. * @title Snake game project. -- Part 1 --
  5. *
  6. * This is the code documentation page of the Snake game project.
  7. * Listed are:
  8. * * All used classes
  9. * * All member functions
  10. * * All data members
  11. *
  12. * @author Christos Choutouridis AEM:8997
  13. * @email cchoutou@ece.auth.gr
  14. */
  15. import java.util.*;
  16. /**
  17. * @class Game
  18. *
  19. * @brief This is the main control class of the game.
  20. *
  21. * This class includes the main function.Using this class's api
  22. * the user can create a board, register players and roll the game.
  23. *
  24. * @author Christos Choutouridis AEM:8997
  25. * @email cchoutou@ece.auth.gr
  26. */
  27. public class Game {
  28. /** @name Constants */
  29. /**@{ */
  30. static final int MAX_PLAYERS = 6; /**< The maximum number of allowed players in the game */
  31. static final int MAX_GAME_ROUNDS = 1000; /**< the maximum allowed round of the game */
  32. /**@} */
  33. /** @name Private data members */
  34. /** @{ */
  35. private int round; /**< The current round of the game */
  36. private Board board; /**< A reference to board */
  37. private ArrayList<Player> players; /**< A reference to players */
  38. private Map<Integer, Integer> playingOrder;
  39. /** @} */
  40. /** @name private api */
  41. /** @{ */
  42. /**
  43. * Search the players already in the players vector and compare their turn to play
  44. * with the result of a dice. If there is another one with the same dice result return true.
  45. *
  46. * @param turn The dice result to check in order to find player's turn to play
  47. * @param players Reference to already register players
  48. * @return True if there is another player with the same dice result
  49. */
  50. private boolean _search (int die, ArrayList<Integer[]> pairs) {
  51. for (int i =0; i<pairs.size() ; ++i)
  52. if (pairs.get(i)[1] == die)
  53. return true;
  54. return false;
  55. }
  56. private void _sort (ArrayList<Integer[]> pairs) {
  57. Integer[] temp;
  58. for (int i=pairs.size()-1 ; i>0 ; --i) {
  59. for (int j =0 ; j<i ; ++j) {
  60. if (pairs.get(j)[1] > pairs.get(i)[1]) {
  61. temp = pairs.get(i);
  62. pairs.set(i, pairs.get(j));
  63. pairs.set(j, temp);
  64. }
  65. }
  66. }
  67. }
  68. private Player _getPlayer(int playerId) {
  69. for (Player p : players) {
  70. if (p.getPlayerId() == playerId)
  71. return p;
  72. }
  73. return null;
  74. }
  75. /** @} */
  76. /** @name Constructors */
  77. /** @{ */
  78. /** Default doing nothing constructor */
  79. Game () {
  80. round = 0;
  81. board = new Board();
  82. players = new ArrayList<>();
  83. playingOrder
  84. = new HashMap<Integer, Integer>();
  85. }
  86. /**
  87. * @brief The main constructor
  88. * This constructor create a board and prepares the board for the game.
  89. * After this call the user can call @ref registerPlayer()
  90. * @param N The row for the board
  91. * @param M The columns of the board
  92. * @param numOfSnakes Number of snakes to place
  93. * @param numOfLadders Number of ladders to place
  94. * @param numOfApples Number of Apples to place
  95. */
  96. Game (int N, int M, int numOfSnakes, int numOfLadders, int numOfApples) {
  97. round = 0;
  98. // delegate constructors
  99. board = new Board (N, M, numOfSnakes, numOfLadders, numOfApples);
  100. players = new ArrayList<>();
  101. playingOrder
  102. = new HashMap<Integer, Integer>();
  103. }
  104. /** @} */
  105. /** @name Get/Set interface */
  106. /** @{ */
  107. int getRound () { return round; }
  108. void setRound (int round) { this.round = round; }
  109. /** Get reference to board */
  110. Board getBoard () { return board; }
  111. /** Set board
  112. * @param board Reference to board to use
  113. * @note This requires board must be allocated elsewhere.
  114. */
  115. void setBoard (Board board) {
  116. this.board = board;
  117. }
  118. /** Get reference to players */
  119. ArrayList<Player> getPlayers() { return players; }
  120. /**
  121. * Set players
  122. * @param players Reference to players to use
  123. * @note This requires players must be allocated elsewhere.
  124. */
  125. void setPlayers(ArrayList<Player> players) {
  126. this.players = players;
  127. }
  128. Map<Integer, Integer> getPlayingOrder () { return playingOrder; }
  129. void setPlayingOrder (Map<Integer, Integer> playingOrder) {
  130. this.playingOrder = playingOrder;
  131. }
  132. /** @} */
  133. /** @name Public functionality */
  134. /** @{ */
  135. /**
  136. * Register a player to the game
  137. * @param playerId The player ID to use
  138. * @param name The player name to use
  139. * @return The status of the operation
  140. */
  141. boolean registerPlayer (int playerId, String name) {
  142. if (players.size() >= MAX_PLAYERS)
  143. return false;
  144. players.add(new Player(playerId, name, board));
  145. return true;
  146. }
  147. /**
  148. * Register a player to the game
  149. * @param playerId The player ID to use
  150. * @param name The player name to use
  151. * @return The status of the operation
  152. */
  153. boolean registerHeuristicPlayer (int playerId, String name) {
  154. if (players.size() >= MAX_PLAYERS)
  155. return false;
  156. players.add(new HeuristicPlayer(playerId, name, board));
  157. return true;
  158. }
  159. /**
  160. * @brief Set the playing order of players
  161. * This function emulates the classic roll of dice to decide which player
  162. * plays first which second and so on.
  163. */
  164. Map<Integer, Integer> setTurns (ArrayList<Player> players) {
  165. int[] pairData = new int[2];
  166. Integer[] PairData;
  167. ArrayList<Integer[]>
  168. pairList = new ArrayList<>();
  169. for (int d, i =0 ; i<players.size() ; ++i) {
  170. do
  171. d = players.get(i).dice ();
  172. while (_search (d, pairList));
  173. pairData[0] = players.get(i).getPlayerId();
  174. pairData[1] = d;
  175. PairData = Arrays.stream(pairData).boxed().toArray( Integer[]::new );
  176. pairList.add(PairData);
  177. }
  178. // Sort playeingOrger
  179. _sort (pairList);
  180. // Make and return the Map
  181. for (int i =0 ; i<pairList.size() ; ++i) {
  182. playingOrder.put(pairList.get(i)[0], pairList.get(i)[1]);
  183. }
  184. return playingOrder;
  185. }
  186. /**
  187. * Sort the players according to their score
  188. */
  189. void scoreSort () {
  190. players.sort((p1, p2) ->
  191. Integer.compare (p1.getScore(), p2.getScore())
  192. );
  193. }
  194. /**
  195. * A game round. In each round every player plays when is his turn
  196. *
  197. * @return The winner if we have one, or null
  198. */
  199. Player round (boolean verbose) {
  200. int tile;
  201. ++round; // keep track of round
  202. // traverse the players vector and move each player on the board
  203. // using a dice throw
  204. for (Integer pid : playingOrder.keySet()) {
  205. Player p = _getPlayer(pid);
  206. tile = p.getNextMove (p.getTile());
  207. p.statistics(verbose, false);
  208. if (tile>= board.getN()*board.getM())
  209. // The first one here is the winner
  210. return p;
  211. }
  212. return null; // No one finished yet
  213. }
  214. /** @} */
  215. /**
  216. * @brief Main
  217. * As the requirements of the project suggested.
  218. * We:
  219. * * Create a game
  220. * * Manually create a board
  221. * * Register 2 players (John Doe for now)
  222. * * Place a predefined number of snakes, ladders and apples
  223. * * Deploy the game by calling @ref playOrder() and @ref round()
  224. * At the end we print the results and exit
  225. */
  226. public static void main(String[] args) {
  227. // Current project requirements
  228. int lines = 20;
  229. int columns = 10;
  230. int numOfSnakes = 3;
  231. int numOfLadders = 3;
  232. int numOfApples = 6;
  233. int numOfPlayers = 2;
  234. boolean verbose = false;
  235. // Print caption
  236. System.out.println("================== Snake Game ==================");
  237. System.out.println("Board: " +lines +"x" +columns +" with " +numOfSnakes +" snakes, "
  238. +numOfLadders +" ladders and " +numOfApples +" apples.");
  239. System.out.println("Players: " + numOfPlayers);
  240. System.out.println("");
  241. // Board creation
  242. Game game = new Game (lines, columns, numOfSnakes, numOfLadders, numOfApples);
  243. // game.getBoard().createElementBoard(); // Not explicitly required
  244. // Player registration, the one is cheater
  245. for (int i=0 ; i<numOfPlayers && i<MAX_PLAYERS; ++i) {
  246. if (i == 0)
  247. game.registerHeuristicPlayer(i+1, String.format("Player %d", i+1));
  248. else
  249. game.registerPlayer(i+1, String.format("Player %d", i+1));
  250. }
  251. game.setTurns(game.getPlayers()); // Choose play order
  252. Player winner;
  253. do // Keep going until someone finishes
  254. winner = game.round (verbose);
  255. while (winner == null
  256. && game.getRound() < MAX_GAME_ROUNDS);
  257. if (game.getRound() == MAX_GAME_ROUNDS) {
  258. // Check if we finished
  259. System.out.println("Game did not finished in " + MAX_GAME_ROUNDS + " rounds. Abort.");
  260. return;
  261. }
  262. // Print the results
  263. System.out.println("*** Game finished ***");
  264. System.out.println("");
  265. System.out.println("");
  266. System.out.println("*** Game Results ***");
  267. System.out.println("Rounds: " + game.getRound());
  268. System.out.println("Winner: " + winner.getName() + " [" + winner.getScore() +" points]");
  269. System.out.println("Score: ");
  270. game.scoreSort (); // sort players based on their score
  271. for (int i=game.getPlayers().size()-1 ; i>=0 ; --i) {
  272. // Loop all players
  273. Player p = game.getPlayers().get(i);
  274. if (p == winner)
  275. System.out.println(" * " +p.getName() + ": " + p.getScore() +" points");
  276. else
  277. System.out.println(" " +p.getName() + ": " + p.getScore() +" points");
  278. }
  279. for (Player p : game.getPlayers()) {
  280. if (p.getClass().getSimpleName().equals("HeuristicPlayer"))
  281. p.statistics(verbose, true);
  282. }
  283. }
  284. }