NOTE: I apologize for the text wall, but I'm stuck getting my own code to work. I've dug through the other similar questions, but I'm not seeing why I can't get this code to search through everything. I WILL accept semi-cryptic answers that at least point me in the right direction in thanks.
To practice java, and answer a running question I have about minesweeper, I decided to try to build a minesweeper bot to find out exactly what the best possible winning percentage is for a given game start. I'm still working on getting the right behavior in the game portion of the code though, specifically where I have the game revealing squares that don't have adjacent mines. I end up with 0's on the edge of the revealed space, instead of my code searching the tiles around it, like below:
Printing Field:
-
-
-
-
-
-
-
-
-
- 1 1 2 1
- 0 0 0 0 0 1
- 1 0 0 0 1 2 3
- 1 0 0 0 0 0 0 0
- 2 1 0 0 0 0 0
- 1 0 0 0 0 0
- 1 0 0 0 0 0
I am tracking the actual field in a 2 dimensional Character array, and then tracking the revealed spaces in a same-sized Boolean array. I am including the method below that I am running once another method has found a '0', which marks a space without a bomb. I have another method which handles printing the revealed parts out to the current field, and can share that if anyone is curious.
private void checkAround(int x, int y)
{
//this pattern is used to parse out the comma to get the coordinates.
String regex = "[,]";
Pattern pat = Pattern.compile(regex);
ArrayList<String> to_check = new ArrayList<String>(); //the list of coordinates to check.
to_check.add("" + x + "," + y);
revealed_field[x][y] = true; //marking the coordinates as revealed.
do //iterates through the to_check list until nothing is in it.
{
//these next 2 sections handle pulling the next item from to_check
String temp = to_check.get(0);
to_check.remove(0);
String[] xy = pat.split(temp);
int a = Integer.parseInt(xy[0]); //local declaration of x
int b = Integer.parseInt(xy[1]); //local declaration of y
//if either a or b are outside the bounds of the respective axis, we skip the coordinate and move on.
if (b > height-1 || b < 0) continue;
if (a > width-1 || a < 0) continue;
if (bomb_field[b][a] == '0') //if this is not adjacent to a bomb
{
if (a > 0 && revealed_field[b][a-1] == false) //adds the square above to to_check
{
to_check.add("" + (b) + "," + (a-1));
revealed_field[b][a-1] = true;
}
if (b > 0 && revealed_field[b-1][a] == false) //adds the square left to to_check
{
to_check.add("" + (b-1) + "," + (a));
revealed_field[b-1][a] = true;
}
if (b < height-1 && revealed_field[b+1][a] == false) //adds the square right to to_check
{
to_check.add("" + (b+1) + "," + (a));
revealed_field[b+1][a] = true;
}
if (a < width-1 && revealed_field[b][a+1] == false) //adds the square below to to_check
{
to_check.add("" + (b) + "," + (a+1));
revealed_field[b][a+1] = true;
}
}
}
while (to_check.size() > 0); //ends once we have nothing to check.
}
You are storing b first in the list, then a, in the entries in the list. But you are interpreting the entries as if they contain a first, then b.
For example, if the start point is x=4, y=10:
You add "4,10" to the list.
You remove "4,10" from the list.
You check the cell at x=4, y=10.
You add "11,4", "9,4", "10,5" and "10,3" to the list - instead of "4,11", "4,9", "5,10" and "3,10".
Related
I'm making Java Minesweeper for as a simple project, but the program can never count the correct number of bombs. Here is the function, I've written, numFunction() that finds all possible combinations of touching x and y cords and iterates over all of them together. Note that I've used try/catch here to eliminate any index errors:
public static int numTouching(int x, int y){
int n=0;
//define every possible coordinate touching the bomb
//iterate through the lists of coordinates to count the number of touching bombs
int[]xCords = {x-1, x, x+1};
int[]yCords = {y-1, y, y+1};
if(board[x][y] != "B"){
try{
for(int i=0; i<xCords.length; i++){
for(int j=0; j<yCords.length; j++){
int xPos = xCords[i];
int yPos= yCords[j];
if(board[xPos][yPos]=="B" && board[xPos][yPos]!=board[x][y]){
n++;
board[x][y]=n;
}
}
}
}
catch(Exception e){}
}
return n;
}
Here is the sample output for this program (I want to make it so that all of the elements touching B are set to 1):
Column count = 3
0 0 0
0 B 0
0 1 1
Num touching (0,1): 0
Num touching (1,0): 0
0 0 0
0 B 0
0 1 1
The weird thing is that it changes depending on the order of the elements in xCords and yCords (it seems that only the first two values of each array matters). For instance if xCords = {x, x-1, x+1}, and yCords = {y, y-1, y+1}, this is the sample output:
Column count = 3
0 0 0
0 B 1
0 1 0
Num touching (0,1): 0
Num touching (1,0): 0
0 0 0
0 B 1
0 1 0
Thanks in advance.
Your problem is due to java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds, which you cannot see because you are not printing your exceptions in your catch statement. Please add a e.printStackTrace(); into your catch statement to see this in action.
All you need to do is check if your indices are valid, the following code placed right above your =="B" check works for me (also as Holger stated, you should use .equals("B") instead of =="B")
if (xPos < 0 || yPos < 0 || xPos >= board.length || yPos >= board[0].length) {
continue;
}
I don't understand how this exercise return the number's square. In particular I don't understand the sixth line in which there is return statement and after this "+2*x-1". What is the program behavior in that call?
public class Es {
public static int RecCalc(int x) {
if (x==0) {
return 0;
}else {
return RecCalc(x - 1) + 2 * x - 1;
}
}
public static void main(String[] args) {
System.out.println(RecCalc(3));
}
}
We can see how this works with a little algebra:
(x-1)² + 2x - 1
== x² - 2x + 1 + 2x - 1
== x²
If you are unfamiliar with the formula for (x + y)² then you can do (x-1)² by writing it as (x-1)*(x-1) and using the FOIL method or the distributive property. This is left as an exercise for the reader.
Let's step through, one call at a time.
The first call to kick it all off is:
RecCalc(3);
In Java, the return statement will take everything up to the semi-colon.
So, return 3 + 2 will return 5 to the caller.
RecCalc(3) will result in calling:
RecCalc(2) + 2*3 -1;
RecCalc(2) will result in calling:
RecCalc(1) + 2*2 -1;
RecCalc(1) will result in calling:
RecCalc(0) + 2*1 - 1;
RecCalc(0) will return 0.
Now we can work our way back up the call stack.
RecCalc(0) == 0
RecCalc(1) == RecCalc(0) + 2*1 -1 == (0) + 2*1 -1 == 1
RecCalc(2) == RecCalc(1) + 2*2 -1 == (1) + 2*2 -1 == 4
RecCalc(3) == RecCalc(2) + 2*3 -1 == (4) + 2*3 -1 == 9
This doesn't explain the math, but explains the recursion.
Let's look at the math.
As explained by #CodeApprentice, x² = (x-1)² + 2x -1
The real trick to this whole recursive scheme is the (x-1)².
We know that for x = 4, we can use (x-1)² plus some other junk to get the answer.
But that's just the square of 3 plus some other junk!
Now, to get the square of 3, we know that 3² = (x-1)² plus junk.
But that's just the square of 2 plus some other junk!
And so, we work our way down until we get to a trivial answer, where we return 0. (In fact, you could also return 1 for x=1).
I hope that explains it!
If you have 4 things, you can make a square with side 2:
xx
xx
If you want to make a square with side 3, you need 9 things: add 2 things on each of the side and bottom, plus 1 for the corner:
xx.
xx.
..+
Or, to put it another way, add 3 things on each of the side and bottom, take away 1 for the corner.
Generalizing, if you have a square of side length (n-1), to make a square of side length (n), you have to add on 2 lots of (n-1) things, plus one; or 2 lots of (n) things, take away one.
Hence:
number of things in a square of side length n
= (number of things in a square of side length (n-1))
+ 2 * (n-1) + 1
= (number of things in a square of side length (n-1))
+ 2 * n - 1
Perhaps if you put in a print statement it will help.
public static void main(String[] args) {
System.out.println(RecCalc(5));
}
public static int RecCalc(int x) {
if (x == 0) {
return 0;
} else {
int v = RecCalc(x - 1) + 2 * x - 1;
System.out.println((x-1) + " " + (2*x) + " " + (-1));
return v;
}
}
Prints
0 2 -1
1 4 -1
2 6 -1
3 8 -1
4 10 -1
25
Notice that the value of the sum of the last two columns in each line is an odd number. And the sum of any number of consecutive odd numbers starting with 1 is a perfect square. So essentially, this method just sums up the first x odd numbers.
I'm currently working on a homework assignment for my Java OOP class. The assignment is that a mouse is trapped midway in a 30ft long pipe. The mouse needs to move randomly with a 50% chance of going left or right. The mouse can only move a random distance between a min of 3ft and a max distance of 8ft for each move made. The program should keep track of the distance that the mouse is from the left and right ends of the pipe after each move and once it has reached one end of the pipe, the loop should end and it should print out that the mouse has reached whatever end it reached. I'm using the variable fromendL to keep track of the mouse's distance from the left end and fromendR for the other end. The problem i'm encountering is that every time the loop runs it's resetting the values of each variable so and it's never giving me the distance over the course of multiple loops. Everything I believe I have working fine, although it might not be the most efficient way (i'm still fairly new to programming).
I'll attach the code below:
class Main {
public static void main(String[] args)
{
int fromendL;
int fromendR;
int tMin = 3;
int tMax = 8;
int direction;
int travel;
int travelR = 15;
int travelL = 15;
boolean escaped = false;
while (!escaped)
{
direction = (int)(Math.random()* 2 + 1);
travel = (int)(Math.random() * (tMax - tMin) + 3);
if (direction == 1)
{
fromendL = 15 - travel;
fromendR = 30 - 15 + travel;
travelL = travelL - travel;
System.out.println("The mouse has moved: " + travel + " ft to the left" );
System.out.println("The mouse is " + fromendL +" ft from The Left End");
System.out.println("The mouse is " + fromendR +" ft from The Right End\n");
if(travelL == 0 || travelL < 0)
{
escaped = true;
System.out.println("The Mouse has escaped the Left end of the Pipe!");
}
else if (travelR == 30 || travelR > 30)
{
escaped = true;
System.out.println("The Mouse has escaped the Right end of the Pipe!");
}
}
else if (direction == 2)
{
fromendL = 15 + travel;
fromendR = 30 - 15 - travel;
travelR = travelR + travel;
System.out.println("The mouse has moved: " + travel + " ft to the right");
System.out.println("The mouse is " + fromendL +" ft from The Left End");
System.out.println("The mouse is " + fromendR +" ft from The Right End\n");
if(travelR == 30 || travelR > 30)
{
escaped = true;
System.out.println("The Mouse has escaped the Right end of the Pipe!");
}
else if (travelL == 0 || travelL < 0)
{
escaped = true;
System.out.println("The Mouse has escaped the Left end of the Pipe!");
}
}
}
}
}
The following piece of code should solve the original problem. Please analyze it to find some of the improvements compared to your code.
Instead of using two variables to keep the position (fromendLand fromendR), I use a single one (pos). If I know the length of the pipe (which doesn't change) and the position starting from the left side of the pipe, the distance to the right end can be calculated.
Constructs like if (a == 0 || a < 0) are better written like if (a <= 0) in my opinion.
I use the direction as +1 or -1. Just like in mathematics, the negative direction is like going to the left, the positive direction is like going to the right.
The reason that your variables are reset every time lies in
fromendL = 15 - travel;
fromendR = 30 - 15 + travel;
travelL = travelL - travel;
You start from 15 resp 30 over and over again instead of using the last position of the mouse.
My code looks like
(I use tabs for indentation; my eyes are too old to see the subtle 2-character indentations ;) :
class Main {
public static void main(String[] args)
{
static final int tMin = 3;
static final int tMax = 8;
static final int pLength = 30;
int direction;
int travel;
int pos = pLength / 2;
boolean escaped = false;
while (!escaped) {
direction = (int)(Math.random() * 2);
if (direction == 0) direction = -1;
travel = ((int)(Math.random() * (tMax - tMin)) + tMin) * direction;
pos += travel;
System.out.println("The mouse has moved: " + Math.abs(travel) + " ft to the " + (travel > 0 ? "right" : "left"));
System.out.println("The mouse is " + pos +" ft from The Left End");
System.out.println("The mouse is " + (pLength - pos) + " ft from The Right End\n");
if (pos >= pLength || pos <= 0) {
System.out.println("The Mouse has escaped the " + (pos <= 0 ? "Left" : "Right") + " end of the Pipe!");
escaped = true;
}
}
}
}
The ? is a ternary operator. It tests the condition and if true, the expression evaluates to the value directly following the question mark. If false the expression evaluates to the value following the colon. Use it with care, many people don't like it and think it's confusing. And for that reason I've put it between parenthesis so it's clear where the construct starts and ends.
Since pos is either less or equal zero (escaped to the left) or greater or equal 30 (escaped to the right), I only have to test which of both it is. If I know the mouse didn't escape to the left it must have escaped to the right. (The condition of the if already guarantees that the mouse has escaped).
Link to specific problem: https://hyperskill.org/projects/48/stages/258/implement#comment
public class Main {
private static Scanner input = new Scanner(System.in);
public static void edit(char[][] matrix){
System.out.print("Enter the coordinates: ");
String coords = input.nextLine();
String coords2 = coords.replaceAll("\\s", "");
int coordsNum = Integer.parseInt(coords2);
int compare = coordsNum % 10;
int compare2 = coordsNum / 10;
for(int i = 0; i < coords2.length(); i++){
if(compare < 1 || compare > 3 || compare2 < 1 || compare2 > 3){
//Code
edit(matrix);
}
//Check if input are numbers
if(!Character.isDigit(coords2.charAt(i))){
//Code
edit(matrix);
}
}
}
When I the recursion occurs, and I type a new String, the variables coordsNum, compare, and compare2 are not updated from my input. They remain the same whenever my input is below 0 or above 3. I tried making the variables into one single input line but that did not work. There is nothing wrong with the logic either.
Ex) Input: 4 1 -> Recur -> 1 3 -> Print out values, prints 4,1 instead of 1,3
This code is quite strange.
So lets look at what happens:
edit#1 prints "Enter the coordinates: "
You read "4 2" as a whole line into the variable coords.
You create coords2 to "42" by removing whitespace from coords.
you create cordsnum = 42 and compare = 2 and compare2 = 4
You start a for loop of 2 iterations (edit#1for#1)
in edit#1for i = 0 you check bounds for compare and compare2 where compare2 > 3
edit#2 prints "Enter the coordinates: "
You read "2 2" as a whole line into variables coords.
You create coords2 to "22" by removing whitespace from coords.
you create cordsnum = 22 and compare = 2 and compare2 = 2
You start a for loop of 2 iterations (edit#2for)
in edit#2for i = 0 you check bounds for compare and compare2 where non matches
you check if !Character.isDigit("22".charAt(0)), which is false
in edit#2for i = 1 you check bounds AGAIN for compare and compare2 where non matches
you check if !Character.isDigit("22".charAt(1)), which is false
method returns to edit#1, here coord2 is "42", coordnum=42, compare = 2, and compare2 = 4
you check !Character.isDigit("42".charAt(0)), which is false
in edit#1for i = 1 you check AGAIN bounds for compare and compare2 where compare2 > 3
edit#3 prints "Enter the coordinates: "
...
So what I'm not sure why you check if compare2 contains numbers since if it didn't Integer.parseInt(coords2) would throw an exception and you never get to check it. Also checking compare < 1 || compare > 3 || compare2 < 1 || compare2 > 3 twice is the reason why you end up doing another round even when you inputed ok data.
What I want to to understand is that when a method returns it resumes from the callee. It does not care if it called itself since it is a different version of itself with their own variables. When it returns it returns one step and continues just as you would assume with a non recursive call. No difference there at all.
Good luck with your challenge!
This is a brute force attempt at the chromatic number of a matrix. It seems to work in the sense that it gives me the correct number of colors required but instead of 1,2,3,4 it will display 1,2,3,6. For some reason even if the matrix is possibly successful with fewer colors it will still fail and keep going to the max number. Is there a reason why it continues to fail?
"n" is the max number of colors. "v" is the vertex, and "m" is the number of currently used colors.
pseudo code:
http://i42.tinypic.com/deoc2u.jpg
static int color(){
int i;
for(i = 1; i <= n; i++)
{
if(color(0,i)){
return i;}
}
return i;
}
static boolean color(int v, int m) {
if(v > n-1)
return true;
else
{
for(int i = 1; i <= m; i++)
{
boolean match = false;
q[v] = i;
for(int j = 0; j < n; j++)
{
if(input[v][j] == 1)
{
if(q[v] == j+1)
match = true;
}
}
if(match == false)
{
if(color(v+1,m))
return true;
}
}
q[v] = 0;
return false;
}
}
sample output:
File Name: file1
Input
6
0 1 1 0 1 1
1 0 1 1 1 1
1 1 0 1 0 1
0 1 1 0 1 1
1 1 0 1 0 1
1 1 1 1 1 0
1 failed
2 failed
3 failed
4 failed
5 failed
Colors:
1 2 3 1 3 6
Gah, I should be asleep! But I can't count the number of times I've put off an assigment to the absolute last possible moment, so I'm feeling sympathetic regarding your deadline.
It's not really a "brute-force" approach, since that would actually come down to trying each and every possible node coloring combination and check which ones don't conflict. Your approach is a heuristic known as greedy coloring. It can find optimal results but can also yield an arbitrarily bad solution. That said, I've tried manually going through the sample input you've provided (thank you, Microsoft Paint) and following that algorithm the result should indeed be 4 when starting from vertex 0.
So here's what I believe might be wrong with your code. In the following extract...
if(input[v][j] == 1)
{
if(q[v] == j+1)
match = true;
}
You seem to be comparing the color of the current vertex (which will just be i anyway) to a vertex index, rather than the color of that other vertex. I think you'll need to alter the inner test to...
if(i == q[j])
or, if you wish (won't make a difference)...
if(q[i] == q[j])
Also, you're doing a bit too many checks. Vertex 0 can be assigned color 1. Vertex 1 then needs to be checked against vertex 0 if it's adjacent. Vertex 2 needs to be checked against 0 and 1 if they're adjacent, and so on. You're checking against vertices that couldn't have been assigned a color yet. So don't limit j to n but limit it to your current vertex v.
Finally, using a construct like if(match == false) is rather confusing and not necessary. Just use if(!match) instead.
Hope this helps. If you're still stuck and I happen to catch the comments in time, I can provide more pointers.