Discussion 12: Graphical Applications

In today’s discussion, you’ll get some hands-on practice building a GUI game, Lights Out. In Lights Out, you are presented with a grid of light bulbs where some of the bulbs are on and some are off in a random arrangement.

the completed \

The goal is to click on different grid squares so that all of the light bulbs are simultaneously off. Each time that a square is clicked, it toggles (i.e., switches from on to off or from off to on) that light square’s light bulb as well as the light bulbs in any of the orthogonally adjacent squares (i.e., the squares directly above, left of, right of, or below the clicked square). Once you get better at solving the puzzle, you can try to minimize the number of clicks that you need.

Learning Outcomes

Reminder: Discussion Guidelines

The work that you complete in discussion serves as a formative assessment tool, meaning it offers the opportunity to assess your understanding of the material and for our course staff to get a “pulse” on how things are going so we can make adjustments in future classes. Your grade in discussion is based entirely on attendance and participation; if you show up and you are actively engaged with the activity (working on the activity on your computer, discussing the activity with your group, asking and answering questions, etc.) for the entire 50-minute section period, you will earn full credit. If you complete the activity early, helping other students is a great way to further your own understanding. You do not need to submit any of the work that you complete during discussion.

Since discussion activities are not graded for correctness, we do not place any restrictions on resources that you may use to complete them, which include notes, books, unrestricted conversations with other students, internet searches, and the use of large language models or other generative AI. We advise you to be pragmatic about your use of these resources and think critically about whether they are enhancing your learning. Discussion activities are intended to serve as “strength training” for programming tasks we will expect on assignments and exams (and that you will encounter in future courses and careers), and their main benefit comes from critically thinking to “puzzle” them out.

Working together in small groups is encouraged during discussion!

Your Tasks

Since our treatment of GUIs in CS 2110 is more practical, introducing the basic tools that you need to begin designing graphical applications, we’ll dive right into the code for this discussion. The best way to get better at graphical applications (which tend to be more intricate than many of the other topics that we’ve considered previously) is to play around designing and building them.

Download and read through the starter code. You’ll see that there are 8 TODO tasks for you to complete to finish building the “Lights Out” game. It’s important that you complete these tasks in order so that you can assess your progress at various checkpoints along the way. Rather than using unit tests to verify the correctness of your code (which can be more cumbersome for graphical applications), we encourage you to play-test your game to check that it works.

Creating the Application Window (LightsOutApp.java)

The LightsOutApp class (which extends JFrame) is the main application class. Complete the body of its main() method to construct a new game window and make it visible. Remember to use SwingUtilities.invokeLater() (as we introduced in the lecture) so that the application is started on the event dispatch thread.

When you run this main() method, you should see that a minimal window appears with nothing inside of it (we’ll add widgets to the window in upcoming steps).

the completed \

When you close this window, it should not terminate the program. Instead, you’ll need to manually terminate the application with the red “Stop” button at the top of IntelliJ.

Creating the Application Window (LightsOutApp.java)

At the top of the LightsOutApp constructor, use instance methods inherited from the JFrame class to set certain properties of the application window (as described in the TODO comment). Look back at the code from Lecture 24 to see which methods may be useful.

When you do this, the window likely will still not be large enough to read its title; we still haven’t added any of its child components. However, you can confirm that the window is no longer resizable and that closing it terminates the application.

Laying Out the Game Components (LightsOutApp.java)

Below the code that you’ve just written, you’ll see starter code that initializes the three child components of the JFrame:

Add all of these components to the JFrame in the appropriate positions and ask the layout manager to adjust the sizing and layout of the application window accordingly.

When you run the application now, it will look closer to what we desire.

the completed \

The clicks label and reset button have appeared, but we can not yet see the light button grid (which we will turn our attention to next). At this point, we have finished the work that we will do in the LightsOutApp class.

Creating the Light Buttons (LightGrid.java)

Within the LightGrid constructor, add code to construct and initialize the grid of buttons. Make sure to follow the instructions in the TODO comment to complete all of the required steps. You should start by selecting an appropriate layout manager for this panel.

Once you have completed this task, rerun the application. You should now see a grid of light buttons, but the bulbs are missing their glass tops and coloring; you’ll complete the custom painting next.

the completed \

Custom Painting (LightButton.java)

Take a look at the paintComponent() definition within the LightButton class. You’ll see that we’ve done the rather painstaking work to draw the lightbulb bases, threads, and filament within each of the buttons, but we have left the rest of the drawing for you to complete. Follow the instructions in the TODO prompt to complete this painting. You’ll need to select different colors based on the isLit field (part of the model).

When you rerun the application, you should see that all of the bulbs appear to be “off”.

the completed \

Next, you’ll add the logic to toggle the bulbs.

Toggling the LightButton State (LightButton.java)

Implement the LightButton.toggle() method according to its specifications. Once you have done this, you will have a complete implementation of the LightButton class.

Main Game Logic (LightGrid.java)

The main logic of the game takes place in the LightGrid.toggleNeighborhood() method, which flips the state of the correct light buttons in response to a user’s click. Complete this method according to its specifications. You’ll need to call the toggle() method that you just completed in the previous TODO. It may also help to write an additional private helper method to extract some repeated code and improve maintainability.

Now, when you rerun the application, its view should match the desired appearance. Clicking the reset button should “scramble” up the board state. However, clicking the light buttons will not yet do anything. Completing this part of the controller is your last TODO task.

The Light Button Controller (LightGrid.java)

You’ll find the TODO 8 task inside a lambda expression within the processClick() method. Don’t worry too much about the syntax in this method for right now. This will be the focus of our lecture on Thursday. This processClick() method returns an ActionListener, which describes how the application’s state (its model and view) should be updated in response to an event (clicking a light button).

Add code to the body of this lambda expression to carry out the two steps described in the TODO comment. Make sure that you read through the rest of the class specifications to make sure you are taking care of these steps appropriately.

After you complete this TODO, you should have a finished “Lights Out” game. Verify that the light toggling works as intended and that the label at the top of the frame correctly keeps track of the number of clicks.

How well can you solve the “Lights Out” puzzle? Feel free to update the main() method to try out other grid sizes. You may also need to update the preferred size of the light buttons in the LightButton constructor to make sure the window still fits on your screen.