A fully functional Minesweeper game in Java that is similar to the one bundled with Windows, and that can be easily enhanced.
1.import java.awt.BorderLayout;
2.import java.awt.GridLayout;
3.import java.awt.event.InputEvent;
4.import java.util.Random;
5.
6.import javax.swing.JButton;
7.import javax.swing.JFrame;
8.import javax.swing.JOptionPane;
9.import javax.swing.JPanel;
10.import javax.swing.JProgressBar;
11.import javax.swing.JToggleButton;
12.import javax.swing.JToolBar;
13.
14.public class Minesweeper extends JFrame {
15.
16. private int columns = 10;
17. private int rows = 10;
18. private static final long serialVersionUID = 1L;
19. // Stores which cells are bombs and which are not
20. boolean jBombs[][] = new boolean[rows][columns];
21. // Stores information on which cell has been displayed
22. boolean jShown[][] = new boolean[rows][columns];
23. // Stores information on surrounding cells
24. int jCells[][] = new int[rows][columns];
25. private int currX, currY = 0;
26. JToggleButton jButtons[] = new JToggleButton[columns*rows];
27. private JPanel jPanel = null;
28. private JToolBar jToolBar = null;
29. private JPanel jContentPane = null;
30. private JButton jBtnNewGame = null;
31. private JProgressBar jProgressBar = null;
32. /**
33. * This is the default constructor
34. */
35. public Minesweeper() {
36. super();
37. initialize();
38. }
39.
40. /**
41. * This method initializes this
42. *
43. * @return void
44. */
45. private void initialize() {
46. this.setSize(436, 315);
47. this.setContentPane(getJPanel());
48. this.setTitle("Minesweeper");
49. }
50.
51. /**
52. * This method initializes jPanel
53. *
54. * @return javax.swing.JPanel
55. */
56. private JPanel getJPanel() {
57. if (jPanel == null) {
58. jPanel = new JPanel();
59. jPanel.setLayout(new BorderLayout());
60. jPanel.add(getJToolBar(), BorderLayout.NORTH);
61. jPanel.add(getJContentPane(), BorderLayout.CENTER);
62. jPanel.add(getJProgressBar(), BorderLayout.SOUTH);
63. }
64. return jPanel;
65. }
66.
67. /**
68. * This method initializes jToolBar
69. *
70. * @return javax.swing.JToolBar
71. */
72. private JToolBar getJToolBar() {
73. if (jToolBar == null) {
74. jToolBar = new JToolBar();
75. jToolBar.setFloatable(false);
76. jToolBar.add(getJBtnNewGame());
77. }
78. return jToolBar;
79. }
80.
81. /**
82. * This method initializes jContentPane
83. *
84. * @return javax.swing.JPanel
85. */
86. private JPanel getJContentPane() {
87. if (jContentPane == null)
88. {
89. GridLayout gridLayout = new GridLayout();
90. gridLayout.setRows(rows);
91. gridLayout.setColumns(columns);
92. jContentPane = new JPanel();
93. jContentPane.setLayout(gridLayout);
94.
95. BuildBoard();
96. }
97.
98. return jContentPane;
99. }
100.
101. private void BuildBoard()
102. {
103. // JContentPane will call this function before jProgressBar was
built when first started
104. if(jProgressBar != null) // So we check to see if the progress
.bar has been initialized
105. {
106. jProgressBar.setValue(0);
107. }
108. jContentPane.removeAll();
109. int i = 0;
110. for(int x = 0; x < rows; x++)
111. {
112. for(int y = 0; y < columns; y++)
113. {
114. currX = x;
115. currY = y;
116. Random randBomb = new Random();
117. jBombs[x][y] = randBomb.nextBoolean() && randBomb.nextBoolean() && randBomb.nextBoolean(); // 13% chances of a bomb
118. jButtons[i] = new JToggleButton("");
119. jButtons[i].addMouseListener(new java.awt.event.MouseAdapter(){
120. public void mouseReleased(java.awt.event.MouseEvent e) {
121. if(e.getModifiers() == InputEvent.BUTTON3_MASK)
122. {
123. markCell(e);
124. }
125. else if(e.getModifiers() == InputEvent.BUTTON1_MASK)
126. {
127. showCell(e);
128. }
129. }
130. });
131. jContentPane.add(jButtons[i]);
132. i++;
133. }
134. }
135.
136. // Build the board
137 for(int x = 0; x < rows; x++)
138. {
139. for(int y = 0; y < columns; y++)
140. {
141. jCells[x][y] = bombCount(x, y);
142. jShown[x][y] = false; // Reset previous values
143. }
144. }
145. jContentPane.setEnabled(true);
146. this.repaint();
147. this.validate();
148. }
149.
150. /**
151. * This method initializes jBtnNewGame
152. *
153. * @return javax.swing.JButton
154. */
155. private JButton getJBtnNewGame() {
156. if (jBtnNewGame == null) {
157. jBtnNewGame = new JButton();
158. jBtnNewGame.setText("New Game");
159. jBtnNewGame.addMouseListener(new java.awt.event.MouseAdapter() {
160. public void mouseReleased(java.awt.event.MouseEvent e) {
161. BuildBoard();
162. }
163. });
164. }
165. return jBtnNewGame;
166. }
167.
168. /**
169. * This method initializes jProgressBar
170. *
171. * @return javax.swing.JProgressBar
172. */
173. private JProgressBar getJProgressBar() {
174. if (jProgressBar == null) {
175. jProgressBar = new JProgressBar();
176. jProgressBar.setMaximum(columns * rows);
177. }
178. return jProgressBar;
179. }
180.
181. public static void main(String args[](
182. {
183.
184. }
185.
186. // Displays all cells marked as bombs
187. private void showAllBombs()
188. {
189. for(int x = 0; x < rows; x++)
190. {
191. for(int y = 0; y < columns; y++)
192. {
193. if(jBombs[x][y] == true)
194. {
195. JToggleButton jButton = findButton(x,y);
196. if(jButton.isEnabled()) // Don't go over the ones that were already counted
197. {
198. jProgressBar.setValue(jProgressBar.getValue() + 1);
199. }
200. jButton.setText("X");
201. jButton.setSelected(true);
202. jButton.setEnabled(false);
203. }
204. }
205. }
206. }
207.
208. private void clearCells(int x, int y)
209. {
210. // If the cell is in bounds
211. if(inBounds(x, y))
212. {
213. if(!jShown[x][y] && jBombs[x][y] == false)
214. {
215. jShown[x][y] = true;
216. JToggleButton jButton = findButton(x,y);
217. if(jCells[x][y] > 0)
218. {
219. jButton.setText(Integer.toString(jCells[x][y]));
220. }
221. else
222. {
223. jButton.setText("");
224. }
225. if(jButton.isEnabled()) // Don't go over the ones that were already counted
226. {
227. jProgressBar.setValue(jProgressBar.getValue() + 1);
228. }
229. jButton.setSelected(true);
230. jButton.setEnabled(false);
231.
232. // Check surrounding cells
233. if(jCells[x][y] == 0)
234. {
235. for(int r = -1; r <= 1; r++)
236. {
237. for(int c = -1; c <= 1; c++)
238. {
239. clearCells(x + r, y + c);
240. }
241. }
242. }
243. }
244. }
245. }
246.
247. private boolean inBounds(int x, int y)
248. {
249. // Check if position is within bounds
250. return 0 <= x && x < jCells.length && 0 <= y && y < jCells[x].length;
251. }
252.
253. private boolean isBomb(JToggleButton jButton)
254. {
255. int i = 0;
256. for(int x = 0; x < rows; x++)
257. {
258. for(int y = 0; y < columns; y++)
259. {
260. if(jButton == jButtons[i])
261. {
262. currX = x;
263. currY = y;
264. return jBombs[x][y];
265. }
266. i++;
267. }
268. }
269. return false;
270. }
271.
272. private void disableBoard()
273. {
274. for(int x = 0; x < rows; x++)
275. {
276. for(int y = 0; y < columns; y++)
277. {
278. JToggleButton jButton = findButton(x,y);
279. jButton.setEnabled(false);
280. }
281. }
282. }
283.
284. private JToggleButton findButton(int x, int y)
285. {
286. return jButtons[(x*rows+y)];
287. }
288.
289. private void showCell(java.awt.event.MouseEvent e)
290. {
291. JToggleButton jButton = (JToggleButton)e.getSource();
292. if(jButton.isEnabled())
293. {
294. jProgressBar.setValue(jProgressBar.getValue() + 1);
295. jButton.setEnabled(false);
296.
297. if(isBomb(jButton))
298. {
299. showAllBombs();
300. jButton.setEnabled(false);
301. JOptionPane.showMessageDialog(null,"You lost " + Math.round((jProgressBar.getPercentComplete() * 100)) + "% through.", "You Lost!", JOptionPane.INFORMATION_MESSAGE);
302. disableBoard();
303. }
304. else
305. {
306. if(jCells[currX][currY] > 0)
307. {
308. jButton.setText(Integer.toString(jCells[currX][currY]));
309. }
310. else if(jCells[currX][currY] == 0)
311. {
312. clearCells(currX, currY);
313. }
314. }
315. }
316. }
317.
318. private int bombCount(int x, int y)
319. {
320. int bombCount = 0;
321.
322. // Count bombs in surrounding cells
323. for(int r = -1; r <= 1; r++)
324. {
325. for(int c = -1; c <= 1; c++)
326. {
327. int newx = x + r;
328. int newy = y + c;
329. if(inBounds(newx, newy))
330. {
331. if(jBombs[newx][newy] == true)
332. {
333. bombCount++;
334. }
335. }
336. }
337. }
338. return bombCount;
339. }
340.
341. private void markCell(java.awt.event.MouseEvent e) // To set and remove the "!" flag
342. {
343. JToggleButton jButton = (JToggleButton)e.getSource();
344. if(jButton.isEnabled())
345. {
346. if(jButton.getText() != "!")
347. {
348. jButton.setText("!");
349. }
350. else
351. {
352. jButton.setText("");
353. }
354. }
355. }
356. } // @jve:decl-index=0:visual-constraint="10,10"
Nathan Pakovskie is an esteemed senior developer and educator in the tech community, best known for his contributions to Geekpedia.com. With a passion for coding and a knack for simplifying complex tech concepts, Nathan has authored several popular tutorials on C# programming, ranging from basic operations to advanced coding techniques. His articles, often characterized by clarity and precision, serve as invaluable resources for both novice and experienced programmers. Beyond his technical expertise, Nathan is an advocate for continuous learning and enjoys exploring emerging technologies in AI and software development. When he’s not coding or writing, Nathan engages in mentoring upcoming developers, emphasizing the importance of both technical skills and creative problem-solving in the ever-evolving world of technology.
Specialties: C# Programming, Technical Writing, Software Development, AI Technologies, Educational Outreach