From 3b9b92970a47665e9aad40962af1d97967e7ba30 Mon Sep 17 00:00:00 2001 From: rja8678 Date: Mon, 1 Mar 2021 01:20:15 -0500 Subject: [PATCH 1/4] Changed render to only on clicks not constantly --- src/nick/sweeper/main/Grid.java | 44 +++++- src/nick/sweeper/main/Input.java | 34 ++++- src/nick/sweeper/main/MineSweeper.java | 177 ++++++++++++++----------- src/nick/sweeper/main/Tile.java | 26 +++- src/radar/sweeper/draw/MousePath.java | 34 +++++ 5 files changed, 225 insertions(+), 90 deletions(-) create mode 100644 src/radar/sweeper/draw/MousePath.java diff --git a/src/nick/sweeper/main/Grid.java b/src/nick/sweeper/main/Grid.java index 91ba5b6..798a2db 100644 --- a/src/nick/sweeper/main/Grid.java +++ b/src/nick/sweeper/main/Grid.java @@ -4,6 +4,7 @@ import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; +import java.awt.image.BufferStrategy; import nick.sweeper.ai.AILogic; import nick.sweeper.main.Tile.Type; @@ -20,7 +21,7 @@ public class Grid { */ public static final short squareDrawSize = 35; - public static final boolean drawHighlight = true; + public static final boolean drawHighlight = false; private final int sizeX, sizeY, numMines; @@ -39,6 +40,8 @@ public class Grid { private final MineSweeper game; private Tile highlight; + + private BufferStrategy bs; public Grid(final int xSize, final int ySize, final int mines, final MineSweeper gameObj) { @@ -51,6 +54,7 @@ public Grid(final int xSize, final int ySize, final int mines, final MineSweeper numMines = mines; game = gameObj; + grid = new Tile[sizeX][sizeY]; initGrid( ); } @@ -71,11 +75,26 @@ private final void clearEmptyNeighbors(final Tile t) { } } - public void draw(final Graphics g) { - + public void addGraphics(BufferStrategy bs) { + this.bs = bs; + + // Needs to be called multiple times to fill the buffer + draw(bs); + draw(bs); + draw(bs); + } + + public void draw(BufferStrategy bs) { + Graphics g = bs.getDrawGraphics(); + setOffsets(game.getWidth( ) / 2, game.getHeight( ) / 2); + update( ); + + g.setColor(Color.BLACK); + g.fillRect(0, 0, game.getWidth( ), game.getHeight( )); +// drawTileGrid(g); - if (highlight != null) { + if (highlight != null && drawHighlight) { // Tile X and Y final int tX = highlight.getX( ) - 1; final int tY = highlight.getY( ) - 1; @@ -103,6 +122,8 @@ public void draw(final Graphics g) { g.setColor(Color.GREEN); g.drawString(win, rX, rY); + + game.stop(false); } else if (hitMine) { g.setFont(new Font("Courier New", Font.BOLD, squareDrawSize)); final String lose = "Hit a Mine!"; @@ -117,6 +138,10 @@ public void draw(final Graphics g) { g.setColor(Color.RED); g.drawString(lose, rX, rY); } + + + g.dispose( ); + bs.show( ); } private final void drawTileGrid(final Graphics g) { @@ -148,9 +173,13 @@ private void initGrid( ) { int minesToPlace = numMines; for (int x = 0; x < sizeX; x++) { for (int y = 0; y < sizeY; y++) { + if(x < 2 && y < 2) { + grid[x][y] = new Tile(this, x, y, false); + continue; + } final int spotsLeft = (totalSquares( ) - y) - (x * sizeY); - final double chanceOfMine = (double) (minesToPlace) / spotsLeft; + final double chanceOfMine = (double) (minesToPlace) / (spotsLeft - 4); if (Math.random( ) <= chanceOfMine) { grid[x][y] = new Tile(this, x, y, true); minesToPlace--; @@ -229,7 +258,6 @@ public void onClick(final int pX, final int pY, final boolean flag) { if (s != null) { onClick(s, flag); } - } public void onClick(final Tile s, final boolean flag) { @@ -264,6 +292,8 @@ public void onClick(final Tile s, final boolean flag) { } clearEmptyNeighbors(s); + + draw(bs); } public float percentComplete( ) { @@ -280,7 +310,6 @@ public float percentMines( ) { } public Dimension renderSize( ) { - return new Dimension(sizeX * squareDrawSize, sizeY * squareDrawSize); } @@ -363,6 +392,7 @@ public void update( ) { if (hitMine) { game.stop(true); +// game.restart(); } } diff --git a/src/nick/sweeper/main/Input.java b/src/nick/sweeper/main/Input.java index dbf151b..353852e 100644 --- a/src/nick/sweeper/main/Input.java +++ b/src/nick/sweeper/main/Input.java @@ -6,6 +6,8 @@ import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; +import radar.sweeper.draw.MousePath; + public class Input implements MouseListener, MouseMotionListener, KeyListener { private static int mX, mY; @@ -27,13 +29,21 @@ public static int mouseY( ) { return mY; } - private final Grid g; - - public Input(final Grid g) { + private Grid g; + + private MousePath mousePath; + + public Input() { + } + public void setGrid(Grid g) { this.g = g; } - + + public void setMousePath(MousePath mp) { + this.mousePath = mp; + } + @Override public void keyPressed(final KeyEvent e) { @@ -55,7 +65,7 @@ public void keyTyped(final KeyEvent e) { @Override public void mouseClicked(final MouseEvent e) { - g.onClick(e.getX( ), e.getY( ), e.getButton( ) != MouseEvent.BUTTON1); +// g.onClick(e.getX( ), e.getY( ), e.getButton( ) != MouseEvent.BUTTON1); } @@ -81,11 +91,23 @@ public void mouseMoved(final MouseEvent e) { mX = e.getX( ); mY = e.getY( ); + +// System.out.println(mX+" "+mY); + if(mousePath != null) { + mousePath.hoveredLocation(mX, mY); + } } @Override - public void mousePressed(final MouseEvent arg0) { + public void mousePressed(final MouseEvent e) { + if(e.getButton() == MouseEvent.BUTTON1) { + g.onClick(e.getX( ), e.getY( ), false); + return; + } + if(e.getButton() == MouseEvent.BUTTON2) { + g.onClick(e.getX( ), e.getY( ), true); + } } @Override diff --git a/src/nick/sweeper/main/MineSweeper.java b/src/nick/sweeper/main/MineSweeper.java index 3627a80..e2f5785 100644 --- a/src/nick/sweeper/main/MineSweeper.java +++ b/src/nick/sweeper/main/MineSweeper.java @@ -1,40 +1,45 @@ package nick.sweeper.main; import java.awt.Canvas; -import java.awt.Graphics; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; import java.awt.image.BufferStrategy; import javax.swing.JFrame; import nick.sweeper.ai.AILogic; +import radar.sweeper.draw.MousePath; public final class MineSweeper extends Canvas implements Runnable { private static final long serialVersionUID = 1L; - public static final short height = 25, width = 25, numMines = 90; + public static final short height = 26, width = 50, numMines = 250; +// public static final short height = 15, width = 15, numMines = 20; private static JFrame frame; private static Grid grid; - private static final short maxFPS = 240; - private static boolean isRunning = true; - private static final MineSweeper game = new MineSweeper( ); - - private static final Thread thread = new Thread(game, "Main Thread"); + private static final Input input = new Input(); + + private MineSweeper game; - public static final String name = "FreeSweeper v1.2c"; + private Thread thread; - private static final Input input = new Input(grid); + public static final String name = "FreeSweeper v1.3a"; + + private BufferStrategy bs; public static final boolean debug = false; private static AILogic ai; private static boolean aiEngage = false; + + private MousePath mousePath; public static AILogic getAI( ) { @@ -43,6 +48,11 @@ public static AILogic getAI( ) { public static void main(final String[ ] args) { + MineSweeper game = new MineSweeper(); + Thread thread = new Thread(game, "Main Thread"); + + game.addThread(thread); + frame = new JFrame( ); frame.setResizable(true); @@ -52,9 +62,6 @@ public static void main(final String[ ] args) { frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setMinimumSize(grid.renderSize( )); - frame.addMouseListener(input); - frame.addMouseMotionListener(input); - game.addMouseListener(input); game.addMouseMotionListener(input); @@ -63,6 +70,13 @@ public static void main(final String[ ] args) { frame.add(game); frame.pack( ); + frame.addWindowListener(new WindowAdapter(){ + public void windowClosing(WindowEvent e) { + game.stop(false); + frame.dispose(); + } + }); + frame.setVisible(true); thread.start( ); } @@ -72,32 +86,22 @@ public static void toggleAI( ) { aiEngage = !AILogic.isRunning( ); } + public void addThread(Thread thread) { + this.thread = thread; + } + public MineSweeper( ) { - grid = new Grid(width, height, numMines, this); setPreferredSize(grid.renderSize( )); + + mousePath = new MousePath(grid); + input.setGrid(grid); + input.setMousePath(mousePath); + ai = new AILogic(grid); } - private void render( ) { - - final BufferStrategy bs = getBufferStrategy( ); - - if (bs == null) { - createBufferStrategy(3); - return; - } - - final Graphics g = bs.getDrawGraphics( ); - - g.clearRect(0, 0, getWidth( ), getHeight( )); - grid.draw(g); - - g.dispose( ); - bs.show( ); - } - public int renderHeight( ) { return getHeight( ); @@ -108,56 +112,66 @@ public int renderWidth( ) { return getWidth( ); } - @SuppressWarnings("unused") +// @SuppressWarnings("unused") +// @Override +// public void run( ) { +// +// System.out.printf("%.1f", grid.percentMines( )); +// System.out.println("% of the map is mined."); +// +// final double delta = 1000.0 / 60, minFrameTime = 1000000000.0 / maxFPS; +// +// short fps = 0, ups = 0; +// long lastUpdate = System.currentTimeMillis( ), lastPrint = System.currentTimeMillis( ), +// lastFrameTime = System.nanoTime( ); +// +// while (isRunning) { +// +// if ((lastUpdate + delta) < System.currentTimeMillis( )) { +// // System.out.println("Update"); +// update( ); +// lastUpdate += delta; +// ++ups; +// } +// +// while ((lastFrameTime + minFrameTime) < System.nanoTime( )) { +// render( ); +// lastFrameTime += minFrameTime; +// ++fps; +// } +// +// if ((lastPrint + 1000) < System.currentTimeMillis( )) { +// +// final String basePrint = name + " (" + grid.sizeX( ) + ", " + grid.sizeY( ) + ") | Flags Used: " + grid.flagsUsed( ) + " | Mines: " + grid.numMines( ) + " | " + String.format("%.2f", grid.percentComplete( )) + "% Complete | AI Engaged: " + ai.isAlive( ); +// +// if (debug) { +// frame.setTitle(basePrint + " | UPS: " + ups + " | FPS: " + fps); +// } else { +// frame.setTitle(basePrint); +// } +// +// fps = 0; +// ups = 0; +// lastPrint += 1000; +// } +// +// } +// } + @Override - public void run( ) { - - System.out.printf("%.1f", grid.percentMines( )); - System.out.println("% of the map is mined."); - - final double delta = 1000.0 / 60, minFrameTime = 1000000000.0 / maxFPS; - - short fps = 0, ups = 0; - long lastUpdate = System.currentTimeMillis( ), lastPrint = System.currentTimeMillis( ), - lastFrameTime = System.nanoTime( ); - - while (isRunning) { - - if ((lastUpdate + delta) < System.currentTimeMillis( )) { - // System.out.println("Update"); - update( ); - lastUpdate += delta; - ++ups; - } - - while ((lastFrameTime + minFrameTime) < System.nanoTime( )) { - render( ); - lastFrameTime += minFrameTime; - ++fps; - } - - if ((lastPrint + 1000) < System.currentTimeMillis( )) { - - final String basePrint = name + " (" + grid.sizeX( ) + ", " + grid.sizeY( ) + ") | Flags Used: " + grid.flagsUsed( ) + " | Mines: " + grid.numMines( ) + " | " + String.format("%.2f", grid.percentComplete( )) + "% Complete | AI Engaged: " + ai.isAlive( ); - - if (debug) { - frame.setTitle(basePrint + " | UPS: " + ups + " | FPS: " + fps); - } else { - frame.setTitle(basePrint); - } - - fps = 0; - ups = 0; - lastPrint += 1000; - } - - } + public void run() { + createBufferStrategy(2); + bs = getBufferStrategy( ); + + grid.addGraphics(bs); } public synchronized void stop(final boolean lost) { isRunning = false; AILogic.halt( ); + + mousePath.saveImg("output"); if (lost) { System.out.println("Hit a mine!"); @@ -175,6 +189,20 @@ public synchronized void stop(final boolean lost) { } } + public void restart() { +// frame.remove(game); + + game = new MineSweeper(); + +// frame.add(game); + frame.pack( ); + + frame.setVisible(true); + + thread = new Thread(game, "Main Thread"); + thread.start(); + } + private void update( ) { grid.setOffsets(getWidth( ) / 2, getHeight( ) / 2); @@ -187,4 +215,5 @@ private void update( ) { } + } diff --git a/src/nick/sweeper/main/Tile.java b/src/nick/sweeper/main/Tile.java index a0c5918..ae9d5b9 100644 --- a/src/nick/sweeper/main/Tile.java +++ b/src/nick/sweeper/main/Tile.java @@ -116,20 +116,40 @@ public void render(final Graphics g, final int pX, final int pY, final short siz } } else if (getType( ) == Tile.Type.EMPTY) { - - g.setColor(Color.GRAY); + g.setColor(Color.LIGHT_GRAY); g.fillRect(pX, pY, size, size); } else if (getType( ) == Tile.Type.NUMBER) { g.setColor(Color.LIGHT_GRAY); g.fillRect(pX, pY, size, size); - g.setColor(Color.BLUE); + switch(numMineNeighbors) { + case 1: + g.setColor(Color.BLUE); + break; + case 2: + g.setColor(new Color(36, 142, 60)); + break; + case 3: + g.setColor(new Color(211, 47, 47)); + break; + case 4: + g.setColor(new Color(123, 31, 162)); + break; + case 5: + g.setColor(Color.ORANGE); + break; + default: + g.setColor(Color.CYAN); + } String txt = getDisplayNum( ); final int stringMidHigh = g.getFontMetrics( ).getHeight( ) / 2; final int stringMidWide = g.getFontMetrics( ).stringWidth(txt) / 2; final short squareMid = (short) (size / 2); g.drawString(txt, (pX - stringMidWide) + squareMid, pY + stringMidHigh + squareMid); + }else if(getType() == Tile.Type.MINE) { + g.setColor(Color.RED); + g.fillRect(pX, pY, size, size); } } diff --git a/src/radar/sweeper/draw/MousePath.java b/src/radar/sweeper/draw/MousePath.java new file mode 100644 index 0000000..3960c91 --- /dev/null +++ b/src/radar/sweeper/draw/MousePath.java @@ -0,0 +1,34 @@ +package radar.sweeper.draw; + +import java.awt.Color; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; + +import nick.sweeper.main.Grid; + +public class MousePath { + private BufferedImage img; + + public void hoveredLocation(int x, int y) { + img.setRGB(x, y, Color.WHITE.getRGB()); + } + + public MousePath(Grid grid) { + img = new BufferedImage(grid.renderSize().width, grid.renderSize().height, BufferedImage.TYPE_INT_RGB); + System.out.println(grid.renderSize()); + } + + public void saveImg(String filename) { + File file = new File(filename + ".png"); + + try { + ImageIO.write(img, "png", file); + } catch (IOException e) { + System.out.println("Unable to save image"); + } + System.out.println("Saved image as "+filename+".png"); + } +} From 3d4152836330f3f25a33293c9bb2db66c97d4b2b Mon Sep 17 00:00:00 2001 From: rja8678 Date: Mon, 1 Mar 2021 16:36:45 -0500 Subject: [PATCH 2/4] Fixed AI and made window closing smoother --- src/nick/sweeper/ai/AILogic.java | 1 + src/nick/sweeper/main/Grid.java | 16 ++++- src/nick/sweeper/main/Input.java | 10 ++- src/nick/sweeper/main/MineSweeper.java | 86 +++++++------------------- src/radar/sweeper/draw/MousePath.java | 3 + 5 files changed, 47 insertions(+), 69 deletions(-) diff --git a/src/nick/sweeper/ai/AILogic.java b/src/nick/sweeper/ai/AILogic.java index 5b3b642..6fd2b2b 100644 --- a/src/nick/sweeper/ai/AILogic.java +++ b/src/nick/sweeper/ai/AILogic.java @@ -100,6 +100,7 @@ private byte minesVisible(final Tile[ ] list) { } private void process( ) { + System.out.println("AI Processing"); if (grid.percentComplete( ) >= 100) { System.out.println("Total Runtime: " + totalRuntime + "ms (" + (totalRuntime / 1000) + "s)"); diff --git a/src/nick/sweeper/main/Grid.java b/src/nick/sweeper/main/Grid.java index 798a2db..66568ff 100644 --- a/src/nick/sweeper/main/Grid.java +++ b/src/nick/sweeper/main/Grid.java @@ -123,6 +123,8 @@ public void draw(BufferStrategy bs) { g.setColor(Color.GREEN); g.drawString(win, rX, rY); + g.dispose( ); + bs.show( ); game.stop(false); } else if (hitMine) { g.setFont(new Font("Courier New", Font.BOLD, squareDrawSize)); @@ -137,9 +139,17 @@ public void draw(BufferStrategy bs) { g.setColor(Color.RED); g.drawString(lose, rX, rY); + + + g.dispose( ); + bs.show( ); + game.stop(true); } - + final String basePrint = MineSweeper.name+" (" + sizeX( ) + ", " + sizeY( ) + ") | Flags Used: " + flagsUsed( ) + " | Mines: " + numMines( ) + " | " + String.format("%.2f", percentComplete( )) + "% Complete | AI Engaged: " + MineSweeper.getAI().isAlive( ); + + game.setTitle(basePrint); + g.dispose( ); bs.show( ); } @@ -386,12 +396,12 @@ public void update( ) { setHighLight(tileAt(tX, tY)); } } - if (numKnown( ) == totalSquares( )) { + if (numKnown( ) == totalSquares( ) || numKnown() - flagsUsed() == totalSquares() - numMines()) { completed = true; } if (hitMine) { - game.stop(true); +// game.stop(true); // game.restart(); } diff --git a/src/nick/sweeper/main/Input.java b/src/nick/sweeper/main/Input.java index 353852e..e553e26 100644 --- a/src/nick/sweeper/main/Input.java +++ b/src/nick/sweeper/main/Input.java @@ -6,6 +6,7 @@ import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; +import nick.sweeper.ai.AILogic; import radar.sweeper.draw.MousePath; public class Input implements MouseListener, MouseMotionListener, KeyListener { @@ -48,7 +49,11 @@ public void setMousePath(MousePath mp) { public void keyPressed(final KeyEvent e) { if (e.getKeyCode( ) == KeyEvent.VK_A) { - MineSweeper.toggleAI( ); + if(!MineSweeper.getAI().isAlive()) { + MineSweeper.getAI().start(); + }else { + AILogic.halt(); + } } } @@ -92,7 +97,6 @@ public void mouseMoved(final MouseEvent e) { mX = e.getX( ); mY = e.getY( ); -// System.out.println(mX+" "+mY); if(mousePath != null) { mousePath.hoveredLocation(mX, mY); } @@ -105,7 +109,7 @@ public void mousePressed(final MouseEvent e) { g.onClick(e.getX( ), e.getY( ), false); return; } - if(e.getButton() == MouseEvent.BUTTON2) { + if(e.getButton() == MouseEvent.BUTTON3) { g.onClick(e.getX( ), e.getY( ), true); } } diff --git a/src/nick/sweeper/main/MineSweeper.java b/src/nick/sweeper/main/MineSweeper.java index e2f5785..2a2bbf8 100644 --- a/src/nick/sweeper/main/MineSweeper.java +++ b/src/nick/sweeper/main/MineSweeper.java @@ -14,8 +14,8 @@ public final class MineSweeper extends Canvas implements Runnable { private static final long serialVersionUID = 1L; - public static final short height = 26, width = 50, numMines = 250; -// public static final short height = 15, width = 15, numMines = 20; +// public static final short height = 26, width = 50, numMines = 250; + public static final short height = 15, width = 15, numMines = 20; private static JFrame frame; @@ -42,10 +42,10 @@ public final class MineSweeper extends Canvas implements Runnable { private MousePath mousePath; public static AILogic getAI( ) { - return ai; } + //TODO Use args to override size of board public static void main(final String[ ] args) { MineSweeper game = new MineSweeper(); @@ -72,7 +72,7 @@ public static void main(final String[ ] args) { frame.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e) { - game.stop(false); + game.fastStop(); frame.dispose(); } }); @@ -82,7 +82,6 @@ public void windowClosing(WindowEvent e) { } public static void toggleAI( ) { - aiEngage = !AILogic.isRunning( ); } @@ -111,52 +110,10 @@ public int renderWidth( ) { return getWidth( ); } - -// @SuppressWarnings("unused") -// @Override -// public void run( ) { -// -// System.out.printf("%.1f", grid.percentMines( )); -// System.out.println("% of the map is mined."); -// -// final double delta = 1000.0 / 60, minFrameTime = 1000000000.0 / maxFPS; -// -// short fps = 0, ups = 0; -// long lastUpdate = System.currentTimeMillis( ), lastPrint = System.currentTimeMillis( ), -// lastFrameTime = System.nanoTime( ); -// -// while (isRunning) { -// -// if ((lastUpdate + delta) < System.currentTimeMillis( )) { -// // System.out.println("Update"); -// update( ); -// lastUpdate += delta; -// ++ups; -// } -// -// while ((lastFrameTime + minFrameTime) < System.nanoTime( )) { -// render( ); -// lastFrameTime += minFrameTime; -// ++fps; -// } -// -// if ((lastPrint + 1000) < System.currentTimeMillis( )) { -// -// final String basePrint = name + " (" + grid.sizeX( ) + ", " + grid.sizeY( ) + ") | Flags Used: " + grid.flagsUsed( ) + " | Mines: " + grid.numMines( ) + " | " + String.format("%.2f", grid.percentComplete( )) + "% Complete | AI Engaged: " + ai.isAlive( ); -// -// if (debug) { -// frame.setTitle(basePrint + " | UPS: " + ups + " | FPS: " + fps); -// } else { -// frame.setTitle(basePrint); -// } -// -// fps = 0; -// ups = 0; -// lastPrint += 1000; -// } -// -// } -// } + + public void setTitle(String title) { + frame.setTitle(title); + } @Override public void run() { @@ -166,6 +123,18 @@ public void run() { grid.addGraphics(bs); } + public synchronized void fastStop() { + AILogic.halt(); + mousePath.saveImg("output"); + + try { + ai.join(1000); + thread.join(); + } catch(Exception e) { + System.out.println("Error occured while closing"); + } + } + public synchronized void stop(final boolean lost) { isRunning = false; @@ -175,9 +144,12 @@ public synchronized void stop(final boolean lost) { if (lost) { System.out.println("Hit a mine!"); + }else { + System.out.println("Won game!"); } try { + wait(2000); if (debug) { wait( ); } @@ -202,18 +174,6 @@ public void restart() { thread = new Thread(game, "Main Thread"); thread.start(); } - - private void update( ) { - - grid.setOffsets(getWidth( ) / 2, getHeight( ) / 2); - grid.update( ); - - if (aiEngage && !AILogic.isRunning( )) { - ai.start( ); - aiEngage = false; - } - - } } diff --git a/src/radar/sweeper/draw/MousePath.java b/src/radar/sweeper/draw/MousePath.java index 3960c91..15c68fd 100644 --- a/src/radar/sweeper/draw/MousePath.java +++ b/src/radar/sweeper/draw/MousePath.java @@ -13,6 +13,9 @@ public class MousePath { private BufferedImage img; public void hoveredLocation(int x, int y) { + if(x < 0 || y < 0 || x >= img.getWidth() || y >= img.getHeight()) { + return; + } img.setRGB(x, y, Color.WHITE.getRGB()); } From 4f27f2dfb68cc14d9bde6c6118f7b4f42f473d2c Mon Sep 17 00:00:00 2001 From: rja8678 Date: Mon, 1 Mar 2021 17:05:50 -0500 Subject: [PATCH 3/4] Signed-off-by: rja8678 --- src/nick/sweeper/main/Grid.java | 14 +++--- src/nick/sweeper/main/Input.java | 4 ++ src/nick/sweeper/main/MineSweeper.java | 62 +++++++++++++++++--------- src/radar/sweeper/draw/MousePath.java | 28 +++++++++--- 4 files changed, 76 insertions(+), 32 deletions(-) diff --git a/src/nick/sweeper/main/Grid.java b/src/nick/sweeper/main/Grid.java index 66568ff..0ea34c7 100644 --- a/src/nick/sweeper/main/Grid.java +++ b/src/nick/sweeper/main/Grid.java @@ -21,7 +21,7 @@ public class Grid { */ public static final short squareDrawSize = 35; - public static final boolean drawHighlight = false; + public static final boolean drawHighlight = true; private final int sizeX, sizeY, numMines; @@ -79,19 +79,19 @@ public void addGraphics(BufferStrategy bs) { this.bs = bs; // Needs to be called multiple times to fill the buffer - draw(bs); - draw(bs); - draw(bs); + draw(); + draw(); + draw(); } - public void draw(BufferStrategy bs) { + public void draw() { Graphics g = bs.getDrawGraphics(); setOffsets(game.getWidth( ) / 2, game.getHeight( ) / 2); update( ); g.setColor(Color.BLACK); g.fillRect(0, 0, game.getWidth( ), game.getHeight( )); -// + drawTileGrid(g); if (highlight != null && drawHighlight) { @@ -303,7 +303,7 @@ public void onClick(final Tile s, final boolean flag) { clearEmptyNeighbors(s); - draw(bs); + draw(); } public float percentComplete( ) { diff --git a/src/nick/sweeper/main/Input.java b/src/nick/sweeper/main/Input.java index e553e26..6ef6084 100644 --- a/src/nick/sweeper/main/Input.java +++ b/src/nick/sweeper/main/Input.java @@ -100,6 +100,10 @@ public void mouseMoved(final MouseEvent e) { if(mousePath != null) { mousePath.hoveredLocation(mX, mY); } + + if(Grid.drawHighlight) { + g.draw(); + } } @Override diff --git a/src/nick/sweeper/main/MineSweeper.java b/src/nick/sweeper/main/MineSweeper.java index 2a2bbf8..761cc16 100644 --- a/src/nick/sweeper/main/MineSweeper.java +++ b/src/nick/sweeper/main/MineSweeper.java @@ -15,14 +15,12 @@ public final class MineSweeper extends Canvas implements Runnable { private static final long serialVersionUID = 1L; // public static final short height = 26, width = 50, numMines = 250; - public static final short height = 15, width = 15, numMines = 20; + public static short height = 15, width = 15, numMines = 20; private static JFrame frame; private static Grid grid; - private static boolean isRunning = true; - private static final Input input = new Input(); private MineSweeper game; @@ -36,8 +34,6 @@ public final class MineSweeper extends Canvas implements Runnable { public static final boolean debug = false; private static AILogic ai; - - private static boolean aiEngage = false; private MousePath mousePath; @@ -45,10 +41,33 @@ public static AILogic getAI( ) { return ai; } - //TODO Use args to override size of board + + /** + * @param args Valid arguments are + */ public static void main(final String[ ] args) { - MineSweeper game = new MineSweeper(); + MineSweeper game; + + if(args.length > 0) { + if(args.length < 3) { + System.out.println("Please specify the width and height of the board in the number of spaces and the number of mines to place"); + } + + width = (short) Integer.parseInt(args[0]); + height = (short) Integer.parseInt(args[1]); + numMines = (short) Integer.parseInt(args[2]); + + if(args.length > 3) { + game = new MineSweeper(args[3]); + }else { + game = new MineSweeper(); + } + }else { + game = new MineSweeper(); + } + + Thread thread = new Thread(game, "Main Thread"); game.addThread(thread); @@ -81,25 +100,26 @@ public void windowClosing(WindowEvent e) { thread.start( ); } - public static void toggleAI( ) { - aiEngage = !AILogic.isRunning( ); - } - public void addThread(Thread thread) { this.thread = thread; } - public MineSweeper( ) { + public MineSweeper() { grid = new Grid(width, height, numMines, this); setPreferredSize(grid.renderSize( )); - mousePath = new MousePath(grid); - input.setGrid(grid); - input.setMousePath(mousePath); ai = new AILogic(grid); } + + public MineSweeper(String outputFile) { + this(); + + mousePath = new MousePath(grid, outputFile); + + input.setMousePath(mousePath); + } public int renderHeight( ) { @@ -125,7 +145,10 @@ public void run() { public synchronized void fastStop() { AILogic.halt(); - mousePath.saveImg("output"); + + if(mousePath != null) { + mousePath.saveImg(); + } try { ai.join(1000); @@ -137,10 +160,11 @@ public synchronized void fastStop() { public synchronized void stop(final boolean lost) { - isRunning = false; AILogic.halt( ); - mousePath.saveImg("output"); + if(mousePath != null) { + mousePath.saveImg(); + } if (lost) { System.out.println("Hit a mine!"); @@ -174,6 +198,4 @@ public void restart() { thread = new Thread(game, "Main Thread"); thread.start(); } - - } diff --git a/src/radar/sweeper/draw/MousePath.java b/src/radar/sweeper/draw/MousePath.java index 15c68fd..0eaa202 100644 --- a/src/radar/sweeper/draw/MousePath.java +++ b/src/radar/sweeper/draw/MousePath.java @@ -9,9 +9,19 @@ import nick.sweeper.main.Grid; +/** + * @author Radar + * A class to plot the path of your cursor as you play minesweeper + */ public class MousePath { private BufferedImage img; + private String outFile; + /** + * Function to tell the canvas that the mouse has hovered a point + * @param x The x position of the cursor + * @param y The y position of the cursor + */ public void hoveredLocation(int x, int y) { if(x < 0 || y < 0 || x >= img.getWidth() || y >= img.getHeight()) { return; @@ -19,19 +29,27 @@ public void hoveredLocation(int x, int y) { img.setRGB(x, y, Color.WHITE.getRGB()); } - public MousePath(Grid grid) { + /** + * Creates a new mouse path tracker + * @param grid The grid for the minesweeper game + */ + public MousePath(Grid grid, String outFile) { img = new BufferedImage(grid.renderSize().width, grid.renderSize().height, BufferedImage.TYPE_INT_RGB); - System.out.println(grid.renderSize()); + this.outFile = outFile; } - public void saveImg(String filename) { - File file = new File(filename + ".png"); + /** + * Function to save the mouse path into an image file + * @param filename The name of the file to save the output to without extension (png is used) + */ + public void saveImg() { + File file = new File(outFile + ".png"); try { ImageIO.write(img, "png", file); } catch (IOException e) { System.out.println("Unable to save image"); } - System.out.println("Saved image as "+filename+".png"); + System.out.println("Saved image as "+outFile+".png"); } } From 42dd240e7007afaca6ab8e8c18d6ad8490a6ad6a Mon Sep 17 00:00:00 2001 From: Radar6255 Date: Mon, 1 Mar 2021 17:28:15 -0500 Subject: [PATCH 4/4] Restarts the game when it ends --- src/nick/sweeper/ai/AILogic.java | 1 - src/nick/sweeper/main/Grid.java | 13 +++++-------- src/nick/sweeper/main/MineSweeper.java | 23 ++++++++++++++--------- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/nick/sweeper/ai/AILogic.java b/src/nick/sweeper/ai/AILogic.java index 6fd2b2b..5b3b642 100644 --- a/src/nick/sweeper/ai/AILogic.java +++ b/src/nick/sweeper/ai/AILogic.java @@ -100,7 +100,6 @@ private byte minesVisible(final Tile[ ] list) { } private void process( ) { - System.out.println("AI Processing"); if (grid.percentComplete( ) >= 100) { System.out.println("Total Runtime: " + totalRuntime + "ms (" + (totalRuntime / 1000) + "s)"); diff --git a/src/nick/sweeper/main/Grid.java b/src/nick/sweeper/main/Grid.java index 0ea34c7..0e1d922 100644 --- a/src/nick/sweeper/main/Grid.java +++ b/src/nick/sweeper/main/Grid.java @@ -79,6 +79,7 @@ public void addGraphics(BufferStrategy bs) { this.bs = bs; // Needs to be called multiple times to fill the buffer + // Not quite perfect and doesn't work all the time draw(); draw(); draw(); @@ -125,7 +126,8 @@ public void draw() { g.dispose( ); bs.show( ); - game.stop(false); +// game.stop(false); + game.restart(); } else if (hitMine) { g.setFont(new Font("Courier New", Font.BOLD, squareDrawSize)); final String lose = "Hit a Mine!"; @@ -143,7 +145,8 @@ public void draw() { g.dispose( ); bs.show( ); - game.stop(true); +// game.stop(true); + game.restart(); } final String basePrint = MineSweeper.name+" (" + sizeX( ) + ", " + sizeY( ) + ") | Flags Used: " + flagsUsed( ) + " | Mines: " + numMines( ) + " | " + String.format("%.2f", percentComplete( )) + "% Complete | AI Engaged: " + MineSweeper.getAI().isAlive( ); @@ -399,12 +402,6 @@ public void update( ) { if (numKnown( ) == totalSquares( ) || numKnown() - flagsUsed() == totalSquares() - numMines()) { completed = true; } - - if (hitMine) { -// game.stop(true); -// game.restart(); - } - } } diff --git a/src/nick/sweeper/main/MineSweeper.java b/src/nick/sweeper/main/MineSweeper.java index 761cc16..eb2dec7 100644 --- a/src/nick/sweeper/main/MineSweeper.java +++ b/src/nick/sweeper/main/MineSweeper.java @@ -185,17 +185,22 @@ public synchronized void stop(final boolean lost) { } } - public void restart() { -// frame.remove(game); + public synchronized void restart() { + if(mousePath != null) { + mousePath.saveImg(); + } - game = new MineSweeper(); + try { + wait(2000); + } catch(Exception e) { + System.out.println("Unable to wait to restart"); + } + grid = new Grid(width, height, numMines, this); -// frame.add(game); - frame.pack( ); - - frame.setVisible(true); + input.setGrid(grid); - thread = new Thread(game, "Main Thread"); - thread.start(); + ai = new AILogic(grid); + + grid.addGraphics(bs); } }