Skip to content

Commit 9ff69aa

Browse files
committed
Initial Commit
0 parents  commit 9ff69aa

File tree

2 files changed

+370
-0
lines changed

2 files changed

+370
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.settings
2+
.classpath
3+
.project
4+
bin/

src/MineSweeper.java

Lines changed: 366 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,366 @@
1+
import java.awt.Color;
2+
import java.awt.Dimension;
3+
import java.awt.Font;
4+
import java.awt.GridLayout;
5+
import java.awt.Insets;
6+
import java.awt.event.MouseAdapter;
7+
import java.awt.event.MouseEvent;
8+
import java.awt.event.WindowEvent;
9+
import java.util.Random;
10+
import javax.swing.AbstractButton;
11+
import javax.swing.JButton;
12+
import javax.swing.JFrame;
13+
import javax.swing.JOptionPane;
14+
import javax.swing.JPanel;
15+
16+
public class MineSweeper{
17+
18+
19+
static int tiles = 300;
20+
static int grid[] = new int[tiles];
21+
static boolean flags[] = new boolean[tiles];
22+
static boolean discovered[] = new boolean[tiles];
23+
static JButton[] buttons = new JButton[tiles];
24+
static int[] xMod = {0, 1, 1, 1, 0, -1, -1, -1};
25+
static int[] yMod = {1, 1, 0, -1, -1, -1, 0, 1};
26+
static JFrame frame;
27+
static JPanel panel;
28+
static Random ran;
29+
static boolean gameOver = false;
30+
static boolean boardGenerated = false;
31+
static int rows, cols;
32+
static int buttonSize = 40;
33+
static int bombAmount = 50;
34+
35+
// possible label colours (1 is blue, 2 is green ect.)
36+
static Color[] label = {new Color(0x0100FE), new Color(0x017F01), new Color(0x0FE0000), new Color(0x010080), new Color(0x810102), new Color(0x008081), new Color(0x000000), new Color(0x808080)};
37+
38+
39+
public static void initialize(){
40+
41+
// rows = (int)Math.sqrt(tiles);
42+
// cols = (int)Math.sqrt(tiles);
43+
rows = 15;
44+
cols = 20;
45+
46+
if(rows * cols != tiles){
47+
System.out.println("Error Invalid Number of Tiles");
48+
}
49+
50+
// initialize objects
51+
ran = new Random();
52+
frame = new JFrame("Tatti Sweeper");
53+
panel = new JPanel();
54+
55+
// create and add buttons to grid
56+
createButtons();
57+
58+
// set default values
59+
clearBoard();
60+
61+
// setup JFrame
62+
frame.getContentPane().add(panel);
63+
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
64+
frame.setResizable(true);
65+
frame.setSize(buttonSize * cols, buttonSize * rows);
66+
frame.setLocationRelativeTo(null);
67+
}
68+
69+
public static void clearBoard(){
70+
// populate arrays
71+
for (int i = 0; i < grid.length; i++){
72+
buttons[i].setEnabled(true);
73+
buttons[i].setText("");
74+
grid[i] = 0;
75+
flags[i] = false;
76+
discovered[i] = false;
77+
}
78+
gameOver = false;
79+
}
80+
81+
private static void generateBoard(int click){
82+
83+
plantBombs(bombAmount, click);
84+
updateButtonLabels();
85+
}
86+
87+
// initilize button objects as well as attach mouse handler
88+
private static void createButtons(){
89+
90+
// loop through buttons
91+
for (int i = 0; i < buttons.length; i++){
92+
93+
buttons[i] = new JButton();
94+
buttons[i].setFont(new Font("verdana", Font.BOLD, 18));
95+
buttons[i].setMargin(new Insets(0, 0, 0, 0));
96+
buttons[i].setPreferredSize(new Dimension(buttonSize, buttonSize));
97+
buttons[i].setMaximumSize(new Dimension(buttonSize, buttonSize));
98+
buttons[i].setActionCommand(Integer.toString(i));
99+
buttons[i].addMouseListener(new MouseAdapter(){
100+
101+
public void mousePressed(MouseEvent e){
102+
103+
int button = Integer.parseInt(((AbstractButton)e.getSource()).getActionCommand());
104+
105+
if(!boardGenerated && e.getButton() != MouseEvent.BUTTON3){
106+
generateBoard(button);
107+
sweep(button);
108+
}
109+
else if(!gameOver){
110+
// seperate right click flags and left click sweeps
111+
if(e.getButton() == MouseEvent.BUTTON3){
112+
// toggles the flag at requested button
113+
flag(button);
114+
}
115+
else{
116+
// normal sweeping
117+
sweep(button);
118+
}
119+
}
120+
}
121+
});
122+
123+
// add buttons to JFrame
124+
panel.add(buttons[i]);
125+
}
126+
127+
// create grid
128+
panel.setLayout(new GridLayout(rows, cols));
129+
130+
// display the window
131+
frame.pack();
132+
frame.setVisible(true);
133+
}
134+
135+
public static void updateButtonLabels(){
136+
137+
// loop through all tiles
138+
for (int i = 0; i < grid.length; i++){
139+
140+
// tiles must be discovered inorder for anything other then flags to be displayed
141+
if(discovered[i]){
142+
if(grid[i] == 0){ // valid range of colours
143+
// blank tiles get set to disabled for effect
144+
buttons[i].setText("");
145+
buttons[i].setEnabled(false);
146+
}
147+
else if(grid[i] < 9 && grid[i] > 0){
148+
buttons[i].setForeground(label[grid[i] - 1]);
149+
buttons[i].setText(Integer.toString(grid[i]));
150+
}
151+
}
152+
153+
// gameover reveals all of the board
154+
if(gameOver){
155+
if(grid[i] > 0 && grid[i] < 9){
156+
buttons[i].setForeground(label[grid[i] - 1]);
157+
buttons[i].setText(Integer.toString(grid[i]));
158+
}
159+
else if(grid[i] == 0){
160+
buttons[i].setEnabled(false);
161+
}
162+
// show bombs as black 'X'
163+
else if(grid[i] == -1){
164+
buttons[i].setForeground(Color.BLACK);
165+
buttons[i].setText("X");
166+
}
167+
}
168+
}
169+
}
170+
171+
// inverts the boolean flag value
172+
private static void flag(int i){
173+
174+
// cannot flag already discovered tiles
175+
if(!discovered[i]){
176+
flags[i] = !flags[i];
177+
// update board
178+
updateButtonLabels();
179+
}
180+
181+
// if tile is flagged, set as red 'F', otherwise clear button (for blank buttons previously marked)
182+
if(flags[i]){
183+
buttons[i].setForeground(Color.RED);
184+
buttons[i].setText("F");
185+
}
186+
else{
187+
buttons[i].setText("");
188+
updateButtonLabels();
189+
}
190+
}
191+
192+
// selects specified amount of tiles to be bombs
193+
public static void plantBombs(int amount, int click){
194+
195+
// loop until desired number is achieved
196+
for (int i = 0; i < amount; i++){
197+
int possibleLocation = ran.nextInt(tiles);
198+
199+
// if tile is not already taken, set tile to be bomb, otherwise reloop
200+
if(grid[possibleLocation] != -1 && possibleLocation != click){
201+
grid[possibleLocation] = -1;
202+
}
203+
else{
204+
i--;
205+
}
206+
}
207+
generateNumbers();
208+
boardGenerated = true;
209+
}
210+
211+
// populates the grid with numbers representing how many bombs are in the surrounding 8 tiles
212+
public static void generateNumbers(){
213+
214+
// loop through grid
215+
for (int i = 0; i < grid.length; i++){
216+
217+
// no markers are needed on tiles with bombs
218+
if(grid[i] != -1){
219+
220+
// counter variable used to keep a running total of bombs
221+
int counter = 0;
222+
223+
// up to 8 possible tiles around
224+
for (int k = 0; k < 8; k++){
225+
226+
// convert 1D array number into rows and cols
227+
// then a modifier is added on to search in 3 x 3 area
228+
int x = i % cols + yMod[k];
229+
int y = i / cols + xMod[k];
230+
231+
// make sure the new values are valid on the grid
232+
if(checkIfValid(x, y)){
233+
// if the grid location is a bomb then add to the total
234+
if(grid[y * cols + x] == -1){
235+
counter++;
236+
}
237+
}
238+
}
239+
// set current tile to total count
240+
grid[i] = counter;
241+
}
242+
}
243+
}
244+
245+
// discovers blank and number tiles around the given source
246+
public static void sweep(int current){
247+
248+
// if current tile is a flag, reveal it (mouse would have clicked on current tile meaning player wanted to reveal flag)
249+
if(flags[current]){
250+
// removes flag and discover
251+
flags[current] = false;
252+
discovered[current] = true;
253+
}
254+
// action depends on tile type
255+
switch (grid[current]) {
256+
// sweeping a bomb loses the game.
257+
case -1:
258+
// sets gameover and displays board
259+
gameOver = true;
260+
updateButtonLabels();
261+
// taunts player
262+
int n = JOptionPane.showConfirmDialog(frame, "You Suck\nTry Again?", "Lol Loser!", JOptionPane.YES_NO_OPTION);
263+
if(n == 0){
264+
boardGenerated = false;
265+
clearBoard();
266+
}
267+
break;
268+
// continues spread of tile is blank
269+
case 0:
270+
discovered[current] = true;
271+
spread(current);
272+
break;
273+
// stops spread on anything thats not blank
274+
default:
275+
discovered[current] = true;
276+
// updateboard
277+
break;
278+
}
279+
updateButtonLabels();
280+
checkWin();
281+
}
282+
283+
// tests of the game has been won
284+
private static void checkWin(){
285+
286+
// assumes the player has won until proven otherwise
287+
boolean win = true;
288+
289+
// loops through grid
290+
for (int i = 0; i < grid.length && win; i++){
291+
// undiscovered nonbomb tiles or unflaged bombs means that the player has not won
292+
if(!discovered[i] && grid[i] != -1){
293+
win = false;
294+
}
295+
}
296+
297+
// on winning
298+
if(win){
299+
int n = JOptionPane.showConfirmDialog(frame, "Winner Winner Chicken Dinner!\n Play another?", "Congrats!", JOptionPane.YES_NO_OPTION);
300+
if(n == 0){
301+
boardGenerated = false;
302+
clearBoard();
303+
}
304+
else{
305+
frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
306+
}
307+
}
308+
}
309+
310+
private static void spread(int i){
311+
312+
// convert values to rows and cols for ease of use;
313+
int x = i % cols;
314+
int y = i / cols;
315+
316+
// test 8 tiles around
317+
for (int k = 0; k < 8; k++){
318+
319+
// add modifier to cordinates to accese surrounding area
320+
int currentX = x + xMod[k];
321+
int currentY = y + yMod[k];
322+
323+
// converts 2 coordinates back to single
324+
int current = currentY * cols + currentX;
325+
326+
// make sure new location is valid the current tile being spread from is a blank space
327+
if(checkIfValid(currentX, currentY) && grid[i] == 0){
328+
329+
// handling diffrent grid types
330+
switch (grid[current]) {
331+
case -1:
332+
// do not continue spreading at bomb
333+
break;
334+
case 0:
335+
// at a blank tile that is not discovered and not flaged, discover and spread from there
336+
if(!discovered[current] && !flags[current]){
337+
discovered[current] = true;
338+
spread(current);
339+
}
340+
break;
341+
default:
342+
// otherwise discover tile
343+
discovered[current] = true;
344+
break;
345+
}
346+
}
347+
}
348+
}
349+
350+
// make sure x and y are in bounds of 0 to row length
351+
public static boolean checkIfValid(int x, int y){
352+
353+
return (x > -1 && x < cols && y > -1 && y < rows);
354+
}
355+
356+
public static void main(String args[]){
357+
358+
javax.swing.SwingUtilities.invokeLater(new Runnable(){
359+
360+
public void run(){
361+
362+
initialize();
363+
}
364+
});
365+
}
366+
}

0 commit comments

Comments
 (0)