A java PacMan game application for A.U.TH (data structures class)
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

382 Zeilen
12 KiB

  1. package gr.auth.ee.dsproject.pacman;
  2. import java.util.ArrayList;
  3. import gr.auth.ee.dsproject.node.Globals;
  4. import gr.auth.ee.dsproject.node.Tree;
  5. import gr.auth.ee.dsproject.node.Node89978445;
  6. /**
  7. * <p>
  8. * Title: DataStructures2011
  9. * </p>
  10. *
  11. * <p>
  12. * Description: Data Structures project: year 2011-2012
  13. * </p>
  14. *
  15. * <p>
  16. * Copyright: Copyright (c) 2011
  17. * </p>
  18. *
  19. * <p>
  20. * Company: A.U.Th.
  21. * </p>
  22. *
  23. * @author Michael T. Tsapanos
  24. * @version 1.0
  25. */
  26. public class Creature implements gr.auth.ee.dsproject.pacman.AbstractCreature
  27. {
  28. public String getName () {
  29. return "Mine";
  30. }
  31. private int step = 1;
  32. private boolean amPrey;
  33. public Creature (boolean isPrey) {
  34. amPrey = isPrey;
  35. }
  36. /**
  37. * @brief
  38. * For any current position creates a tree for minmax alpha-beta pruning algorithm
  39. * apply the min-max algo and return the move representing by resulting node
  40. * @return
  41. * the move of pacman to play
  42. */
  43. public int calculateNextPacmanPosition (Room[][] Maze, int[] currPosition)
  44. {
  45. int [] bestPos = {-1, -1}; // Best position in maze to play
  46. int bestMove = 0;
  47. Node89978445 bestNode; // The node with the best evaluation
  48. Node89978445 cur = new Node89978445 (Maze, currPosition); // The node with the current position
  49. //make the tree
  50. createSubTreePacman (cur.getDepth (), cur, Maze, currPosition);
  51. // min-max to find best node and consequently the best position
  52. bestNode = Tree.minmaxAB (cur, Globals.MINMAXTREE_MAX_DEPTH-1, Integer.MIN_VALUE, Integer.MAX_VALUE, true);
  53. bestPos = bestNode.getCurrentPacmanPos();
  54. // convert back to move encoding
  55. if ((bestMove = Node89978445.moveConv (bestPos, currPosition)) != Globals.INVALID_MOVE)
  56. return bestMove;
  57. else
  58. return 0;
  59. }
  60. /**
  61. * @brief
  62. * For any ghost (or root) parent node, create all child nodes representing
  63. * pacman's valid moves.
  64. * @note
  65. * This routine calls createSubTreeGhosts() called back from it recursively.
  66. * The recursion ends when the right depth is reached.
  67. */
  68. void createSubTreePacman (int depth, Node89978445 parent, Room[][] Maze, int[] curPacmanPosition)
  69. {
  70. if (depth >= Globals.MINMAXTREE_MAX_DEPTH-1)
  71. /*<
  72. * As the depth starts from 0 and MINMAXTREE_MAX_DEPTH
  73. * is strictly even, with this comparison we accept that there
  74. * is no need for a max-depth layer of ghosts-evaluation based nodes.
  75. * As soon as we accept the depth-1 layers max evaluated node.
  76. */
  77. return;
  78. else {
  79. Node89978445 newNode;
  80. Room[][] newMaze;
  81. int[] nextPosition = {-1, -1};
  82. // scan possible valid moves
  83. for (int move=0 ; move<4 ; ++move) {
  84. if ((nextPosition = Node89978445.pacmanValidMove (parent, move)) != Globals.POSITION_FALSE) {
  85. // Make a copy of the maze in order to simulate next move and move Pacman
  86. newMaze = PacmanUtilities.copy (Maze);
  87. PacmanUtilities.movePacman (newMaze, parent.getCurrentPacmanPos(), nextPosition);
  88. // Create a node for the move in the new stated game maze
  89. newNode = new Node89978445 (newMaze, nextPosition);
  90. Tree.grow (newNode, parent); // add node to the min-max search tree
  91. // call the recursive branch creator
  92. createSubTreeGhosts (newNode.getDepth (), newNode, newMaze, newNode.getCurrentGhostPos());
  93. }
  94. }
  95. }
  96. }
  97. /**
  98. * @brief
  99. * For any parent node, create all child node representing ghosts valid moves.
  100. * @note
  101. * This routine recursively call createSubTreePacman().
  102. * The recursion ends when the right depth is reached.
  103. */
  104. void createSubTreeGhosts (int depth, Node89978445 parent, Room[][] Maze, int[][] currGhostsPosition)
  105. {
  106. if (depth >= Globals.MINMAXTREE_MAX_DEPTH-1)
  107. /*<
  108. * As the depth starts from 0 and MINMAXTREE_MAX_DEPTH
  109. * is strictly even, with this comparison we accept that there
  110. * is no need for a max-depth layer of ghosts-evaluation based nodes.
  111. * As soon as we accept the depth-1 layers max evaluated node.
  112. */
  113. return;
  114. else {
  115. Node89978445 newNode;
  116. Room[][] newMaze;
  117. ArrayList<int[][]> ghostMoves;
  118. // Get all possible ghost moves
  119. ghostMoves = PacmanUtilities.allGhostMoves(Maze, currGhostsPosition);
  120. // loop all ghost moves
  121. for (int i=0 ; i<ghostMoves.size() ; ++i) {
  122. // Make a copy of the maze in order to simulate next move and move ghosts
  123. newMaze = PacmanUtilities.copy (Maze);
  124. PacmanUtilities.moveGhosts(newMaze, currGhostsPosition, ghostMoves.get(i));
  125. // Create a node for the move in the new stated game maze
  126. newNode = new Node89978445 (newMaze, parent.getCurrentPacmanPos());
  127. Tree.grow (newNode, parent); // add node to the min-max search tree
  128. //recursive call for the rest of the tree
  129. createSubTreePacman (newNode.getDepth (), newNode, newMaze, parent.getCurrentPacmanPos());
  130. }
  131. }
  132. }
  133. public int[] getPacPos (Room[][] Maze)
  134. {
  135. int[] pacmanPos = new int[2];
  136. for (int i = 0; i < PacmanUtilities.numberOfRows; i++) {
  137. for (int j = 0; j < PacmanUtilities.numberOfColumns; j++) {
  138. if (Maze[i][j].isPacman()) {
  139. pacmanPos[0] = i;
  140. pacmanPos[1] = j;
  141. return pacmanPos;
  142. }
  143. }
  144. }
  145. return pacmanPos;
  146. }
  147. public boolean[] comAvPos (Room[][] Maze, int[][] currentPos, int[] moves, int currentGhost)
  148. {
  149. boolean[] availablePositions = { true, true, true, true };
  150. int[][] newPos = new int[4][2];
  151. for (int i = 0; i < 4; i++) {
  152. if (Maze[currentPos[currentGhost][0]][currentPos[currentGhost][1]].walls[i] == 0) {
  153. availablePositions[i] = false;
  154. continue;
  155. }
  156. if (PacmanUtilities.flagColision(Maze, currentPos[currentGhost], i)) {
  157. availablePositions[i] = false;
  158. }
  159. else if (currentGhost == 0)
  160. continue;
  161. else {
  162. switch (i) {
  163. case Room.WEST:
  164. newPos[currentGhost][0] = currentPos[currentGhost][0];
  165. newPos[currentGhost][1] = currentPos[currentGhost][1] - 1;
  166. break;
  167. case Room.SOUTH:
  168. newPos[currentGhost][0] = currentPos[currentGhost][0] + 1;
  169. newPos[currentGhost][1] = currentPos[currentGhost][1];
  170. break;
  171. case Room.EAST:
  172. newPos[currentGhost][0] = currentPos[currentGhost][0];
  173. newPos[currentGhost][1] = currentPos[currentGhost][1] + 1;
  174. break;
  175. case Room.NORTH:
  176. newPos[currentGhost][0] = currentPos[currentGhost][0] - 1;
  177. newPos[currentGhost][1] = currentPos[currentGhost][1];
  178. }
  179. for (int j = (currentGhost - 1); j > -1; j--) {
  180. switch (moves[j]) {
  181. case Room.WEST:
  182. newPos[j][0] = currentPos[j][0];
  183. newPos[j][1] = currentPos[j][1] - 1;
  184. break;
  185. case Room.SOUTH:
  186. newPos[j][0] = currentPos[j][0] + 1;
  187. newPos[j][1] = currentPos[j][1];
  188. break;
  189. case Room.EAST:
  190. newPos[j][0] = currentPos[j][0];
  191. newPos[j][1] = currentPos[j][1] + 1;
  192. break;
  193. case Room.NORTH:
  194. newPos[j][0] = currentPos[j][0] - 1;
  195. newPos[j][1] = currentPos[j][1];
  196. // break;
  197. }
  198. if ((newPos[currentGhost][0] == newPos[j][0]) && (newPos[currentGhost][1] == newPos[j][1])) {
  199. availablePositions[i] = false;
  200. continue;
  201. }
  202. if ((newPos[currentGhost][0] == currentPos[j][0]) && (newPos[currentGhost][1] == currentPos[j][1]) && (newPos[j][0] == currentPos[currentGhost][0])
  203. && (newPos[j][1] == currentPos[currentGhost][1])) {
  204. availablePositions[i] = false;
  205. }
  206. }
  207. }
  208. }
  209. return availablePositions;
  210. }
  211. public int comBestPos (boolean[] availablePositions, int[] pacmanPosition, int[] currentPos)
  212. {
  213. int[] newVerticalDifference = new int[2];
  214. for (int i = 0; i < 2; i++)
  215. newVerticalDifference[i] = currentPos[i] - pacmanPosition[i];
  216. int[] distanceSquared = new int[4];
  217. for (int i = 0; i < 4; i++) {
  218. if (availablePositions[i] == true) {
  219. switch (i) {
  220. case Room.WEST:
  221. newVerticalDifference[1]--;
  222. break;
  223. case Room.SOUTH:
  224. newVerticalDifference[0]++;
  225. break;
  226. case Room.EAST:
  227. newVerticalDifference[1]++;
  228. break;
  229. case Room.NORTH:
  230. newVerticalDifference[0]--;
  231. break;
  232. }
  233. distanceSquared[i] = newVerticalDifference[0] * newVerticalDifference[0] + newVerticalDifference[1] * newVerticalDifference[1];
  234. } else
  235. distanceSquared[i] = PacmanUtilities.numberOfRows * PacmanUtilities.numberOfRows + PacmanUtilities.numberOfColumns * PacmanUtilities.numberOfColumns + 1;
  236. }
  237. int minDistance = distanceSquared[0];
  238. int minPosition = 0;
  239. for (int i = 1; i < 4; i++) {
  240. if (minDistance > distanceSquared[i]) {
  241. minDistance = distanceSquared[i];
  242. minPosition = i;
  243. }
  244. }
  245. return minPosition;
  246. }
  247. public int[] calculateNextGhostPosition (Room[][] Maze, int[][] currentPos)
  248. {
  249. int[] moves = new int[PacmanUtilities.numberOfGhosts];
  250. int[] pacmanPosition = new int[2];
  251. pacmanPosition = getPacPos(Maze);
  252. for (int i = 0; i < PacmanUtilities.numberOfGhosts; i++) {
  253. moves[i] = comBestPos(comAvPos(Maze, currentPos, moves, i), pacmanPosition, currentPos[i]);
  254. }
  255. return moves;
  256. }
  257. public boolean[] checkCollision (int[] moves, int[][] currentPos)
  258. {
  259. boolean[] collision = new boolean[PacmanUtilities.numberOfGhosts];
  260. int[][] newPos = new int[4][2];
  261. for (int i = 0; i < moves.length; i++) {
  262. if (moves[i] == 0) {
  263. if (currentPos[i][1] > 0) {
  264. newPos[i][0] = currentPos[i][0];
  265. newPos[i][1] = currentPos[i][1] - 1;
  266. } else {
  267. newPos[i][0] = currentPos[i][0];
  268. newPos[i][1] = PacmanUtilities.numberOfColumns - 1;
  269. }
  270. } else if (moves[i] == 1) {
  271. if (currentPos[i][0] < PacmanUtilities.numberOfRows - 1) {
  272. newPos[i][0] = currentPos[i][0] + 1;
  273. newPos[i][1] = currentPos[i][1];
  274. } else {
  275. newPos[i][0] = 0;
  276. newPos[i][1] = currentPos[i][1];
  277. }
  278. } else if (moves[i] == 2) {
  279. if (currentPos[i][1] < PacmanUtilities.numberOfColumns - 1) {
  280. newPos[i][0] = currentPos[i][0];
  281. newPos[i][1] = currentPos[i][1] + 1;
  282. } else {
  283. newPos[i][0] = currentPos[i][0];
  284. newPos[i][1] = 0;
  285. }
  286. } else {
  287. if (currentPos[i][0] > 0) {
  288. newPos[i][0] = currentPos[i][0] - 1;
  289. newPos[i][1] = currentPos[i][1];
  290. } else {
  291. newPos[i][0] = PacmanUtilities.numberOfRows - 1;
  292. newPos[i][1] = currentPos[i][1];
  293. }
  294. }
  295. collision[i] = false;
  296. }
  297. for (int k = 0; k < moves.length; k++) {
  298. }
  299. for (int i = 0; i < moves.length; i++) {
  300. for (int j = i + 1; j < moves.length; j++) {
  301. if (newPos[i][0] == newPos[j][0] && newPos[i][1] == newPos[j][1]) {
  302. collision[j] = true;
  303. }
  304. if (newPos[i][0] == currentPos[j][0] && newPos[i][1] == currentPos[j][1] && newPos[j][0] == currentPos[i][0] && newPos[j][1] == currentPos[i][1]) {
  305. collision[j] = true;
  306. }
  307. }
  308. }
  309. return collision;
  310. }
  311. }