Reputation: 1117
Below I have posted a snippet of code I have written whilst trying to replicate the game minesweeper in very simplistic terms. I've got a slight query...
The code below generates a pair of co-ordinates, checks to see if the particular co-ordinates are already held in the ArrayList
, and if not, adds them to the list, repeating this process until I have a list of ten mine locations. on running the program I have found that the list contains duplicates when it shouldn't...
public class MineSweeper {
private static ArrayList mines;
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
MineSweeper ms = new MineSweeper();
}
public MineSweeper(){
mines = new ArrayList(10);
generateMines();
showMines();
}
private void generateMines(){
int x = 0, y = 0, mineCount = 0;
Random rnd = new Random();
StringBuilder str = new StringBuilder();
while(mineCount != 10)
{
x = rnd.nextInt(9) + 1;
y = rnd.nextInt(9) + 1;
str.append(x).append(",").append(y);
if(!(mines.contains(str.toString())))
{
mines.add(str);
mineCount ++;
}
str = new StringBuilder();
}
}
private void showMines(){
System.out.println(mines.toString());
}
}
I believed that my if statement
would catch any duplicates but was wrong.
I eventually solved the problem by changing the if statement
to if(!(mines.toString().contains(str)))
Can somebody enlighten me on the difference please?
Upvotes: 1
Views: 383
Reputation: 151
if we look at your if statement:
mines.contains(str.toString())
mines
is an ArrayList
of generic type StringBuilder
(because it had undefined generic type it automatically uses ArrayList<Object>
). This can be checked if you do this
System.out.println(mines.get(1) instanceof StringBuilder); //print true
str
is a StringBuilder
object which you have cast to a String
. You are thus comparing a StringBuilder
object to a String
object. It is important to note that contains()
uses equals()
for comparison.
this can be illustrated with this example:
StringBuilder testStrB = new StringBuilder("test");
System.out.println(testStrB.equals(testStrB.toString())); //print false
in fact, I get the warning that equals()
is used on incompatible types.
with your working statement
mines.toString().contains(str)
it seems that contains()
accepts a CharSequence
, which is a super-interface of StringBuilder
. As mines.toString
uses contains()
of the entire String
searching for a CharSequence
represented by StringBuilder
, it works.
in summary:
your initial (non-working) if statement tried to use (for each element of mines
)
StringBuilder.equals(String)
whereas your working if statement used
String.contains(StringBuilder)
which allows StringBuilder
to be used as a CharSequence
and thus compared.
for interest:
System.out.println(testStrB.toString().equals(testStrB)); //prints false
// (and incompatible types warning)
so a String
cannot EQUAL a StringBuilder
, but can CONTAIN it. Probably because equals()
takes an Object
and contains()
takes a CharSequence
Upvotes: 0
Reputation: 2681
ArrayList contains StringBuilder's and in mines.contains(str.toString())
you compare to a String (str.toString) so you compare a StringBuilder with a String thus they are never equal.
You have quite a number of other problems as well, for example mines field is static, Random is not, etc
Upvotes: 0
Reputation: 311428
You are checking if mines
contains str.toString()
, but adding str
, which is a StringBuilder
instance. Since all the objects you're adding are StringBuilder
s, mines
can't contain a String
.
You should choose which class you're going with, and stick to it. E.g., with String
s:
if (!(mines.contains(str.toString()))) {
mines.add(str.toString());
mineCount++;
}
Upvotes: 2
Reputation: 25
It could be an issue with the "if(!(mines.contains(str.toString())))", i just dont know how the coordinates are saved and accessed by the "ArrayList" object.
Upvotes: 1