-
Notifications
You must be signed in to change notification settings - Fork 17
For Review #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: prereview
Are you sure you want to change the base?
For Review #1
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| ## Mine Sweeper | ||
|
|
||
| For this recipe, you will be implementing a simplified version of the | ||
| [Mine Sweeper](https://en.wikipedia.org/wiki/Minesweeper_(video_game)) game. | ||
|
|
||
| The purpose of this exercise is to introduce you to *functional programming* | ||
| aspects of Java introduced in Java 8. Specifically, it will cover: | ||
|
|
||
| - [Lambda Expressions](https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html) | ||
| - [Method References](https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html) | ||
|
|
||
| To complete the recipe, please follow all the instructions laid out in | ||
| MineSweeper.java. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,132 @@ | ||
| package org.jointheleague.level4.minesweeper; | ||
|
|
||
| import java.awt.BorderLayout; | ||
| import java.awt.Color; | ||
| import java.awt.GridLayout; | ||
| import java.util.Optional; | ||
| import java.util.Random; | ||
| import java.util.stream.IntStream; | ||
|
|
||
| import javax.swing.JButton; | ||
| import javax.swing.JFrame; | ||
| import javax.swing.JMenu; | ||
| import javax.swing.JMenuBar; | ||
| import javax.swing.JMenuItem; | ||
| import javax.swing.JPanel; | ||
| import javax.swing.SwingUtilities; | ||
| import javax.swing.WindowConstants; | ||
|
|
||
| /** | ||
| * Implement the Mine Sweeper game by following the instructions in the | ||
| * comments. All instructions are marked with "TODO". | ||
| */ | ||
| public class MineSweeper { | ||
| private static final int WIDTH = 10; | ||
| private static final int HEIGHT = 15; | ||
| private static final int CELL_SIZE = 20; | ||
| private static final int NUM_MINES = 15; | ||
|
|
||
| final JFrame frame = new JFrame(); | ||
| private final JButton[][] buttons = new JButton[HEIGHT][WIDTH]; | ||
| private final Random rng = new Random(); | ||
| private Optional<boolean[][]> mines = Optional.empty(); | ||
| private int numCellsRemaining; | ||
|
|
||
| /** | ||
| * Initializes: | ||
| * 1. The `mines` variable with `NUM_MINES` randomly distributed mines | ||
| * 2. The `numCellsRemaining` variable to the number of non-mine | ||
| * cells (`WIDTH` * `HEIGHT` - `NUM_MINES`). | ||
| * | ||
| * @param firstCellX X-index of first cell opened. This cannot be a mine. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I usually avoid |
||
| * @param firstCellY Y-index of first cell opened. This cannot be a mine. | ||
| */ | ||
| private void initializeMines(int firstCellX, int firstCellY) { | ||
| // TODO fill in | ||
| // Hint, use `Optional.of(...)` to create a non-empty `Optional`. | ||
| } | ||
|
|
||
| /** | ||
| * Inspects a given cell, and count the number of neighboring cells that | ||
| * are mines. | ||
| * | ||
| * @param x X-index of cell to inspect. | ||
| * @param y Y-index of cell to inspect. | ||
| * @return The number of neighboring cells that are mines (0-8). | ||
| */ | ||
| private Integer getNeighboringMinesCount(int x, int y) { | ||
| // TODO fill in | ||
| return null; | ||
| } | ||
|
|
||
| /** | ||
| * Resets the game by: | ||
| * 1. Setting the `mines` variable back to empty. | ||
| * 2. Clearing the button texts, and setting button states to enabled. | ||
| * | ||
| * @param unused Just here so that method can be passed as ActionListener. | ||
| */ | ||
| private void resetGame(Object unused) { | ||
| // TODO fill in | ||
| } | ||
|
|
||
| private void createAndShowFrame() { | ||
| final JMenuItem resetMenuItem = new JMenuItem("Reset"); | ||
| resetMenuItem.addActionListener(null); // TODO replace null with method reference that resets the game | ||
|
|
||
| final JMenu gameMenu = new JMenu("Game"); | ||
| gameMenu.add(resetMenuItem); | ||
|
|
||
| final JMenuBar menuBar = new JMenuBar(); | ||
| menuBar.add(gameMenu); | ||
|
|
||
| final JPanel controlPanel = new JPanel(); | ||
| final JButton resetButton = new JButton("Reset"); | ||
| resetButton.addActionListener(null); // TODO replace null with method reference that resets the game | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The TODO is actually part of the assignment. |
||
| controlPanel.add(resetButton); | ||
|
|
||
| final JPanel gameBoardPanel = new JPanel(); | ||
| gameBoardPanel.setSize(WIDTH * CELL_SIZE, HEIGHT * CELL_SIZE); | ||
| gameBoardPanel.setBackground(Color.WHITE); | ||
| gameBoardPanel.setLayout(new GridLayout(HEIGHT, WIDTH)); | ||
| IntStream.range(0, HEIGHT).forEach(y -> | ||
| IntStream.range(0, WIDTH).forEach(x -> { | ||
| // This code loops through the X and Y indexes, | ||
| // creating a button for each cell. | ||
| final JButton b = new JButton(); | ||
| buttons[y][x] = b; | ||
| // When the cell button is pressed, it should: | ||
| // 1. Initializes the mines if it is not yet initialized. | ||
| // 2. If the button is a mine: | ||
| // - Change the button text to an "X" | ||
| // - Display "You Lose" in a dialog box | ||
| // Otherwise: | ||
| // - Change the button text to the number of neighboring | ||
| // cells are mines. | ||
| // - Decrement `numCellsRemaining` | ||
| // - If all cells are open, display "You Win" in a dialog box | ||
| // - Extra credit: If the number of neighboring cells is 0, | ||
| // automatically open all neighboring cells | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there any way to flag a bomb? Should it be extra credit? |
||
| b.addActionListener(null); // TODO replace null with lambda expression | ||
| gameBoardPanel.add(b); | ||
| }) | ||
| ); | ||
|
|
||
| final JFrame frame = new JFrame(); | ||
| frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); | ||
| frame.setSize(WIDTH * CELL_SIZE, (HEIGHT + 1) * CELL_SIZE + 27); | ||
| frame.setLayout(new BorderLayout()); | ||
| frame.setResizable(false); | ||
| frame.setJMenuBar(menuBar); | ||
| frame.add(gameBoardPanel, BorderLayout.CENTER); | ||
| frame.add(controlPanel, BorderLayout.PAGE_END); | ||
|
|
||
| frame.setVisible(true); | ||
| } | ||
|
|
||
| public static void main(String[] args) { | ||
| System.setProperty("apple.laf.useScreenMenuBar", "true"); | ||
| final MineSweeper mineSweeper = new MineSweeper(); | ||
| SwingUtilities.invokeLater(mineSweeper::createAndShowFrame); | ||
| } | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add tests so that the students can test their code as they progress. This gets them used to TDD and gives them a few carrots along the way. |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the number of cells that do not have a mine and has not yet been opened. The name is not clear and can be misunderstood to mean the number of cells not yet opened, including cells with bombs. It is not clear what this field is used for. All we know is that it is decremented (line 106).