+ Reply to Thread
Results 1 to 10 of 10
  1. #1
    Pens win! Pens Win!!! PENS WIN!!!!!
    Join Date
    Jul 2008
    Posts
    7,736
    BG Level
    8

    Java: Basically done, just have one annoying mistake

    Hey there. I'm almost finished with this assignment which basically asks for the following. The user of the program thinks of a number from 1000 to 9999. The program makes an array of Strings with integers 1000-9999(which are converted to Strings), and randomnly picks a number from the range. The program then asks how many "matches" there are in the number, not worrying about the position of the number. Then what the program does is compares each number in the array with the computer's guess, and compares each char of every number to the guess. If there is a match, the match variable is incremented. If the "guessMatch" does not equal "nmatches", then that element in the array is removed.

    So basically, the arraylist after each pass is reduced in size, until there is only 1 element left. Here is the code:

    Code:
    // fill in your information in the line below, and comment it out in order to compile
    // Name: ???   Student ID: ???;
    
    import java.util.ArrayList;
    import java.util.Random;
    
    import javax.swing.JOptionPane;
    
    public class Assignment2 {
      
      private int totalGuess;
      private ArrayList<String> guess;
      private String myGuess;
      private Random random;
      public Assignment2 ( ){
        totalGuess = 0;
        myGuess = "";
        guess = new ArrayList<String>();
        random = new Random();
        for(int i = 1000; i <= 9999 ; i++){ // Adds numbers 1000 to 9999 initially.
          guess.add(Integer.toString(i));
        }
      }
      
      public int myGuessIs() {
        int index = random.nextInt(guess.size());
        myGuess = guess.get((random.nextInt(guess.size()-1)));
        totalGuess++;
        if(guess.size() == 0)
          myGuess = "-1";
         return Integer.parseInt(myGuess);
      }
      public int totalNumGuesses() {
        return totalGuess;
        
      }
      
      public void updateMyGuess(int nmatches) {
        int guessMatches; // fill in code here
        // update the guess based on the number of matches claimed by the user
        for(int i =0 ; i < guess.size(); i++){
          guessMatches = 0;
          for(int j =0; j <= 3 ; j++){
            if(myGuess.charAt(i) == guess.get(j).charAt(i))
              guessMatches++;
          }
          if(nmatches != guessMatches)
            guess.remove(i);
          i+=-1;
        }
      }
         
    
    
    
    
    
    
    // you shouldn't need to change the main function
    public static void main(String[] args) {
      
      Assignment2 gamer = new Assignment2( );
      
      JOptionPane.showMessageDialog(null, "Think of a number between 1000 and 9999.\n Click OK when you are ready...", "Let's play a game", JOptionPane.INFORMATION_MESSAGE);
      int numMatches = 0;
      int myguess = 0;
      
      do {
        myguess = gamer.myGuessIs();
        if (myguess == -1) {
          JOptionPane.showMessageDialog(null, "I don't think your number exists.\n I could be wrong though...", "Mistake", JOptionPane.INFORMATION_MESSAGE);
          System.exit(0);
        }
        String userInput = JOptionPane.showInputDialog("I guess your number is " + myguess + ". How many digits did I guess correctly?");
        // quit if the user input nothing (such as pressed ESC)
        if (userInput == null)
          System.exit(0);
        // parse user input, pop up a warning message if the input is invalid
        try {
          numMatches = Integer.parseInt(userInput.trim());
        }
        catch(Exception exception) {
          JOptionPane.showMessageDialog(null, "Your input is invalid. Please enter a number between 0 and 4", "Warning", JOptionPane.WARNING_MESSAGE);
          numMatches = 0;
        }
        // the number of matches must be between 0 and 4
        if (numMatches < 0 || numMatches > 4) {
          JOptionPane.showMessageDialog(null, "Your input is invalid. Please enter a number between 0 and 4", "Warning", JOptionPane.WARNING_MESSAGE);
          numMatches = 0;
        }
        if (numMatches == 4)
          break;
        // update based on user input
        gamer.updateMyGuess(numMatches);
        
      } while (true);
      
      // the game ends when the user says all 4 digits are correct
      System.out.println("Aha, I got it, your number is " + myguess + ".");
      System.out.println("I did it in " + gamer.totalNumGuesses() + " turns.");
    }
    }
    The output is not what I want it to be, and I cannot figure out why. Can anyone provide some help?

    Thanks!
    -Bori

    P.S - the main function is not to be changed.

  2. #2
    Old Merits
    Join Date
    Mar 2005
    Posts
    1,158
    BG Level
    6

    i +=-1

    which is i = i + -1 could be a problem for you, do you want to increment here or decrement

  3. #3

    for(int i =0 ; i < guess.size(); i++){
    guessMatches = 0;
    for(int j =0; j <= 3 ; j++){
    if(myGuess.charAt(i) == guess.get(j).charAt(i))
    guessMatches++;
    }
    if(nmatches != guessMatches)
    guess.remove(i);
    i+=-1;
    }

    This looks like you mixed up the indices... You run through the ArrayList with i, and through the guess with j, yet you check guess.get(j), although j will only ever get to 3 and won't go through the whole ArrayList. The charAt(i) however should be charAt(j).
    And the i+=-1 is indeed confusing.

  4. #4
    Murder machine with a motor in her nose
    Join Date
    Apr 2007
    Posts
    368
    BG Level
    4
    FFXI Server
    Carbuncle

    if you're not worrying about the position of the number, you have two issues to worry about:
    1) I see what you're doing with the guess.remove(i), i+=-1; (which should be i-=1, really), but as the above poster said you need another loop to actually cycle through your guess list rather than just 4 of them. It should be closer to:

    Code:
    for(int i =0 ; i < guess.size(); i++)
    {
       guessMatches = 0;
       for(int j =0; j <= 3 ; j++)
       {
          for(int k=0; k<=3;k++)
          {
             if(myGuess.charAt(j) == guess.get(i).charAt(k))
                guessMatches++;
          }
       }
       if(nmatches != guessMatches)
       {
          guess.remove(i);
          i-=1;
       }
    }
    of course this doesn't take into account multiples of the same number or number ordering properly. I get the feeling that this program, as described, would get stuck on numbers like 1111 or 1021 (how can you tell 1021 from 2101 1102 1201, etc?). You'd have this issue with any target number with multiples of the same digit, you either match too early and guess the wrong number or end up with too many matches because there's more than 1 digit repeated. i.e. I think of 1000, your program guesses 1102, I say you got 1 number right, but the above algorithm says there's 2 matches due to the duplicate 1s.

    What you'd really need to do for a fair comparison is:
    1) Ask the person "is this your number", first. If the answer is "no", then remove that number from the guess list before doing comparisons
    2) make a copy of the current number being compared and mark off the characters as they're matched, so:
    1000 vs 1102
    round 1: at(0) compared to at(0) 1==1
    set second number at(0) to like 'X'
    next round you're comparing
    1000 vs X102
    looking at at(1)

    Know what I mean?

    That way you won't get duplicate matches on multiple comparisons.

    so something like:

    Code:
    Is this your match...etc
    if no, remove myguess from guess (suggest just storing the offset of your guess, rather than converting it to an int and back)
    
    for(int i =0 ; i < guess.size(); i++)
    {
       guessMatches = 0;
       String TempGuess=guess.get(i);
       for(int j =0; j <= 3 ; j++)
       {
          for(int k=0; k<=3;k++)
          {
             if(myGuess.charAt(j) == TempGuess.charAt(k))
             {
                TempGuess.char(k)='X'; // I don't know the actual syntax for doing this in java, sorry.
                guessMatches++;
                break; //No need to keep looking for matches since each match should only count as 1
             }
          }
       }
       if(nmatches != guessMatches)
       {
          guess.remove(i);
          i-=1;
       }
    }

  5. #5
    so i herd u liek trollin
    Join Date
    Jan 2008
    Posts
    876
    BG Level
    5

    Sorry if I am trolling or something, but I have to say this is impressive for everyone that can understand this stuff. @[email protected]

    Props to everyone who can take computer classes, or actually have a job that involves this type of programming.

    I barely know how to use FFXI commands, nevertheless this stuff. @[email protected]

  6. #6
    Murder machine with a motor in her nose
    Join Date
    Apr 2007
    Posts
    368
    BG Level
    4
    FFXI Server
    Carbuncle

    Also, rather than randomly guessing you could always build a slightly smarter algorithm that makes the first couple guesses as far apart as possible...sort of like how treasure casket guessing works.

    1) make sure your first guess has no repeating digits
    2) if your first guess has 0 matching digits, then just repeat for the next guess
    3) if you match at least 1 digit, pick a guess that contains some # of new digits along the old ones.

    You'd have to play with it to get an algorithm down, but I have a feeling that doing guesses like:
    number to guess: 3195
    1234 -> match 2#s
    1267 -> match 1
    8934 -> match 1
    etc may be more optimal than blind matching since you could end up doing like
    1234 -> match 2
    1236 -> match 2
    1237 -> match 2
    2137 -> match 2
    2138 -> match 2
    etc.

    I'd be curious to know which method ran fewer iterations.

    I'm also highly suspicious that there's probably a much more efficient way to do the guessing without relying on the number's list, since your first 3 guesses should pare the list down from 8000 entries to under 100 or so really fast, right?

    I'd have to think about maybe building a master guess list after the first 3 or 4 guesses, based on doing guesses like:
    1234
    5678
    9012
    3456
    7890

    as the first 5 or 10 guesses to determine which #s are in the answer, for example. Probably using a different array to keep track of which numbers you're sure there aren't any of. i.e.
    # to guess: 3195
    1234 -> 2
    5678 -> 1
    9012 -> 2
    3456 -> 2
    7890 -> 1
    1357 -> 3 odds
    2468 -> 0 evens
    9013 -> 3 at this point we know 13 for sure, know the last numbers are (5 or 7) and (9 or 0) but from 7890 we know only had 1 match, we know it can't be 7 and 9 or 7 and 0 so that leaves us with 5 and (9 or 0). in the above example all our 9 comparisons are next to a 0 comparison so that makes it a bit tougher, but I think I know where I'm going with this.

    i dunno. I'll have to think about it some more.


    Meh. I'm gonna end up messing with this at work on monday, i'm sure of it. T_T

    Re: Klutz
    It's just like learning another language. It looks daunting from the outside, but if you've spent a few years learning it, it becomes second nature.

  7. #7
    Relic Shield
    Join Date
    Jul 2006
    Posts
    1,524
    BG Level
    6
    FFXIV Character
    Ferien Terzo
    FFXIV Server
    Excalibur

    Quote Originally Posted by SnickySnacks View Post
    Re: Klutz
    It's just like learning another language. It looks daunting from the outside, but if you've spent a few years learning it, it becomes second nature.
    Actually, it's processed in the language center of the brain, too. Funny how shit works isn't it?

  8. #8
    Old Merits
    Join Date
    Mar 2005
    Posts
    1,158
    BG Level
    6

    anything without pointers is actually processed from your ass FYI

  9. #9
    Relic Shield
    Join Date
    Jul 2008
    Posts
    1,953
    BG Level
    6
    FFXIV Character
    Audrey Weaver
    FFXIV Server
    Behemoth
    FFXI Server
    Asura

    Quote Originally Posted by Erza View Post
    anything without pointers and recursion is actually processed from your ass FYI
    Appended for completion. I'd put them in the category of 'necessary but not sufficient'.

    But, yeah. Once you get used to it, it's not really that bad. Even the more complicated parts (say, C++ template metaprogramming) are usually just a matter of changing the way you think about things.

  10. #10
    Murder machine with a motor in her nose
    Join Date
    Apr 2007
    Posts
    368
    BG Level
    4
    FFXI Server
    Carbuncle

    Well I got bored and fiddled with this a bit.
    this section:
    Code:
     if(nmatches != guessMatches)
       {
          guess.remove(i);
          i-=1;
       }
    needs to be more like:
    Code:
     if((nmatches > guessMatches) || (!nmatches && guessMatches))
       {
          guess.remove(i);
          i-=1;
       }
    Of course as written it occurs to me that there's no way to determine the ordering of the numbers. So while it will get all 4 numbers correct eventually, it won't necessarily have them in the right order or a way to even know that they're in the wrong order.

    Mine will get the correct #s in about 8 guesses, but not in the right order.

Similar Threads

  1. Did I Just Have a Seizure?
    By Brill Weave in forum General Discussion
    Replies: 39
    Last Post: 2012-03-11, 07:11
  2. Anyone have one of the new Zunes?
    By Ksandra in forum General Discussion
    Replies: 3
    Last Post: 2010-01-06, 12:16
  3. I have an idea. A good one.
    By Genosync in forum General Discussion
    Replies: 45
    Last Post: 2005-04-26, 15:39