Learn to Code
John F. Dumas
contact me | resume | how it works | example programs | testimonials | main page

Help Example: Five

one | two | three | four | five


► QUESTION: The program I'm working on is a color guessing game. The code has an array of colors:

      String[] colors =
      {
         "red", "green", "blue", "yellow", "black", "cyan", "magenta"
      };

And it chooses one at random and challenges the user to guess which color was selected. My code looks right but when I run it, no matter which color I select it says "Incorrect, please try again".

I even added a debug statement:

      if(true)
         System.out.printf("(chosen color: %s)\n", answer);

So when I ran the program I could have it tell me what the chosen color was but even when I type it in exactly, the program still won't accept my answer as being right. Here's my code, can you assist me in figuring out what is wrong?

   import java.util.*;

   public class Guess
   {
      public static void main(String[] args)
      {
         String[] colors =
         {
            "red", "green", "blue", "yellow", "black", "cyan", "magenta"
         };

         System.out.println("The possible colors are:");
         System.out.println("------------------------");

         for(String color : colors)
            System.out.printf("   %s\n", color);

         System.out.println();
         System.out.println("I've just chosen a color at random,");
         System.out.println("see if you can guess which color it is\n");

         Random random = new Random();
         String answer = colors[random.nextInt(colors.length)];

         if(true)
            System.out.printf("(chosen color: %s)\n", answer);

         Scanner input = new Scanner(System.in);

         for(;;)
         {
            System.out.print("Enter guess: ");

            String line = input.nextLine();

            if(line == answer)
            {
               System.out.println("You win!");
               break;
            }

            System.out.println("Incorrect, please try again");
         }
      }
   }


► ANSWER: Looking at your code, I can see why you're a bit confused - at first glance everything looks right. But, consider this snippet:

            if(line == answer)
            {
               System.out.println("You win!");
               break;
            }

Here, we're using '==' to compare what the user supplied (line) with the selected color (answer) but not getting the results we expect, what's the problem? The issue turns out to be related to java's handling of strings.

A java string is an object (just like the object 'Integer', for example), what do you suppose the result of the following would be?

   public class Example
   {
      public static void main(String[] args)
      {
         Integer n1 = new Integer(42);
         Integer n2 = new Integer(42);

         if(n1 == n2)
            System.out.printf("equal");

         else
            System.out.printf("not equal");
      }
   }

When executed, the output (somewhat surprisingly) is "not equal". The reason is that with objects, '==' does not compare object *contents* it compares reference equality (are they the same object). It is reasoning similar to this that causes your program to behave as it does.

When you compare two strings with '==' they are only guaranteed to be equal if (as above) they are the same object. In your program, the strings in your array 'colors' are different objects than the string supplied by the user and stored into 'line'.

Interestingly enough, java's approach here is not the same that c# and c++ utilize (with both of those languages, '==' compares strings for content equality). However, it has been this way since java's creation and is unlikely to change. The solution then is to use the String class's method 'equals' to compare string equality, not '=='.

One final point, the only two classes from 'java.util' that this program uses are 'Scanner' and 'Random'. Importing the entire 'java.util'namespace as in:

   import java.util.*;

is overkill and tells a reader nothing about the actual classes from 'java.util' that this program will use. In a case like this, I think it is better to import the items you need individually. Here's the revised code with the 'import' and '==' issues addressed:

   import java.util.Scanner;
   import java.util.Random;

   public class Guess1
   {
      public static void main(String[] args)
      {
         String[] colors =
         {
            "red", "green", "blue", "yellow", "black", "cyan", "magenta"
         };

         System.out.println("The possible colors are:");
         System.out.println("------------------------");

         for(String color : colors)
            System.out.printf("   %s\n", color);

         System.out.println();
         System.out.println("I've just chosen a color at random,");
         System.out.println("see if you can guess which color it is\n");

         Random random = new Random();
         String answer = colors[random.nextInt(colors.length)];

         if(false)
            System.out.printf("(chosen color: %s)\n", answer);

         Scanner input = new Scanner(System.in);

         for(;;)
         {
            System.out.print("Enter guess: ");

            String line = input.nextLine();

            if(line.equals(answer))
            {
               System.out.println("You win!");
               break;
            }

            System.out.println("Incorrect, please try again");
         }
      }
   }

The java compiler does not have a flag or setting to warn you about this potential issue (direct string comparison) so this is just something you'll have to keep an eye out for in your code going forward.


Reference Files


© John F. Dumas | johnfdumas@gmail.com | main page | top of page