Advertisement
MagisterRain

Minesweeper 2

Jul 22nd, 2018
283
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.04 KB | None | 0 0
  1. // --------------------
  2. // Tree of project:
  3. //
  4. // jsx.Constants.java
  5. // jsx.Minesweeper.java
  6. // jsx.state.GameState.java
  7. // jsx.state.Flag.java
  8. // jsx.state.Direction.java
  9. // jsx.obj.Cell.java
  10. // jsx.obj.Field.java
  11. // --------------------
  12. // TODO (maybe):
  13. // - add mouse in second thread
  14. // - set UI
  15. // - draw images
  16. // - set auto opening empty cells at usual open and when doubleckicking on numbers
  17. //-------------------------------------------------------------------------------
  18. package jsx;
  19.  
  20. import java.awt.Color;
  21. import java.awt.Dimension;
  22. import java.awt.Font;
  23. import java.awt.FontMetrics;
  24. import java.awt.Graphics;
  25. import java.awt.Graphics2D;
  26. import java.awt.RenderingHints;
  27. import java.awt.event.KeyAdapter;
  28. import java.awt.event.KeyEvent;
  29.  
  30. import javax.swing.JFrame;
  31. import javax.swing.JPanel;
  32. import javax.swing.WindowConstants;
  33.  
  34. import jsx.obj.Cell;
  35. import jsx.obj.Field;
  36. import jsx.state.Direction;
  37. import jsx.state.Flag;
  38. import jsx.state.GameState;
  39.  
  40. public class Minesweeper extends JPanel {
  41.  
  42. Field field;
  43.  
  44. public Minesweeper() {
  45. setPreferredSize(new Dimension(342, 364));
  46. setFocusable(true);
  47. addKeyListener(new KeyAdapter() {
  48. @Override
  49. public void keyPressed(KeyEvent e) {
  50. if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
  51. init();
  52. } else {
  53. if (field.getGameState() == GameState.GAME) {
  54. if (e.getKeyCode() == KeyEvent.VK_ENTER) {
  55. field.click(false);
  56. repaint();
  57. } else if (e.getKeyCode() == KeyEvent.VK_SPACE) {
  58. field.click(true);
  59. repaint();
  60. } else if (e.getKeyCode() == KeyEvent.VK_UP) {
  61. field.move(Direction.UP);
  62. repaint();
  63. } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
  64. field.move(Direction.RIGHT);
  65. repaint();
  66. } else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
  67. field.move(Direction.DOWN);
  68. repaint();
  69. } else if (e.getKeyCode() == KeyEvent.VK_LEFT) {
  70. field.move(Direction.LEFT);
  71. repaint();
  72. }
  73. } else {
  74. init();
  75. }
  76. }
  77. }
  78. });
  79. init();
  80. }
  81.  
  82. void init() {
  83. this.field = new Field();
  84. repaint();
  85. }
  86.  
  87. public int getTextColor(Cell cel) {
  88. if (cel.getFlag() == Flag.MARKED)
  89. return 0xffffff;
  90. switch (cel.getValue()) {
  91. case 1:
  92. return 0x002db7;
  93. case 2:
  94. return 0x167a00;
  95. case 3:
  96. return 0xb70000;
  97. case 4:
  98. return 0x000aa3;
  99. case 5:
  100. return 0xb70000;
  101. case 6:
  102. return 0x8cb8ff;
  103. case 7:
  104. return 0xb70000;
  105. case 8:
  106. return 0x9300a0;
  107. }
  108. return 0;
  109. }
  110.  
  111. public int getTileColor(Cell cel) {
  112. switch (cel.getFlag()) {
  113. case CRUSHED:
  114. return 0xba2500;
  115. case ERROR:
  116. return 0xfffb1e;
  117. case MARKED:
  118. case NONE:
  119. return 0x2b66c4;
  120. case OPEN:
  121. return 0xddeaff;
  122. case VERIFIED:
  123. return 0x16bc00;
  124. }
  125. return 0;
  126. }
  127.  
  128. @Override
  129. public void paint(Graphics g) {
  130. super.paint(g);
  131. g.setColor(new Color(255, 223, 94));
  132. g.fillRect(0, 0, getWidth(), getHeight());
  133.  
  134. if (field.getGameState() == GameState.WIN) {
  135. field.show(true);
  136. } else if (field.getGameState() == GameState.LOSE) {
  137. field.show(false);
  138. }
  139.  
  140. for (int x = 0; x < Constants.XGRD; x++) {
  141. int oX = x * (Constants.SIZE + Constants.DIST) + Constants.BORD;
  142. for (int y = 0; y < Constants.YGRD; y++) {
  143. int oY = y * (Constants.SIZE + Constants.DIST) + Constants.BORD;
  144. drawTile((Graphics2D) g, field.get(x, y), oX, oY, field.isSelected(x, y));
  145. }
  146. }
  147. if (field.getGameState() != GameState.GAME) {
  148. g.setColor(new Color(255, 255, 255, 2));
  149. g.fillRect(0, 0, getWidth(), getHeight());
  150. g.setColor(new Color(44, 44, 44));
  151. Font f = new Font("Arial", Font.BOLD, 80);
  152. g.setFont(f);
  153. FontMetrics fm = getFontMetrics(f);
  154. int w = fm.stringWidth(field.getGameState() == GameState.WIN ? "Win!" : "Lose!");
  155. g.drawString(field.getGameState() == GameState.WIN ? "Win!" : "Lose!", (getWidth() - w) / 2, 188);
  156. }
  157. }
  158.  
  159. void drawTileText(Graphics2D g, int oX, int oY, String text, Color color) {
  160. g.setColor(color);
  161. Font font = new Font("Cambria", Font.BOLD, 20);
  162. g.setFont(font);
  163. FontMetrics fm = getFontMetrics(font);
  164. int w = fm.stringWidth(text);
  165. int h = -(int) fm.getLineMetrics(text, g).getBaselineOffsets()[2];
  166.  
  167. g.drawString(text, oX + (Constants.SIZE - w) / 2, oY + Constants.SIZE - (Constants.SIZE - h) / 2 - 2);
  168. }
  169.  
  170. void drawTile(Graphics2D g, Cell cel, int x, int y, boolean b) {
  171. g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  172. g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);
  173.  
  174. if (b) {
  175. g.setColor(new Color(0x000000));
  176. g.fillRect(x, y, Constants.SIZE, Constants.SIZE);
  177.  
  178. g.setColor(new Color(getTileColor(cel)));
  179. g.fillRect(x + 2, y + 2, Constants.SIZE - 4, Constants.SIZE - 4);
  180. } else {
  181. g.setColor(new Color(getTileColor(cel)));
  182. g.fillRect(x, y, Constants.SIZE, Constants.SIZE);
  183. }
  184.  
  185. if (cel.getFlag() == Flag.MARKED) {
  186. drawTileText(g, x, y, "?", new Color(getTextColor(cel)));
  187. } else if (cel.getFlag() == Flag.OPEN && cel.getValue() > 0) {
  188. drawTileText(g, x, y, String.valueOf(cel.getValue()), new Color(getTextColor(cel)));
  189. }
  190. }
  191.  
  192. public static void main(String[] args) {
  193. JFrame game = new JFrame();
  194. game.setTitle("Minesweeper 2");
  195. game.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
  196. game.setSize(342, 364);
  197. game.setResizable(false);
  198. game.add(new Minesweeper());
  199. game.setLocationRelativeTo(null);
  200. game.setVisible(true);
  201. }
  202. }
  203. //-------------------------------------------------------------------------------
  204. package jsx;
  205.  
  206. public class Constants {
  207.  
  208. public static final int DIST = 2; // margin
  209. public static final int SIZE = 32; // tile size
  210. public static final int BORD = 16; // border
  211. public static final int XGRD = 9; // width of grid
  212. public static final int YGRD = 9; // height of grid
  213. public static final int MINS = 12; // mines in grid
  214.  
  215. }
  216. //-------------------------------------------------------------------------------
  217. package jsx.state;
  218.  
  219. public enum GameState {
  220. GAME, WIN, LOSE;
  221. }
  222. //-------------------------------------------------------------------------------
  223. package jsx.state;
  224.  
  225. public enum Flag {
  226. NONE, OPEN, MARKED, CRUSHED, ERROR, VERIFIED;
  227. }
  228. //-------------------------------------------------------------------------------
  229. package jsx.state;
  230.  
  231. public enum Direction {
  232. UP, RIGHT, DOWN, LEFT;
  233. }
  234. //-------------------------------------------------------------------------------
  235. package jsx.obj;
  236.  
  237. import java.util.ArrayList;
  238. import java.util.List;
  239. import java.util.Random;
  240.  
  241. import jsx.Constants;
  242. import jsx.state.Direction;
  243. import jsx.state.Flag;
  244. import jsx.state.GameState;
  245.  
  246. public class Field {
  247.  
  248. Cell[][] field = new Cell[Constants.XGRD][Constants.YGRD];
  249. int condition = 0;
  250. Random random = new Random();
  251. GameState state = GameState.GAME;
  252. int x = 0; // x of selection
  253. int y = 0; // y of selection
  254.  
  255. public Field() {
  256. // creating field cells
  257. for (int x = 0; x < Constants.XGRD; x++) {
  258. for (int y = 0; y < Constants.YGRD; y++) {
  259. field[x][y] = new Cell();
  260. }
  261. }
  262. // inserting mines
  263. for (int i = 0; i < Constants.MINS + 1; i++) {
  264. int x = random.nextInt(Constants.XGRD);
  265. int y = random.nextInt(Constants.YGRD);
  266. if (field[x][y].isMined()) {
  267. i--;
  268. } else {
  269. field[x][y].setMined();
  270. }
  271. }
  272. // getting win condition
  273. for (int x = 0; x < Constants.XGRD; x++)
  274. for (int y = 0; y < Constants.YGRD; y++)
  275. if (!field[x][y].isMined()) {
  276. List<Cell> temp = getNearby(x, y);
  277. for (Cell cell : temp)
  278. if (cell.isMined())
  279. field[x][y].addValue();
  280. }
  281.  
  282. for (int x = 0; x < Constants.XGRD; x++)
  283. for (int y = 0; y < Constants.YGRD; y++)
  284. if (field[x][y].getValue() > 0)
  285. condition++;
  286. }
  287.  
  288. public Cell get(int x, int y) {
  289. return field[x][y];
  290. }
  291.  
  292. public void checkWin() {
  293. int counter = 0;
  294. for (int x = 0; x < Constants.XGRD; x++)
  295. for (int y = 0; y < Constants.YGRD; y++)
  296. if (field[x][y].getFlag() == Flag.OPEN && field[x][y].getValue() > 0)
  297. counter++;
  298. if (counter == condition)
  299. state = GameState.WIN;
  300. }
  301.  
  302. public GameState getGameState() {
  303. return state;
  304. }
  305.  
  306. List<Cell> getNearby(int x, int y) {
  307. List<Cell> out = new ArrayList<Cell>();
  308. for (int i = -1; i < 2; i++)
  309. for (int j = -1; j < 2; j++)
  310. if (x + i > -1 && x + i < Constants.XGRD && y + j > -1 && y + j < Constants.XGRD)
  311. out.add(field[x + i][y + j]);
  312. return out;
  313. }
  314.  
  315. // b: true - win, false - lose
  316. public void show(boolean b) {
  317. for (int x = 0; x < Constants.XGRD; x++)
  318. for (int y = 0; y < Constants.YGRD; y++)
  319. if (b) {
  320. if (field[x][y].isMined()) {
  321. field[x][y].setFlag(Flag.VERIFIED);
  322. } else if (field[x][y].getFlag() == Flag.NONE) {
  323. field[x][y].setFlag(Flag.OPEN);
  324. }
  325. } else {
  326. if (field[x][y].isMined() && field[x][y].getFlag() == Flag.MARKED) {
  327. field[x][y].setFlag(Flag.VERIFIED);
  328. } else if (!field[x][y].isMined() && field[x][y].getFlag() == Flag.MARKED) {
  329. field[x][y].setFlag(Flag.ERROR);
  330. } else if (field[x][y].isMined()) {
  331. field[x][y].setFlag(Flag.CRUSHED);
  332. } else {
  333. field[x][y].setFlag(Flag.OPEN);
  334. }
  335. }
  336. }
  337.  
  338. // b: true - RMC, left - LMC
  339. public void click(boolean b) {
  340. click(x, y, b);
  341. }
  342.  
  343. // b: true - RMC, left - LMC
  344. public void click(int x, int y, boolean b) {
  345. if (b) {
  346. if (field[x][y].getFlag() == Flag.NONE) {
  347. field[x][y].setFlag(Flag.MARKED);
  348. } else if (field[x][y].getFlag() == Flag.MARKED) {
  349. field[x][y].setFlag(Flag.NONE);
  350. }
  351. } else {
  352. if (field[x][y].getFlag() == Flag.NONE)
  353. if (field[x][y].isMined()) {
  354. state = GameState.LOSE;
  355. field[x][y].setFlag(Flag.CRUSHED);
  356. } else {
  357. field[x][y].setFlag(Flag.OPEN);
  358. checkWin();
  359. }
  360. }
  361. }
  362.  
  363. public int getSelectionX() {
  364. return x;
  365. }
  366.  
  367. public int getSelectionY() {
  368. return y;
  369. }
  370.  
  371. public void move(int ox, int oy) {
  372. x = ox < 0 ? 0 : (ox > Constants.XGRD ? Constants.XGRD : ox);
  373. y = oy < 0 ? 0 : (oy > Constants.YGRD ? Constants.YGRD : oy);
  374. }
  375.  
  376. public void move(Direction d) {
  377. x = x < 0 ? 0 : x;
  378. y = y < 0 ? 0 : y;
  379. if (d == Direction.UP && y > 0)
  380. y--;
  381. if (d == Direction.RIGHT && x < Constants.XGRD)
  382. x++;
  383. if (d == Direction.DOWN && y < Constants.YGRD)
  384. y++;
  385. if (d == Direction.LEFT && x > 0)
  386. x--;
  387. }
  388.  
  389. public boolean isSelected(int ox, int oy) {
  390. return x == ox && y == oy;
  391. }
  392.  
  393. }
  394. //-------------------------------------------------------------------------------
  395. package jsx.obj;
  396.  
  397. import jsx.state.Flag;
  398.  
  399. public class Cell {
  400.  
  401. int value;
  402. boolean mine;
  403. Flag flag;
  404.  
  405. public Cell() {
  406. value = 0;
  407. mine = false;
  408. flag = Flag.NONE;
  409. }
  410.  
  411. public void addValue() {
  412. this.value += 1;
  413. }
  414.  
  415. public void setValue(int i) {
  416. this.value += i;
  417. }
  418.  
  419. public int getValue() {
  420. return value;
  421. }
  422.  
  423. public void setFlag(Flag f) {
  424. this.flag = f;
  425. }
  426.  
  427. public Flag getFlag() {
  428. return flag;
  429. }
  430.  
  431. public void setMined() {
  432. this.mine = true;
  433. }
  434.  
  435. public boolean isMined() {
  436. return mine;
  437. }
  438. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement