Welcome to the Java Programming Forums


The professional, friendly Java community. 21,500 members and growing!


The Java Programming Forums are a community of Java programmers from all around the World. Our members have a wide range of skills and they all have one thing in common: A passion to learn and code Java. We invite beginner Java programmers right through to Java professionals to post here and share your knowledge. Become a part of the community, help others, expand your knowledge of Java and enjoy talking with like minded people. Registration is quick and best of all free. We look forward to meeting you.


>> REGISTER NOW TO START POSTING


Members have full access to the forums. Advertisements are removed for registered users.

Results 1 to 13 of 13

Thread: Minesweeper Recursion Method Help

  1. #1
    Junior Member
    Join Date
    Mar 2013
    Posts
    26
    Thanks
    2
    Thanked 2 Times in 2 Posts

    Default Minesweeper Recursion Method Help

    I am trying to make a java minesweeper game. As you may know, if an empty cell is revealed in minesweeper, it reveals its surrounding cells. I believe making a recursive method should allow this feature to work. Here is my source code:
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    import java.util.Random;
     
    public class GameClass extends JApplet implements ActionListener, MouseListener, MouseMotionListener{
     
    	Random r = new Random();
    	Timer t = new Timer(5, this);
    	Graphics g2;
    	Image offscreen;
    	boolean inGame = true, mouse1 = false, mouse2 = false;
    	int mouseX, mouseY;
    	boolean flags[] = new boolean[100];
    	boolean blockers[] = new boolean[100];
    	int minesX[] = new int[10];
    	int minesY[] = new int[10];
     
    	public void init(){
    		t.start();
    		setSize(400, 400);
    		addMouseListener(this);
    		addMouseMotionListener(this);
    		setFocusable(true);
    		setup();
    		offscreen = createImage(400, 400);
    		g2 = offscreen.getGraphics();
    	}
    	public void update(Graphics g){
    		paint(g);
    	}
    	public void setup(){
    		setMines();
    		setBlockers();
    		setFlags();
    	}
     
    	public void paint(Graphics g){
    		g2.clearRect(0, 0, 400, 400);
    		g2.setColor(Color.BLACK);
    		g2.fillRect(0, 0, 400, 400);
    		if(inGame){
    			g2.setColor(Color.RED);
    			for(int z = 0; z < 10; z++){
    				g2.fillRect(minesX[z], minesY[z], 40, 40);
    			}
    			for(int a = 0; a < 10; a++){
    				for(int b = 0; b < 10; b++){
    					if(!checkMine(a*40, b*40)){
    						g2.setColor(Color.WHITE);
    						if(mines(a*40, b*40) != 0){
    							g2.drawString(""+mines(a*40, b*40), a*40+17, b*40+25);
    						}
    					}
    					if(blockers[(b*10)+a]){
    						g2.setColor(Color.BLUE);
    						g2.fillRect((a*40)+2, (b*40)+2, 36, 36);
    					}
    					if(flags[(b*10)+a]){
    						g2.setColor(Color.GREEN);
    						g2.fillRect((a*40)+2, (b*40)+2, 36, 36);
    					}
    					g2.setColor(Color.WHITE);
    					g2.fillRect(a*40, b*40, 40, 2);
    					g2.fillRect(a*40, b*40, 2, 40);
    					g2.fillRect((a*40)+38, b*40, 2, 40);
    					g2.fillRect(a*40, (b*40)+38, 40, 2);
    				}
    			}
    		}
    		else{
    			g2.setColor(Color.WHITE);
    			g2.drawString("GAME OVER", 0, 10);
    		}
    		g.drawImage(offscreen, 0, 0, this);
    	}
     
    	public void actionPerformed(ActionEvent e){
    		repaint();
    	}
     
    	public int mines(int x, int y){
    		int a = 0;
    		if(checkMine(x-40, y-40)){a++;}
    		if(checkMine(x-40, y)){a++;}
    		if(checkMine(x-40, y+40)){a++;}
    		if(checkMine(x, y-40)){a++;}
    		if(checkMine(x, y+40)){a++;}
    		if(checkMine(x+40, y-40)){a++;}
    		if(checkMine(x+40, y)){a++;}
    		if(checkMine(x+40, y+40)){a++;}
    		return a;
    	}
    	public void setMines(){
    		for(int z = 0; z < 10; z++){
    			minesX[z] = r.nextInt(10)*40;
    			minesY[z] = r.nextInt(10)*40;
    			for(int a = z-1; a >= 0; a--){
    				if(minesX[a] == minesX[z] && minesY[a] == minesY[z]){
    					setMines();
    				}
    			}
    		}
    	}
    	public void setBlockers(){
    		for(int z = 0; z < 100; z++){
    			blockers[z] = true;
    		}
    	}
    	public void setFlags(){
    		for(int z = 0; z < 100; z++){
    			flags[z] = false;
    		}
    	}
    	public void clearBlockers(int x, int y){
    		int c = (int) Math.floor(x);
    		int d = (int) Math.floor(y);
    		if(c < 9){
    			blockers[(d*10)+c+1] = false;
    			if(mines(x+40, y) == 0){
    				clearBlockers(x+40, y);
    			}
    		}
    		if(c > 0){
    			blockers[(d*10)+c-1] = false;
    			if(mines(x+-40, y) == 0){
    				clearBlockers(x-40, y);
    			}
    		}
    		if(d < 9){
    			blockers[(d*10)+c+10] = false;
    			if(mines(x, y+40) == 0){
    				clearBlockers(x, y+40);
    			}
    		}
    		if(d > 0){
    			blockers[(d*10)+c-10] = false;
    			if(mines(x, y-40) == 0){
    				clearBlockers(x, y-40);
    			}
    		}
    		if(c < 9 && d < 9){
    			blockers[(d*10)+c+11] = false;
    			if(mines(x+40, y+40) == 0){
    				clearBlockers(x+40, y+40);
    			}
    		}
    		if(c > 0 && d > 0){
    			blockers[(d*10)+c-11] = false;
    			if(mines(x-40, y-40) == 0){
    				clearBlockers(x-40, y-40);
    			}
    		}
    		if(c < 9 && d > 0){
    			blockers[(d*10)+c+9] = false;
    			if(mines(x-40, y+40) == 0){
    				clearBlockers(x-40, y+40);
    			}
    		}
    		if(c > 0 && d < 9){
    			blockers[(d*10)+c-9] = false;
    			if(mines(x+40, y-40) == 0){
    				clearBlockers(x+40, y-40);
    			}
    		}
    	}
    	public boolean checkMine(int x, int y){
    		boolean a = false;
    		for(int z = 0; z < 10; z++){
    			if(minesX[z] == x && minesY[z] == y){
    				a = true;
    			}
    		}
    		return a;
    	}
     
    	public void mousePressed(MouseEvent e){
    		int code = e.getButton();
    		if(code == MouseEvent.BUTTON1){
    			mouse1 = true;
    		}
    		if(code == MouseEvent.BUTTON3){
    			mouse2 = true;
    		}
    	}
    	public void mouseClicked(MouseEvent e){}
    	public void mouseReleased(MouseEvent e){
    		int code = e.getButton();
    		if(code == MouseEvent.BUTTON1){
    			if(mouse1){
    				int a = (int) Math.floor(mouseX/40);
    				int b = (int) Math.floor(mouseY/40);
    				if(flags[(b*10)+a] == false){
    					blockers[(b*10)+a] = false;
    					if(mines(a*40, b*40) == 0){
    						clearBlockers(mouseX, mouseY);
    					}
    					for(int z = 0; z < 10; z++){
    						if(minesX[z] == a*40 && minesY[z] == b*40){
    							inGame = false;
    						}
    					}
    				}
    				mouse1 = false;
    			}
    		}
    		if(code == MouseEvent.BUTTON3){
    			int a = (int) Math.floor(mouseX/40);
    			int b = (int) Math.floor(mouseY/40);
    			if(flags[(b*10)+a]){
    				flags[(b*10)+a] = false;
    			}
    			else if(blockers[(b*10)+a]){
    				flags[(b*10)+a] = true;
    			}
    			mouse2 = false;
    		}
    	}
    	public void mouseEntered(MouseEvent e){}
    	public void mouseExited(MouseEvent e){}
     
    	public void mouseMoved(MouseEvent e){
    		mouseX = e.getX();
    		mouseY = e.getY();
    	}
    	public void mouseDragged(MouseEvent e){}
     
    }
    The minesX array contains the x positions of all the mines and minesY array for the y positions.
    The blockers array contains the information for whether each cell is revealed or not.
    The flags array contains the information for whether each cell is flagged or not.
    The mouseX and mouseY are the mouse's x and y positions.
    The mouse1 indicates whether the left mouse button is pressed or not, and mouse2 for the right button.

    The mines method returns how many mines surround a specific cell which requires its x and y coordinates.
    The setMines method randomly places 10 mines on the board. It is recursive in case two mines end up spawning in the same cell.
    The setBlockers method makes all the cells be not revealed.
    The setFlags method makes all the cells not flagged.
    The checkMine method checks if given x and y coordinates are where a mine is placed.
    The clearBlockers method is what I'm trying to fix. It clears surrounding cells and checks if they are empty. If they are, it recalls the method with the new cell's coordinates. It is not working right now and I can't figure out why.

    By the way, the cells are numbered in the blockers and flags arrays like so:
    0 1 2 3 4 5 6 7 8 9
    10 11 12 13 14 15 16 17 18 19
    and so on until it reaches 99.

    The x and y positions can be converted to these numbers like so if a is the number and x and y are the coordinates:
    a = (y*10)+x

    I thought all this information may be asked about due to the lack of comments in my code. So far I also do not have any way for the player to win or reset the game. I really hope someone can fix this and whoever can, thank you.


  2. #2
    Super Moderator Norm's Avatar
    Join Date
    May 2010
    Location
    Eastern Florida
    Posts
    25,139
    Thanks
    65
    Thanked 2,720 Times in 2,670 Posts

    Default Re: Minesweeper Recursion Method Help

    I thought all this information may be asked about due to the lack of comments in my code
    Why not put the comments in the code so that everything is in one place. If what was posted here is important, then why isn't in the code?
    If you don't understand my answer, don't ignore it, ask a question.

  3. #3
    Junior Member
    Join Date
    Mar 2013
    Posts
    26
    Thanks
    2
    Thanked 2 Times in 2 Posts

    Default Re: Minesweeper Recursion Method Help

    To me, comments seem to waste space in the code and it is annoying for me when it's simple enough for me to understand it without comments. The information that might normally go into a comment, I already know and am just putting it here for others to understand. I agree that comments can be helpful, but it seems that this might not be so complex that I need comments.

  4. #4
    Super Moderator Norm's Avatar
    Join Date
    May 2010
    Location
    Eastern Florida
    Posts
    25,139
    Thanks
    65
    Thanked 2,720 Times in 2,670 Posts

    Default Re: Minesweeper Recursion Method Help

    Then why all the comments out side of the code in post#1 and the comment:
    I thought all this information may be asked about
    comments seem to waste space in the code
    I pity the poor bloke that has to work on any code that you've written.

    You don't need to comment code that will never be changed.

    If the comments in post #1 aren't needed why post them?
    If you don't understand my answer, don't ignore it, ask a question.

  5. #5
    Junior Member
    Join Date
    Mar 2013
    Posts
    26
    Thanks
    2
    Thanked 2 Times in 2 Posts

    Default Re: Minesweeper Recursion Method Help

    They're not needed for me, but for viewers on this forum who may wonder what all the variables and methods I created stand for. I also code by myself, so the only other people working with my code are members on this forum. Please, I can fix bad commenting habits later, so let's just focus on my problem with this code. What happens is that none of the empty cell's adjacent cells are being cleared and this pops up: java.lang.ArrayIndexOutOfBoundsException. I don't know why it's not working and please help me figure out why.

  6. #6
    Super Moderator Norm's Avatar
    Join Date
    May 2010
    Location
    Eastern Florida
    Posts
    25,139
    Thanks
    65
    Thanked 2,720 Times in 2,670 Posts

    Default Re: Minesweeper Recursion Method Help

    java.lang.ArrayIndexOutOfBoundsException.
    Please copy the full text of the error message and paste it here.
    There is an index to an array that has gone past the end of the array.
    If you don't understand my answer, don't ignore it, ask a question.

  7. #7
    Junior Member
    Join Date
    Mar 2013
    Posts
    26
    Thanks
    2
    Thanked 2 Times in 2 Posts

    Default Re: Minesweeper Recursion Method Help

    This is what is said one time after I launched this game and the first click was a blank cell:

    Exception in thread "AWT-EventQueue-1" java.lang.ArrayIndexOutOfBoundsException: 1951
    at GameClass.clearBlockers(GameClass.java:125)
    at GameClass.mouseReleased(GameClass.java:201)
    at java.awt.Component.processMouseEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$000(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPri vilege(Unknown Source)
    at java.security.ProtectionDomain$1.doIntersectionPri vilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPri vilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilter s(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(U nknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarch y(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

  8. #8
    Super Moderator Norm's Avatar
    Join Date
    May 2010
    Location
    Eastern Florida
    Posts
    25,139
    Thanks
    65
    Thanked 2,720 Times in 2,670 Posts

    Default Re: Minesweeper Recursion Method Help

    Exception in thread "AWT-EventQueue-1" java.lang.ArrayIndexOutOfBoundsException: 1951
    at GameClass.clearBlockers(GameClass.java:125)
    Look at the code at line 125 and see what index variable had the value: 1951
    Then check the logic to see how that variable got that value.
    Add a println statement before line 125 to print out the values of the variables.
    If you don't understand my answer, don't ignore it, ask a question.

  9. #9
    Junior Member
    Join Date
    Mar 2013
    Posts
    26
    Thanks
    2
    Thanked 2 Times in 2 Posts

    Default Re: Minesweeper Recursion Method Help

    I figured out part of my problem: in lines 116 and 117 I forgot to divide the number by 40, so it was requesting a number that was out of the boundaries of an the blockers array. But now I have a stack overflow error which says this:

    Exception in thread "AWT-EventQueue-1" java.lang.StackOverflowError
    at GameClass.clearBlockers(GameClass.java:116)
    at GameClass.clearBlockers(GameClass.java:127)
    at GameClass.clearBlockers(GameClass.java:121)
    at GameClass.clearBlockers(GameClass.java:127)

    After that it keeps alternating between 121 and 127. It alternates between those two numbers in every case I've tried when I click on an empty cell. Does this mean something is wrong in my lines of 121 and 127? Also, instead of revealing nothing, it reveals everything to the right of the empty cell including numbers and mines.

  10. #10
    Super Moderator Norm's Avatar
    Join Date
    May 2010
    Location
    Eastern Florida
    Posts
    25,139
    Thanks
    65
    Thanked 2,720 Times in 2,670 Posts

    Default Re: Minesweeper Recursion Method Help

    There must be recursive calls between the methods at those lines.
    If you don't understand my answer, don't ignore it, ask a question.

  11. #11
    Junior Member
    Join Date
    Mar 2013
    Posts
    26
    Thanks
    2
    Thanked 2 Times in 2 Posts

    Default Re: Minesweeper Recursion Method Help

    So far I found one error: In line 126 I said x+-40 instead of x-40. That didn't do anything to the code when I changed it, though.

  12. #12
    Super Moderator Norm's Avatar
    Join Date
    May 2010
    Location
    Eastern Florida
    Posts
    25,139
    Thanks
    65
    Thanked 2,720 Times in 2,670 Posts

    Default Re: Minesweeper Recursion Method Help

    Print out the variables' values and see why the logic isn't stopping the recursive calls when it should.

    I'm done for tonight.
    If you don't understand my answer, don't ignore it, ask a question.

  13. The Following User Says Thank You to Norm For This Useful Post:

    beansnbacon (April 4th, 2013)

  14. #13
    Junior Member
    Join Date
    Mar 2013
    Posts
    26
    Thanks
    2
    Thanked 2 Times in 2 Posts

    Default Re: Minesweeper Recursion Method Help

    I have fixed another part of the problem. The mouse's x and y were used as the x and y in the clearBlockers method. So when I was detecting whether a neighboring cell had 0 mines, it would always be true because the x and y were not changed to the top left corner of its cell which is required for detecting other mines. What I had to do was change each x for c*40 and y for d*40. What this change did was when I clicked on an empty cell, it revealed all the empty cells to its right and stopped on a number cell. However, the stuff it prints out at the bottom is the same, alternating between line 121 and 127.

    --- Update ---

    I fixed another problem and I'm getting close to fixing the whole thing. I made it only reveal the squares if they were already not revealed, so the method isn't doing a whole bunch of unnecessary work. But now there are still a few small bugs. In some spots it reveals too much and others not enough. It also prints out this:

    Exception in thread "AWT-EventQueue-1" java.lang.ArrayIndexOutOfBoundsException: -1
    at GameClass.clearBlockers(GameClass.java:124)
    at GameClass.clearBlockers(GameClass.java:163)
    at GameClass.clearBlockers(GameClass.java:121)
    at GameClass.clearBlockers(GameClass.java:139)
    at GameClass.clearBlockers(GameClass.java:127)
    at GameClass.clearBlockers(GameClass.java:139)
    at GameClass.clearBlockers(GameClass.java:121)
    at GameClass.clearBlockers(GameClass.java:121)
    at GameClass.clearBlockers(GameClass.java:121)
    at GameClass.mouseReleased(GameClass.java:201)
    at java.awt.Component.processMouseEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$000(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPri vilege(Unknown Source)
    at java.security.ProtectionDomain$1.doIntersectionPri vilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPri vilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilter s(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(U nknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarch y(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

    --- Update ---

    Maybe the problem is that when I type something like blockers[(d*10)+c+10] and the position of the cell is at the very bottom, it is trying to get part of the array that doesn't exist.

    --- Update ---

    SOLVED! My final error was in the last two big if statements of the method. I confused the places of the conditions. Since I changed the method so much in the whole process, here is the updated code:
    public void clearBlockers(int x, int y){
    		int c = (int) Math.floor(x/40);
    		int d = (int) Math.floor(y/40);
    		if(c < 9){
    			if(blockers[(d*10)+c+1] == true){
    				blockers[(d*10)+c+1] = false;
    				if(mines((c*40)+40, d*40) == 0 && checkMine((c*40)+40, d*40) == false){
    					clearBlockers((c*40)+40, d*40);
    				}
    			}
    		}
    		if(c > 0){
    			if(blockers[(d*10)+c-1] == true){
    				blockers[(d*10)+c-1] = false;
    				if(mines((c*40)-40, d*40) == 0 && checkMine((c*40)-40, d*40) == false){
    					clearBlockers((c*40)-40, y);
    				}
    			}
    		}
    		if(d < 9){
    			if(blockers[(d*10)+c+10] == true){
    				blockers[(d*10)+c+10] = false;
    				if(mines(c*40, (d*40)+40) == 0 && checkMine(c*40, (d*40)+40) == false){
    					clearBlockers(c*40, (d*40)+40);
    				}
    			}
    		}
    		if(d > 0){
    			if(blockers[(d*10)+c-10] == true){
    				blockers[(d*10)+c-10] = false;
    				if(mines(c*40, (d*40)-40) == 0 && checkMine(c*40, (d*40)-40) == false){
    					clearBlockers(c*40, (d*40)-40);
    				}
    			}
    		}
    		if(c < 9 && d < 9){
    			if(blockers[(d*10)+c+11] == true){
    				blockers[(d*10)+c+11] = false;
    				if(mines((c*40)+40, (d*40)+40) == 0 && checkMine((c*40)+40, (d*40)+40) == false){
    					clearBlockers((c*40)+40, (d*40)+40);
    				}
    			}
    		}
    		if(c > 0 && d > 0){
    			if(blockers[(d*10)+c-11] == true){
    				blockers[(d*10)+c-11] = false;
    				if(mines((c*40)-40, (d*40)-40) == 0 && checkMine((c*40)-40, (d*40)-40) == false){
    					clearBlockers((c*40)-40, (d*40)-40);
    				}
    			}
    		}
    		if(c > 0 && d < 9){
    			if(blockers[(d*10)+c+9] == true){
    				blockers[(d*10)+c+9] = false;
    				if(mines((c*40)-40, (d*40)+40) == 0 && checkMine((c*40)-40, (d*40)+40) == false){
    					clearBlockers((c*40)-40, (d*40)+40);
    				}
    			}
    		}
    }

Similar Threads

  1. [SOLVED] how to trace recursion variables in a recursive method
    By mia_tech in forum What's Wrong With My Code?
    Replies: 12
    Last Post: May 23rd, 2012, 12:00 PM
  2. GUI minesweeper help
    By naitomea4664 in forum AWT / Java Swing
    Replies: 1
    Last Post: February 23rd, 2012, 08:33 PM
  3. recursion for identifying amount of zeroes in minesweeper demo
    By Nightingale in forum Algorithms & Recursion
    Replies: 1
    Last Post: November 28th, 2011, 03:33 PM
  4. Replies: 2
    Last Post: July 7th, 2011, 03:46 PM
  5. Minesweeper java problem
    By bluez_exe in forum Paid Java Projects
    Replies: 1
    Last Post: March 3rd, 2010, 08:55 PM

Tags for this Thread