Skip to content

Lab 12: The Game of Life

Note

This lab is based on Chapter 15 of Think Java from this week's reading. See the chapter for a more detailed explanation of the files provided below.

Bug

Version 1.41.1 of Language Support for Java(TM) by Red Hat, released on 04/02/2025, broke unit testing in VS Code. This bug will hopefully eventually be fixed in an upcoming release of the Test Runner for Java (see issue #1759). In the meantime:

  1. Click the Extensions button on the left sidebar.
  2. Click Language Support for Java(TM) by Red Hat.
  3. On the right side of the Uninstall button, click the down triangle ("More actions").
  4. Click Install Specific Version, and select version 1.40.0.

Learning Objectives

After completing this lab, you should be able to:

  • Extend a class that has a private 2D array attribute.
  • Reason about rows and columns including their length.
  • Calculate row/col indexes that "wrap around" an array.

Background

The Game of Life, invented by the mathematician John Conway, is a "zero-player" game that simulates population growth and decline. You set up the initial conditions and then watch the game play itself. This turns out to be a lot more interesting that it sounds!

Go to PlayGameOfLife.com, click the "Explanation" button (on the lower left), and read how the game works. Then try running the game with different starting configurations. Click the "Lexicon" button to see over a thousand different named patterns.

See also ConwayLife.com, which contains a more sophisticated player, a wiki with over 2500 articles (about various named patterns), and free 500-page textbook about the mathematics behind the game.

The game is so famous that even a Google Search for Conway's Game of Life shows the game running on top of the search results.

Today's Lab

If you haven't already, download and extract think.zip from this week's reading into your src folder. The think.ch15 package is a simple implementation of the Game of Life.

  • The Cell class represents a single cell of the game (on or off) and includes the graphics code for drawing the cell.
  • The GridCanvas class represents the entire grid of cells and extends Java's Canvas class for drawing 2D graphics.
  • The Conway class implements the logic of the game and contains the main() method for running the program.

In the regular Game of Life, the grid has an infinite size. But our Java implementation uses a finite grid instead. As a result, moving objects such as Gliders either "crash" into the edge of the screen or go out of bounds.

An interesting variation of the Game of Life is a toroidal grid, meaning that the cells "wrap around" on the edges. Your task for today's lab is to extend the Game of Life to use a toroidal grid. Rather than modify the original files, you will use inheritance to add new features.

Instructions

  1. Run the Conway application. Discuss with others at your table:

    • What is the program doing?
    • How does the "game" work?
  2. Briefly review the source code. For each file, discuss with others:

    • What is the class's purpose?
    • How does the constructor work?
  3. Define a new class named ToroidalGrid that extends GridCanvas.

    • This new class should be in the labs.lab12 package.
    • Write a default constructor that calls super(10, 8, 20).
    • Define a public int countOn() method; return 0 for now.
    • Override the test() method of GridCanvas; return super.test(r, c) for now.
  4. Add code to the constructor to initialize the grid cells like this:

    Screenshot of ToroidalGrid.java

  5. Modify the constructor of Conway to initialize grid to a ToroidalGrid.

    • Comment out the previous code in the constructor.
    • Run Conway to check your glider from the previous step.
  6. Implement the countOn() method to return the total number of cells that are "on". This method can be used, for example, to track the population over time.

  7. Override the test() method so that the coordinates r and c map to the opposite side of the grid if the values are too low or two high.

  8. Run Conway again to see if the simulation works! The Glider should "fly" around the grid forever, wrapping around the edges.

  9. Add the following code at the end of (and inside of) the ToroidalGrid constructor:

    addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
            int x = e.getX();
            int y = e.getY();
            System.out.print("Clicked (" + x + ", " + y + ")");
        }
    });
    
    You will also need the following imports:
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    

  10. Run Conway and click on the grid several times. You should see messages printed in the terminal window.

  11. Modify the mouseClicked() method to call the countOn() method (that you implemented) and display the results. The output should be in this format:

    Clicked (35, 26) -- 5 cells are alive
    

  12. Modify the mouseClicked() method to calculate the row and col of the cell, based on the x and y coordinates of the event. Then turnOn() that cell and call the repaint() method (inherited from Canvas).

  13. Run Conway and interact with the simulation. Can you get the grid to go completely white? Can you get the grid to fill with all black?

  14. Test your solution using ToroidalGridTest.java. Once everything is working (and passes Checkstyle), submit your ToroidalGrid.java to Gradescope.