Guest User

Untitled

a guest
Jun 19th, 2018
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 23.09 KB | None | 0 0
  1. /**
  2. * x2a1
  3. *
  4. * COMP 1020 SECTION Atrue2
  5. * INSTRUCTOR Pourang Polad Irani
  6. * ASSIGNMENT Assignment 2, question x1
  7. * Nathan Loewen, 7688029
  8. */
  9.  
  10. import java.awt.*;
  11. import java.awt.event.*;
  12.  
  13. import javax.swing.*;
  14.  
  15. import java.io.BufferedReader;
  16. import java.io.BufferedWriter;
  17. import java.io.FileReader;
  18. import java.io.FileWriter;
  19. import java.io.IOException;
  20. import java.util.ArrayList;
  21. import java.util.Timer;
  22. import java.util.TimerTask;
  23.  
  24. public class x3q1 {
  25.  
  26. /**
  27. * @brief Starts a Game of Life.
  28. *
  29. * @param args
  30. */
  31. public static void main(String[] args) {
  32.  
  33. new x3q1();
  34. }
  35.  
  36. /**
  37. * @brief Constructor for Game of Life.
  38. */
  39. public x3q1() {
  40.  
  41. /* Create a new window */
  42. new Menu();
  43. }
  44. }
  45.  
  46. /**
  47. * @brief The game menu. Shows previews of saved games and allows them to be selected.
  48. */
  49. class Menu extends JFrame implements MouseListener, MouseMotionListener {
  50. private static final long serialVersionUID = -8135714158736019980L;
  51. private JPanel_ pane = new JPanel_(); /** < Panel to draw to */
  52. private Graphics buffer; /** < Graphics buffer */
  53. private Image bufferImage; /** < Image to draw to in the buffer */
  54. private static ArrayList<boolean[][]> maps = new ArrayList<boolean[][]>(); /** < Stores the cell data. */
  55. private static int open; /**< The open map. */
  56. private final int WINDOWWIDTH = 800;
  57. private final int WINDOWHEIGHT = 800;
  58. private final int CELLWIDTH = 10;
  59. private final int CELLHEIGHT = 10;
  60. private int mouse_x = -1;
  61. private int mouse_y = -1;
  62. private Game game;
  63. private Menu menu = this;
  64. private static Object lock = new Object();
  65.  
  66. public Menu() {
  67.  
  68. /* Set window title */
  69. super("X3Q1 (Conway's Game of Life)");
  70.  
  71. setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  72.  
  73. /* Inherit main frame */
  74. Container con = getContentPane();
  75.  
  76. /* Add the panel */
  77. con.add(pane);
  78. pane.setLayout(null);
  79.  
  80. setVisible(true);
  81.  
  82. this.setBounds(0, 0, WINDOWWIDTH + getInsets().left
  83. + getInsets().right, WINDOWHEIGHT + getInsets().top
  84. + getInsets().bottom);
  85. this.setLocationRelativeTo(null);
  86.  
  87. /* Set up graphics buffer */
  88. bufferImage = createImage(WINDOWWIDTH, WINDOWHEIGHT);
  89. buffer = bufferImage.getGraphics();
  90.  
  91. pane.addMouseMotionListener(this);
  92. pane.addMouseListener(this);
  93.  
  94. load();
  95. updatePreviews();
  96. }
  97.  
  98. private void updatePreviews() {
  99. int x = 0;
  100. int y = 0;
  101. int X = 0;
  102. int Y = 0;
  103. int i,j,k;
  104. int width,height;
  105. double scale;
  106. boolean[][] map;
  107.  
  108. Graphics drawTemp; /** < Graphics buffer */
  109. Image drawTempImage; /** < Image to draw to in the buffer */
  110.  
  111. buffer.setColor(Color.LIGHT_GRAY);
  112. buffer.fillRect(0, 0, bufferImage.getWidth(this), bufferImage.getHeight(this));
  113.  
  114. /* For each map */
  115. for (i=0; i<maps.size(); i++) {
  116. map = maps.get(i);
  117.  
  118. drawTempImage = createImage(map[0].length * CELLWIDTH, map.length * CELLHEIGHT);
  119. drawTemp = drawTempImage.getGraphics();
  120.  
  121. /* Calculate Sizing for map */
  122. width = drawTempImage.getWidth(this);
  123. height = drawTempImage.getHeight(this);
  124. scale = 400./Math.max(width,height);
  125.  
  126. /* For each cell */
  127. for (j = 0; j < map.length; j++) {
  128. for (k = 0; k < map[0].length; k++) {
  129.  
  130. /* Set drawing color */
  131. if (map[j][k])
  132. drawTemp.setColor(Color.black);
  133. else
  134. drawTemp.setColor(Color.white);
  135.  
  136. /* Draw the cell */
  137. drawTemp.fillRect(x, y, CELLWIDTH, CELLHEIGHT);
  138.  
  139. /* Draw the cell border */
  140. if (scale >= 1) {
  141. drawTemp.setColor(Color.LIGHT_GRAY);
  142. drawTemp.drawRect(x, y, CELLWIDTH, CELLWIDTH);
  143. }
  144.  
  145. x += CELLWIDTH;
  146. }
  147. y += CELLHEIGHT;
  148. x = 0;
  149. }
  150. y = 0;
  151.  
  152. /* Shade if mouse is not over it */
  153. if (i != (mouse_y+1)*(mouse_x+mouse_y+1)/2 || mouse_x == -1 || mouse_y == -1) {
  154. drawTemp.setXORMode(Color.white);
  155. drawTemp.setColor(Color.lightGray);
  156. drawTemp.fillRect(0, 0, drawTempImage.getWidth(this), drawTempImage.getHeight(this));
  157. }
  158.  
  159. /* Draw to buffer */
  160. buffer.drawImage(drawTempImage,
  161. X+(int)((400-(width * scale))/2), Y+(int)((400-(height * scale))/2),
  162. (int)(width * scale) + X + (int)((400-(width * scale))/2),
  163. (int)(height * scale) + Y + (int)((400-(height * scale))/2),
  164. 0, 0, width,height,
  165. null);
  166.  
  167. /* Draw boarder */
  168. buffer.setColor(Color.black);
  169. buffer.drawRect(X+(int)((400-(width * scale))/2), Y+(int)((400-(height * scale))/2),
  170. (int)(width * scale), (int)(height * scale));
  171. /* Update drawing position on bufferImage */
  172. X += 400;
  173. if (X>400) {
  174. X = 0;
  175. Y += 400;
  176. }
  177. }
  178.  
  179. //if (mouse_x != -1 || mouse_y != -1) {
  180. // buffer.setColor(Color.blue);
  181. // buffer.drawRect(mouse_x * WINDOWWIDTH/2, mouse_y * WINDOWHEIGHT/2, WINDOWWIDTH/2, WINDOWHEIGHT/2);
  182. //}
  183. this.invalidate();
  184. this.repaint();
  185. }
  186.  
  187. /**
  188. * @brief Loads save game from file.
  189. */
  190. private static void load() {
  191. BufferedReader fileIn; /** < File reader */
  192. char[] buf; /** < Buffer for characters in a line */
  193. String sizeBuf = ""; /** < Buffer for size of map */
  194. String lineBuf; /** < Buffer for line read from file */
  195. int i = 0;
  196. int x, y;
  197. int numMaps = 0;
  198.  
  199. y = 0;
  200. try {
  201. /* Create file reader */
  202. fileIn = new BufferedReader(new FileReader("Life.txp"));
  203.  
  204. /* Read and process each line */
  205. while ((lineBuf = fileIn.readLine()) != null) {
  206. buf = lineBuf.toCharArray();
  207. if (buf.length == 0) {
  208. continue;
  209. }
  210.  
  211. /* If this line specifies dimensions */
  212. if (Character.isDigit(buf[0])) {
  213.  
  214. /* Get X dimension */
  215. while (i < buf.length && Character.isDigit(buf[i])) {
  216. sizeBuf += buf[i];
  217. i++;
  218. }
  219. x = Integer.parseInt(sizeBuf);
  220. sizeBuf = "";
  221. i++;
  222.  
  223. /* Get Y dimension */
  224. while (i < buf.length && Character.isDigit(buf[i])) {
  225. sizeBuf += buf[i];
  226. i++;
  227. }
  228. y = Integer.parseInt(sizeBuf);
  229.  
  230. /* Add a new map */
  231. numMaps++;
  232. maps.ensureCapacity(numMaps);
  233. maps.add(new boolean[y][x]);
  234.  
  235. /* Reset variables */
  236. sizeBuf = "";
  237. i = 0;
  238. y = 0;
  239. x = 0;
  240.  
  241. /* Line specifies cell states */
  242. } else {
  243. if ( y < maps.get(numMaps-1).length) {
  244. for (x = 0; x < maps.get(numMaps-1)[0].length; x++) {
  245.  
  246. /* Cell is live */
  247. if (Character.compare(buf[x], 'X') == 0)
  248. maps.get(numMaps-1)[y][x] = true;
  249.  
  250. /* Cell is dead */
  251. else
  252. maps.get(numMaps-1)[y][x] = false;
  253. }
  254. }
  255. y++;
  256. }
  257. }
  258.  
  259. fileIn.close();
  260. }
  261. /* catch IO errors */
  262. catch (IOException e) {
  263. System.out.println("IO Error!");
  264. e.printStackTrace();
  265. }
  266. }
  267.  
  268. /**
  269. * @brief Saves the game state
  270. */
  271. public static void save(boolean[][] saveMap) {
  272.  
  273. int x,y;
  274.  
  275. BufferedWriter fileOut; /** < The file writer */
  276.  
  277. /* Update the map in memory */
  278. maps.set(open, saveMap);
  279.  
  280. try {
  281. /* Create the file writer */
  282. fileOut = new BufferedWriter(new FileWriter("Life.txp"));
  283.  
  284. for (boolean[][] map : maps) {
  285. /* Write map dimensions */
  286. fileOut.write("" + map[0].length + " " + map.length);
  287.  
  288. fileOut.newLine();
  289.  
  290. /* Write cell states */
  291. for (y = 0; y < map.length; y++) {
  292. for (x = 0; x < map[0].length; x++) {
  293. if (map[y][x])
  294. fileOut.write("X");
  295. else
  296. fileOut.write(" ");
  297. }
  298. fileOut.newLine();
  299. }
  300. }
  301.  
  302. fileOut.close();
  303. }
  304. /* catch IO errors */
  305. catch (IOException e) {
  306. System.out.println("IO Error!");
  307. e.printStackTrace();
  308. }
  309. }
  310.  
  311. /**
  312. * @brief JPanel component with paintComponent() override.
  313. */
  314. class JPanel_ extends JPanel {
  315. private static final long serialVersionUID = 5318671062431096334L;
  316.  
  317. /**
  318. * @brief Draws the buffer to the panel.
  319. */
  320. public void paintComponent(Graphics g) {
  321. g.drawImage(bufferImage, getInsets().left, getInsets().top,
  322. this);
  323. }
  324. }
  325.  
  326. /**
  327. * @brief Called when the mouse moves over the pane.
  328. * updates the mouse position.
  329. */
  330. public void mouseMoved(MouseEvent event) {
  331.  
  332. /* Get the cell that the mouse is over */
  333. int x = event.getX();
  334. int y = event.getY();
  335. x /= (WINDOWWIDTH/2);
  336. y /= (WINDOWHEIGHT/2);
  337.  
  338. /* The mouse is over the same cell. Don't do anything */
  339. if (mouse_x == x && mouse_y == y)
  340. return;
  341.  
  342. /* update the mouse position */
  343. mouse_x = x;
  344. mouse_y = y;
  345.  
  346. /* redraw */
  347. updatePreviews();
  348. }
  349.  
  350. /**
  351. * @brief Called when the mouse exits the pane.
  352. * Invalidates the mouse position.
  353. */
  354. public void mouseExited(MouseEvent arg0) {
  355.  
  356. /* invalidate the mouse position */
  357. mouse_x = -1;
  358. mouse_y = -1;
  359.  
  360. /* redraw */
  361. updatePreviews();
  362. this.invalidate();
  363. this.repaint();
  364. }
  365.  
  366. /**
  367. * @brief Called when we receive a mouse click.
  368. */
  369. public void mouseClicked(MouseEvent event) {
  370.  
  371. /* Get the cell that was clicked on */
  372. int x = event.getX();
  373. int y = event.getY();
  374. x /= (WINDOWWIDTH/2);
  375. y /= (WINDOWHEIGHT/2);
  376.  
  377. /* Toggle the cell */
  378. open = (y+1)*(x+y+1)/2;
  379. this.setVisible(false);
  380. game = new Game(maps.get(open));
  381.  
  382. final Thread t = new Thread() {
  383. public void run() {
  384. synchronized(lock) {
  385. while (game.isVisible())
  386. try {
  387. lock.wait();
  388. } catch (InterruptedException e) {
  389. e.printStackTrace();
  390. }
  391. game = null;
  392. menu.setVisible(true);
  393. updatePreviews();
  394. menu.requestFocus();
  395. menu.toFront();
  396. return;
  397. }
  398. }
  399. };
  400. t.start();
  401.  
  402. game.addWindowListener(new WindowAdapter() {
  403. public void windowClosing(WindowEvent arg0) {
  404. synchronized (lock) {
  405. game.setVisible(false);
  406. save(game.map);
  407. lock.notify();
  408. }
  409. }
  410. });
  411. }
  412.  
  413. public void mouseDragged(MouseEvent arg0) {}
  414. public void mouseEntered(MouseEvent arg0) {}
  415. public void mousePressed(MouseEvent arg0) {}
  416. public void mouseReleased(MouseEvent arg0) {}
  417. }
  418.  
  419. /**
  420. * @brief Defines a window for Conway's Game of Life
  421. */
  422. class Game extends JFrame implements ActionListener, MouseListener,
  423. ComponentListener, MouseMotionListener, KeyListener {
  424. private static final long serialVersionUID = 4295288338564549551L;
  425. private JPanel_ pane = new JPanel_(); /** < Panel to draw to */
  426. private final int CELLWIDTH = 10; /** < Width of one cell */
  427. private final int CELLHEIGHT = 10; /** < Height of one cell */
  428. private final int CONTROLHEIGHT = 40; /** < Height of game controls */
  429. private Graphics buffer; /** < Graphics buffer */
  430. private Image bufferImage; /** < Image to draw to in the buffer */
  431. private JButton button_startStop = new JButton("Start"); /** < Start/Stop button */
  432. private JButton button_clear = new JButton("Clear"); /** < Button to clear all cells */
  433. private boolean sizeable = true; /** < Guards against resize loops. */
  434. private int mouse_x = -1; /** < X position of cell containing mouse. */
  435. private int mouse_y = -1; /** < Y position of cell containing mouse. */
  436. boolean[][] map; /** < A map of cell states */
  437. private Timer loop; /** < Timer for the game loop. */
  438. private boolean running; /** < Whether the game loop is running. */
  439.  
  440. /**
  441. * @Brief Constructor for the game window.
  442. */
  443. public Game(boolean[][] startingMap) {
  444.  
  445. /* Set window title */
  446. super("X3Q1 (Conway's Game of Life)");
  447.  
  448. map = startingMap;
  449.  
  450. /* Set close operation */
  451. setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
  452.  
  453. /* Inherit main frame */
  454. Container con = getContentPane();
  455.  
  456. /* Add the panel */
  457. con.add(pane);
  458. pane.setLayout(null);
  459.  
  460. /* Set the window to be visible.
  461. * This is required for proper window sizing. */
  462. setVisible(true);
  463.  
  464. /* Update the window size */
  465. if (sizeable) {
  466. sizeable = false;
  467. updateWindowSize();
  468. sizeable = true;
  469. }
  470.  
  471. /* Set up Start/Stop button */
  472. button_startStop.addActionListener(this);
  473. button_startStop.setFocusable(false);
  474. pane.add(button_startStop);
  475. /* Set up Clear button */
  476. button_clear.addActionListener(this);
  477. button_clear.setFocusable(false);
  478. pane.add(button_clear);
  479.  
  480. /* Listen */
  481. pane.addMouseListener(this);
  482. pane.addComponentListener(this);
  483. pane.addMouseMotionListener(this);
  484. addKeyListener(this);
  485. setFocusable(true);
  486. }
  487.  
  488. /**
  489. * @brief Updates the cells.
  490. */
  491. private void updateMap() {
  492.  
  493. boolean[][] newMap = new boolean[map.length][map[0].length]; /** < The new cells */
  494. int i, j;
  495.  
  496. /* For each cell */
  497. for (i = 0; i < map.length; i++) {
  498. for (j = 0; j < map[i].length; j++) {
  499.  
  500. /* If the cell is alive and should die */
  501. if (map[i][j]
  502. && !(neighbors(i, j) == 2 || neighbors(i, j) == 3))
  503. newMap[i][j] = false;
  504.  
  505. /* If the cell is dead and should live */
  506. else if (!map[i][j] && neighbors(i, j) == 3)
  507. newMap[i][j] = true;
  508.  
  509. /* The cell does nothing */
  510. else
  511. newMap[i][j] = map[i][j];
  512. }
  513. }
  514.  
  515. /* Use the new map */
  516. map = newMap;
  517. }
  518.  
  519. /**
  520. * @brief Finds the number of live neighbors a cell has.
  521. *
  522. * @param y
  523. * Vertical coordinate of cell.
  524. * @param x
  525. * Horizontal coordinate of cell.
  526. * @return The number of neighbors.
  527. */
  528. private int neighbors(int y, int x) {
  529.  
  530. int neighbors = 0;
  531.  
  532. /* Check the cells above. */
  533. if (y == 0) { /* Check for top edge */
  534. /* Top left */
  535. if (x == 0) { /* Check for left edge */
  536. if (map[map.length - 1][map[0].length - 1])
  537. neighbors++;
  538. } else if (map[map.length - 1][x - 1])
  539. neighbors++;
  540. /* Top center */
  541. if (map[map.length - 1][x])
  542. neighbors++;
  543. /* Top right */
  544. if (x == map[0].length - 1) { /* Check for right edge */
  545. if (map[map.length - 1][0])
  546. neighbors++;
  547. } else if (map[map.length - 1][x + 1])
  548. neighbors++;
  549. } else {
  550. /* Top left */
  551. if (x == 0) { /* Check for left edge */
  552. if (map[y - 1][map[0].length - 1])
  553. neighbors++;
  554. } else if (map[y - 1][x - 1])
  555. neighbors++;
  556. /* Top center */
  557. if (map[y - 1][x])
  558. neighbors++;
  559. /* Top right */
  560. if (x == map[0].length - 1) { /* Check for right edge */
  561. if (map[y - 1][0])
  562. neighbors++;
  563. } else if (map[y - 1][x + 1])
  564. neighbors++;
  565. }
  566. /* Check Left */
  567. if (x == 0) { /* Check for left edge */
  568. if (map[y][map[0].length - 1])
  569. neighbors++;
  570. } else if (map[y][x - 1])
  571. neighbors++;
  572. /* Check right */
  573. if (x == map[0].length - 1) { /* Check for right edge */
  574. if (map[y][0])
  575. neighbors++;
  576. } else if (map[y][x + 1])
  577. neighbors++;
  578. /* Check cells below */
  579. if (y == map.length - 1) { /* Check for bottom edge */
  580. /* bottom left */
  581. if (x == 0) { /* Check for left edge */
  582. if (map[0][map[0].length - 1])
  583. neighbors++;
  584. } else if (map[0][x - 1])
  585. neighbors++;
  586. /* bottom center */
  587. if (map[0][x])
  588. neighbors++;
  589. /* bottom right */
  590. if (x == map[0].length - 1) { /* Check for right edge */
  591. if (map[0][0])
  592. neighbors++;
  593. } else if (map[0][x + 1])
  594. neighbors++;
  595. } else {
  596. /* Bottom left */
  597. if (x == 0) { /* Check for left edge */
  598. if (map[y + 1][map[0].length - 1])
  599. neighbors++;
  600. } else if (map[y + 1][x - 1])
  601. neighbors++;
  602. /* Bottom center */
  603. if (map[y + 1][x])
  604. neighbors++;
  605. /* Bottom right */
  606. if (x == map[0].length - 1) { /* Check for right edge */
  607. if (map[y + 1][0])
  608. neighbors++;
  609. } else if (map[y + 1][x + 1])
  610. neighbors++;
  611. }
  612.  
  613. return neighbors;
  614. }
  615.  
  616. /**
  617. * @brief Resizes the game window to fit the map.
  618. */
  619. private void updateWindowSize() {
  620.  
  621. /* Size window */
  622. this.setBounds(this.getWidth(), this.getHeight(), (map[0].length * CELLWIDTH
  623. + getInsets().left + getInsets().right),
  624. (map.length * CELLHEIGHT + getInsets().top
  625. + getInsets().bottom + CONTROLHEIGHT));
  626. this.setLocationRelativeTo(null);
  627. /* Set up graphics buffer */
  628. bufferImage = createImage(map[0].length * CELLWIDTH, map.length
  629. * CELLHEIGHT);
  630. buffer = bufferImage.getGraphics();
  631. /* Size buttons */
  632. updateControlSize();
  633. /* Redraw for new size */
  634. cellsUpdate();
  635. this.invalidate();
  636. this.repaint();
  637. }
  638.  
  639. /**
  640. * @brief Updates button states and sizes.
  641. */
  642. private void updateControlSize() {
  643. if (running) {
  644. /* Start/Stop button gets all the space */
  645. button_startStop.setBounds(0, map.length * CELLHEIGHT,
  646. map[0].length * CELLWIDTH, CONTROLHEIGHT);
  647. /* Disable the clear button */
  648. button_clear.setEnabled(false);
  649. }
  650. else {
  651. /* Enable the clear button */
  652. button_clear.setEnabled(true);
  653. /* The Start/Stop and clear buttons get spaced evenly */
  654. button_startStop.setBounds(0, map.length * CELLHEIGHT,
  655. map[0].length * CELLWIDTH / 2, CONTROLHEIGHT);
  656. button_clear.setBounds(map[0].length * CELLWIDTH / 2,
  657. map.length * CELLHEIGHT, map[0].length * CELLWIDTH / 2,
  658. CONTROLHEIGHT);
  659. }
  660. }
  661.  
  662. /**
  663. * @brief The main logic for Conway's Game of Life. Is called by a Timer.
  664. */
  665. class gameLoop extends TimerTask {
  666. public void run() {
  667. /* Update the cell data */
  668. updateMap();
  669. /* Draw the cells to the buffer */
  670. cellsUpdate();
  671. /* Repaint the game window */
  672. invalidate();
  673. repaint();
  674. }
  675. }
  676.  
  677. /**
  678. * @brief Updates the cells in the graphics buffer.
  679. */
  680. public void cellsUpdate() {
  681. int x = 0;
  682. int y = 0;
  683.  
  684. /* For each cell */
  685. for (int i = 0; i < map.length; i++) {
  686. for (int j = 0; j < map[0].length; j++) {
  687.  
  688. /* Set drawing color */
  689. if (map[i][j])
  690. buffer.setColor(Color.black);
  691. else
  692. buffer.setColor(Color.white);
  693.  
  694. /* Draw the cell */
  695. buffer.fillRect(x, y, CELLWIDTH, CELLHEIGHT);
  696.  
  697. /* Draw the cell border */
  698. buffer.setColor(Color.LIGHT_GRAY);
  699. buffer.drawRect(x, y, CELLWIDTH, CELLWIDTH);
  700.  
  701. x += CELLWIDTH;
  702. }
  703. y += CELLHEIGHT;
  704. x = 0;
  705. }
  706. /* Highlight the cell that has the mouse */
  707. if (mouse_x >= 0 && mouse_y >= 0) {
  708. buffer.setColor(Color.blue);
  709. buffer.drawRect(mouse_x * CELLWIDTH, mouse_y * CELLWIDTH, CELLWIDTH, CELLHEIGHT);
  710. }
  711. }
  712.  
  713. /**
  714. * @brief Toggles the games running state.
  715. */
  716. public void startStop() {
  717. if (running) {
  718. /* Change button text */
  719. button_startStop.setText("Start");
  720. /* Stop the game loop */
  721. loop.cancel();
  722. /* The window can now be resized */
  723. this.setResizable(true);
  724. /* We are no longer running */
  725. running = false;
  726. } else {
  727. /* Change button text */
  728. button_startStop.setText("Stop");
  729. /* Start the game loop */
  730. loop = new Timer();
  731. loop.scheduleAtFixedRate(new gameLoop(), 0, 150);
  732. /* Invalidate the mouse position */
  733. mouse_x = -1;
  734. mouse_y = -1;
  735. /* We are now running */
  736. running = true;
  737. }
  738. /* Update the buttons */
  739. updateControlSize();
  740. }
  741.  
  742. /**
  743. * @brief Sets all cells to false
  744. */
  745. public void clear() {
  746.  
  747. /* If the game is running, don't do anything */
  748. if (running)
  749. return;
  750.  
  751. int i,j;
  752.  
  753. /* Set each cell to false */
  754. for (i=0; i<map.length; i++)
  755. for (j=0; j<map[0].length; j++)
  756. map[i][j] = false;
  757.  
  758. /* redraw */
  759. cellsUpdate();
  760. this.invalidate();
  761. this.repaint();
  762. }
  763.  
  764. /**
  765. * @brief JPanel component with paintComponent() override.
  766. */
  767. class JPanel_ extends JPanel {
  768. private static final long serialVersionUID = 5318671062431096334L;
  769.  
  770. /**
  771. * @brief Draws the buffer to the panel.
  772. */
  773. public void paintComponent(Graphics g) {
  774. g.drawImage(bufferImage, getInsets().left, getInsets().top,
  775. this);
  776. }
  777. }
  778.  
  779. /**
  780. * @brief Called when a button is pushed.
  781. */
  782. public void actionPerformed(ActionEvent event) {
  783. Object source = event.getSource();
  784.  
  785. /* If the Start/Stop button was pushed */
  786. if (source == button_startStop)
  787. startStop();
  788. /* If the clear button was pushed */
  789. else if (source == button_clear)
  790. clear();
  791. }
  792.  
  793. /**
  794. * @brief Called when a keyboard button is pressed.
  795. */
  796. public void keyPressed(KeyEvent event) {
  797. int key = event.getKeyCode();
  798.  
  799. if (key == KeyEvent.VK_SPACE)
  800. startStop();
  801. else if (key == KeyEvent.VK_ESCAPE)
  802. clear();
  803. }
  804.  
  805. /**
  806. * @brief Called when we receive a mouse click.
  807. */
  808. public void mouseClicked(MouseEvent event) {
  809.  
  810. /* If the game is running, don't do anything */
  811. if (running)
  812. return;
  813.  
  814. /* Get the cell that was clicked on */
  815. int x = event.getX();
  816. int y = event.getY();
  817. x /= CELLWIDTH;
  818. y /= CELLHEIGHT;
  819.  
  820. /* Not a valid cell, abort */
  821. if (x >= map[0].length || y >= map.length)
  822. return;
  823.  
  824. /* Toggle the cell */
  825. map[y][x] = !map[y][x];
  826. cellsUpdate();
  827. this.invalidate();
  828. this.repaint();
  829. }
  830.  
  831. /**
  832. * @brief Called when the mouse moves over the pane.
  833. * updates the mouse position.
  834. */
  835. public void mouseMoved(MouseEvent event) {
  836.  
  837. /* If the game is running, don't do anything */
  838. if (running)
  839. return;
  840.  
  841. /* Get the cell that the mouse is over */
  842. int x = event.getX();
  843. int y = event.getY();
  844. x /= CELLWIDTH;
  845. y /= CELLHEIGHT;
  846.  
  847. /* The mouse is over the same cell. Don't do anything */
  848. if (mouse_x == x && mouse_y == y)
  849. return;
  850.  
  851. /* Not a valid cell */
  852. if (x >= map[0].length || y >= map.length) {
  853. x = -1;
  854. y = -1;
  855. }
  856.  
  857. /* update the mouse position */
  858. mouse_x = x;
  859. mouse_y = y;
  860.  
  861. /* redraw */
  862. cellsUpdate();
  863. this.invalidate();
  864. this.repaint();
  865. }
  866.  
  867. /**
  868. * @brief Called when the mouse exits the pane.
  869. * Invalidates the mouse position.
  870. */
  871. public void mouseExited(MouseEvent arg0) {
  872.  
  873. /* If the game is running, don't do anything */
  874. if (running)
  875. return;
  876.  
  877. /* invalidate the mouse position */
  878. mouse_x = -1;
  879. mouse_y = -1;
  880.  
  881. /* redraw */
  882. cellsUpdate();
  883. this.invalidate();
  884. this.repaint();
  885. }
  886.  
  887. /**
  888. * @brief Called when the window is resized
  889. */
  890. public void componentResized(ComponentEvent event) {
  891.  
  892. /* Avoid infinite loops */
  893. if (!sizeable)
  894. return;
  895.  
  896. /* Nobody is allowed to resize */
  897. sizeable = false;
  898.  
  899. /* If we arn't running, it is ok to update the size */
  900. if (!running) {
  901. /* Calculate new array dimensions */
  902. int x = event.getComponent().getWidth() / CELLWIDTH;
  903. int y = (event.getComponent().getHeight() - CONTROLHEIGHT)
  904. / CELLHEIGHT;
  905.  
  906. /* edge case where array dimensions are less than 0. */
  907. if (x<0 || y<0) {
  908. sizeable = true;
  909. return;
  910. }
  911.  
  912. /* If we need to resize the array */
  913. if (y != map.length || x != map[0].length) {
  914. /* Create the new array */
  915. boolean[][] newMap = new boolean[y][x];
  916. for (int i = 0; i < Math.min(y, map.length); i++) {
  917. System.arraycopy(map[i], 0, newMap[i], 0,
  918. Math.min(x, map[0].length));
  919. }
  920. map = newMap;
  921. }
  922. }
  923.  
  924. /* Update the window */
  925. updateWindowSize();
  926. this.invalidate();
  927. this.repaint();
  928.  
  929. /* Resizing is now allowed */
  930. sizeable = true;
  931. }
  932.  
  933. /* Unused required methods */
  934. public void mouseEntered(MouseEvent event) {}
  935. public void mousePressed(MouseEvent arg0) {}
  936. public void mouseReleased(MouseEvent arg0) {}
  937. public void componentHidden(ComponentEvent arg0) {}
  938. public void componentMoved(ComponentEvent arg0) {}
  939. public void componentShown(ComponentEvent arg0) {}
  940. public void mouseDragged(MouseEvent arg0) {}
  941. public void keyReleased(KeyEvent arg0) {}
  942. public void keyTyped(KeyEvent arg0) {}
  943. }
Add Comment
Please, Sign In to add comment