Results 1 to 18 of 18
  1. #1
    Join Date
    Jul 2012
    Posts
    33
    Rep Power
    0

    Default Stanford CS106a Hangman exercise

    Hi

    I've literally just begun doing the Hangman exercise on the online Stanford Cs106a course. Here's what I've done;

    Java Code:
    public class Hangman extends ConsoleProgram {
    
        public void run() {
        	createNewLexicon();
    		playHangman();
    	}
        
        private void createNewLexicon() {
        	lexicon = HangmanLexicon.getWordCount();
        }
        
        private void playHangman() {
        	println("Welcome to Hangman!");
        	int nextword = rgen.nextInt(lexicon);
        	String secretword = HangmanLexicon.getWord(nextword);
        	
        	//get random number from lexicon then use getword to return the string of the secret word.
        	
        }
        private int lexicon;
        private RandomGenerator rgen = RandomGenerator.getInstance();
    }
    I was getting an error on line 9 and line 15 that read something like "can't assign static variable to non-static method". The quick fix suggested by Eclipse was to change the methods in the HangmanLexicon class to static. The HangmanLexicon class is a stub written by Stanford that you use till later in the exercise, when you link the game to a file with a bigger lexicon. I'm just wondering if I'm storing up problems for later if I leave it like this? Is there something I'm doing wrong?

    Thanks! R

  2. #2
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,321
    Rep Power
    25

    Default Re: Stanford CS106a Hangman exercise

    Create an instance of the class using a new statement and use a reference to that instance to call its methods.
    Java Code:
      AClass aRef = new AClass();    // create an instance
      aRef.methodInAClass();          //  call a method
    Don't create a new instance of the class every time you want to call one of its methods. Create one instance and use it as needed.
    If you don't understand my response, don't ignore it, ask a question.

  3. #3
    Join Date
    Jul 2012
    Posts
    33
    Rep Power
    0

    Default Re: Stanford CS106a Hangman exercise

    Quote Originally Posted by Norm View Post
    Create an instance of the class using a new statement and use a reference to that instance to call its methods.
    Java Code:
      AClass aRef = new AClass();    // create an instance
      aRef.methodInAClass();          //  call a method
    Don't create a new instance of the class every time you want to call one of its methods. Create one instance and use it as needed.
    Fantastic, thankyou!

  4. #4
    Join Date
    Jul 2012
    Posts
    33
    Rep Power
    0

    Default Re: Stanford CS106a Hangman exercise

    Hi Norm

    I did some more work on this. Here's where I'm at;

    Java Code:
    public class Hangman extends ConsoleProgram {
    
        public void run() {
        	createNewLexicon();
    		playHangman();
    	}
        
        private void createNewLexicon() {
        	lexicon = lexgen.getWordCount();
        }
        
        private void playHangman() {
        	println("Welcome to Hangman!");
        	int nextword = rgen.nextInt(lexicon);
        	secretword = lexgen.getWord(nextword);
        	wordlength = secretword.length();
        	String initstate = "-";
        	for (int i = 0; i < wordlength; i++) { //creates the initial state of the word as seen by the player
        		initstate = "-" + initstate;
        	}
        	println("The word now looks like this:" + initstate);
        	turns = 8;
        	println("You have 8 guesses left.");
        	stringstate = initstate;
        	while (turns > 0) {
        		String guess = readLine("Your guess: ");
        		if (correctOrIncorrect(guess) == true) {
        			println("That guess is correct");
        			println("The word now looks like this:" + (updateStringState(stringstate, guess)));
        			println("You have " + turns + " guesses left.");
        		}
        			else {
        				println("There are no " + guess + "'s in the word.");
        				turns--;
        				println("The word now looks like this:" + stringstate);
        				println("You have " + turns + " guesses left.");
        			}
        		}
        		
        	}
        
        private boolean correctOrIncorrect(String guess) {  
        	for (int check = 0; check <= wordlength; check++) {
        		String checkpart = secretword.substring(check, check);
        		if (checkpart.equalsIgnoreCase(guess) == true) {
        			return(true);
        		}
        		}
        		return(false);
        	}
        
        	
        private String updateStringState(String stringstate, String guess) {
        	String result = "";
      
        		
        	return result;
        }
        	
        private int wordlength;
        private String stringstate;
        private String secretword;
        private int lexicon;
        private int turns;
        private RandomGenerator rgen = RandomGenerator.getInstance();
        private HangmanLexicon lexgen = new HangmanLexicon();
    }
    Before moving on to writing the updateStringState method at line 53, I thought I'd check the correctOrIncorrect one at 42. I decided to use a boolean to check if it's a correct answer- so as to create two threads for the different effects on turn count and the lines printed after failed or successful guesses. Then if it's a correct guess, the stringstate is fed to the updateStringState method.

    However, correctOrIncorrect is only giving replies of false. I'm assuming that it's possible to use strings of one character? Substring(p1, p2) subdivides the string at position one and everything up to but not including position 2. If I convert guess into a char, there doesnt seem to be many methods I can use...

  5. #5
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,321
    Rep Power
    25

    Default Re: Stanford CS106a Hangman exercise

    correctOrIncorrect is only giving replies of false.
    Try debugging the code to see what it is doing. Add some println statements to print out the values of the variables used in the method to see what the computer sees when it executes the code.
    If you don't understand my response, don't ignore it, ask a question.

  6. #6
    Join Date
    Jul 2012
    Posts
    33
    Rep Power
    0

    Default Re: Stanford CS106a Hangman exercise

    Quote Originally Posted by Norm View Post
    Try debugging the code to see what it is doing. Add some println statements to print out the values of the variables used in the method to see what the computer sees when it executes the code.
    That's really an awesome technique. I did two println's from within the method and the substring is coming up blank for each place on the index it's checking. Thanks again!!!

  7. #7
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,321
    Rep Power
    25

    Default Re: Stanford CS106a Hangman exercise

    substring is coming up blank
    Read the API doc for the methods you are using to make sure you are using them correctly.
    If you don't understand my response, don't ignore it, ask a question.

  8. #8
    Join Date
    Jul 2012
    Posts
    33
    Rep Power
    0

    Default Re: Stanford CS106a Hangman exercise

    Quote Originally Posted by Norm View Post
    Read the API doc for the methods you are using to make sure you are using them correctly.
    Yes, what I was trying to do wasn't possible with that method. So I used a char instead and that part of it now works;

    Java Code:
    public class Hangman extends ConsoleProgram {
    
        public void run() {
        	createNewLexicon();
    		playHangman();
    	}
        
        private void createNewLexicon() {
        	lexicon = lexgen.getWordCount();
        }
        
        private void playHangman() {
        	println("Welcome to Hangman!");
        	int nextword = rgen.nextInt(lexicon);
        	secretword = lexgen.getWord(nextword);
        	wordlength = secretword.length();
        	String initstate = "";
        	for (int i = 0; i < wordlength; i++) { //creates the initial state of the word as seen by the player
        		initstate = "-" + initstate;
        	}
        	println("The word now looks like this:" + initstate);
        	turns = 8;
        	println("You have 8 guesses left.");
        	stringstate = initstate;
        	while (turns > 0) {
        		String input = readLine("Your guess: "); //convert to upper case at this point
        		String guess = input.toUpperCase();
        		if (correctOrIncorrect(guess) == true) {
        			println("That guess is correct");
        			println("The word now looks like this:" + (updateStringState(stringstate, guess)));
        			println("You have " + turns + " guesses left.");
        		}
        		else {
        			println("There are no " + guess + "'s in the word.");
        			turns--;
        			println("The word now looks like this:" + stringstate);
        			println("You have " + turns + " guesses left.");
        			}
        		}
        		
        	}
        
        private boolean correctOrIncorrect(String guess) {  
        	for (int check = 0; check < wordlength; check++) {
        		Character checkpart = secretword.charAt(check);
        		Character guesspart = guess.charAt(0);
        		if (guesspart == checkpart) {
        			return(true);
        		}
        		}
        		return(false);
        	}
        
        	
        private String updateStringState(String stringstate, String guess) {
        	String result = "";
        	for (int check = 0; check < wordlength; check++) {
        		Character checkchar = secretword.charAt(check);
        		Character guesschar = guess.charAt(0);
        		if (guesschar == checkchar) {
        			String part1 = stringstate.substring(0, check);
        			String part2 = stringstate.substring(check + 1);
        			result = part1 + guess + part2;
        		}
        	}	
        	stringstate = result;
        
        	return stringstate;
        	
        }
        	
        private int wordlength;
        private String stringstate;
        private String secretword;
        private int lexicon;
        private int turns;
        private RandomGenerator rgen = RandomGenerator.getInstance();
        private HangmanLexicon lexgen = new HangmanLexicon();
    }
    Now the problem is that stringstate is not being updated. I've made it an ivar thinking that when it gets passed back at lines 66-68 the ivar will be updated, So when it gets called, again after a new guess at line 30, or is used at line 36, it will be the most recent, updated version. Clearly its being wiped at some point and is returning to it's initial state. Do I misunderstand what an ivar does?

  9. #9
    Join Date
    Jul 2012
    Posts
    33
    Rep Power
    0

    Default Re: Stanford CS106a Hangman exercise

    Ok I'm being a moron, I can see I've done that myself by setting result to "" at the beginning of that method. Ignore me...

  10. #10
    Zyril is offline Senior Member
    Join Date
    Oct 2011
    Location
    Sweden
    Posts
    124
    Rep Power
    0

    Default Re: Stanford CS106a Hangman exercise

    (Ignoring)
    Last edited by Zyril; 08-22-2012 at 06:55 PM. Reason: OP solved problem...

  11. #11
    Join Date
    Jul 2012
    Posts
    33
    Rep Power
    0

    Default Re: Stanford CS106a Hangman exercise

    Quote Originally Posted by Norm View Post
    Read the API doc for the methods you are using to make sure you are using them correctly.
    Hiya

    A few days ago you helped me with this Hangman problem. I've now finished the main program, which looks like this;

    Java Code:
    public class Hangman2 extends ConsoleProgram {
    
    	
    	
    	public void init() {
    		canvas = new HangmanCanvas();
    		add(canvas);
    		canvas.reset();
    	}
    	
        public void run() {
        	createNewLexicon();
    		playHangman();
    		endGame();
    	}
        
        private void createNewLexicon() {
        	lexicon = lexgen.getWordCount();
        }
        
        private void playHangman() {
        	println("Welcome to Hangman!");
        	int nextword = rgen.nextInt(lexicon);
        	secretword = lexgen.getWord(nextword);
        	wordlength = secretword.length();
        	String initstate = "";
        	for (int i = 0; i < wordlength; i++) { //creates the initial state of the word as seen by the player
        		initstate = "-" + initstate;
        	}
        	println("The word now looks like this:" + initstate);
        	turns = 8;
        	println("You have 8 guesses left.");
        	stringstate = initstate;
        	int checknum = 0;
        	canvas.displayWord(stringstate);
        	while (turns > 0) {
        		String input = readLine("Your guess: "); //convert to upper case at this point
        		String guess = input.toUpperCase();
        		Character ch = guess.charAt(0);
        		if (checkLength(guess) == false || Character.isLetter(ch) == false) {
        			println("That is an illegal guess ning-nong, try again.");
        		}
        		if (correctOrIncorrect(guess) == true && checkLength(guess) == true && Character.isLetter(ch) == true && checkRepeat(guess) == false) {
        			println("That guess is correct");
        			checknum = checkCharIncidence(guess) + checknum;
        			for (int check = 0; check < wordlength; check++) {
        	    		Character checkchar = secretword.charAt(check);
        	    		Character guesschar = guess.charAt(0);
        	    		if (guesschar == checkchar) {
        	    			String part1 = stringstate.substring(0, check);
        	    			String part2 = stringstate.substring(check + 1);
        	    			stringstate = part1 + guess + part2;
        	    			canvas.displayWord(stringstate);
        	    		}
        			}
        			if (checknum == wordlength) {
        				println ("You guessed the word " + secretword);
        				println ("You win.");
        				endGame();
        			}
        			println("The word now looks like this:" + stringstate);
        			println("You have " + turns + " guesses left.");
        		}
        		if (correctOrIncorrect(guess) == false && Character.isLetter(ch) == true && checkLength(guess) == true) {
        			canvas.noteIncorrectGuess(ch);
        			println("There are no " + guess + "'s in the word.");
        			turns--;
        			println("The word now looks like this:" + stringstate);
        			println("You have " + turns + " guesses left.");
        			}
        		}
        	println("You are completely hung! Aaaaargh!");
        	println("The word was: " + secretword);
        	println("You lose.");
        	endGame();
        	}
        
        
        private boolean correctOrIncorrect(String guess) {  
        	for (int check = 0; check < wordlength; check++) {
        		Character checkpart = secretword.charAt(check);
        		Character guesspart = guess.charAt(0);
        		if (guesspart == checkpart) {
        			return(true);
        			}
        		}
        		return(false);
        	}
        
        private boolean checkRepeat(String guess) {
        	for (int check = 0; check < wordlength; check++) {
        		Character checkpart = secretword.charAt(check);
        		Character guesspart = guess.charAt(0);
        		if (guesspart == checkpart) {
        			Character checkstringstate = stringstate.charAt(check);
        			if (checkpart == checkstringstate) {
        				return(true);
        			}
        		}
        	}
        	return(false);		
        }
        private int checkCharIncidence(String guess) {
        	int checknum = 0;
        	for (int times = 0; times < wordlength; times++) {
        		Character checkagainst = secretword.charAt(times);
        		Character checkwith = guess.charAt(0);
        		if (checkagainst == checkwith) {
        			checknum++;
        		}
        	}
        	return checknum;
        }
        private boolean checkLength(String guess) {
        	int length = guess.length();
        	if (length > 1) {
        		return false;
        	}
        	else {
        		return true;
        	}
        }
        
        private void endGame() {
        	pause(9000);
        	System.exit(0);
        	}
        	
        private HangmanCanvas canvas;
        private int wordlength;
        private String stringstate;
        private String secretword;
        private int lexicon;
        private int turns;
        private RandomGenerator rgen = RandomGenerator.getInstance();
        private HangmanLexicon lexgen = new HangmanLexicon();
    }
    I'm now working on the Hangman canvas, which is behaving strangely. It's a split console/graphics game, with the narrative of the game unfolding in the console and then the scaffold etc in the canvas. The course PDF instructs you to reset the canvas at the beginning of the game with a reset method (line 6 below) in the HangmanCanvas class. According to the PDF you're supposed to put the scaffold in this method. In the same class there's another method called NoteIncorrectGuess (line 42 below) where you put the body parts etc for wrong guesses. Here's where I'm at with the Hangman class;

    Java Code:
    public class HangmanCanvas extends GCanvas {
    	
    
    
    /** Resets the display so that only the scaffold appears */
    	public void reset() {
    	wrongguessnum = 0;
    	int width = getWidth();
    	GLine scaffold = new GLine(width + 50, getHeight() / 2 + SCAFFOLD_HEIGHT / 2 + 200, width + 50, getHeight() / 2 - SCAFFOLD_HEIGHT / 2 + 200);
    	add(scaffold);
    	GLine beam = new GLine(width + 50, getHeight() / 2 - SCAFFOLD_HEIGHT / 2 + 200, width + 50 + BEAM_LENGTH, getHeight() / 2 - SCAFFOLD_HEIGHT / 2 + 200);
    	add(beam);
    	GLine string = new GLine(width + 50 + BEAM_LENGTH, getHeight() / 2 - SCAFFOLD_HEIGHT / 2 + 200, width + 50 + BEAM_LENGTH, getHeight() / 2 - SCAFFOLD_HEIGHT / 2 + 200 + ROPE_LENGTH);
    	add(string);
    	GLine testline = new GLine(0, 0, getWidth(), getHeight());
    	testline.setColor(Color.RED);
    	add(testline);
    	
    	}
    
    /**
     * Updates the word on the screen to correspond to the current
     * state of the game.  The argument string shows what letters have
     * been guessed so far; unguessed letters are indicated by hyphens.
     */
    	public void displayWord(String word) {
    		GObject last = getElementAt(getWidth() / 8, getHeight() - 50);
    		if (last != null) {
    		remove(last);
    		}
    		GLabel stringstate = new GLabel(word, getWidth() / 8, getHeight() - 50);
    		stringstate.setFont("Ariel-28");
    		add(stringstate);
    	}
    
    /**
     * Updates the display to correspond to an incorrect guess by the
     * user.  Calling this method causes the next body part to appear
     * on the scaffold and adds the letter to the list of incorrect
     * guesses that appears at the bottom of the window.
     */
    	public void noteIncorrectGuess(char letter) {
    		
    		GObject last = getElementAt(getWidth() / 8, getHeight() - 25);
    		if (last == null) {
    			incorrectguess = "";
    			incorrectguess = incorrectguess + letter;
    			GLabel badguesses = new GLabel(incorrectguess, getWidth() / 8, getHeight() - 25);
    			badguesses.setFont("Ariel-18");
    			add(badguesses);
    		}
    		if (last != null) {
    			remove(last);
    			incorrectguess = incorrectguess + letter;
    			GLabel badguesses = new GLabel(incorrectguess, getWidth() / 8, getHeight() - 25);
    			badguesses.setFont("Ariel-18");
    			add(badguesses);
    		}
    		wrongguessnum++;
    		
    		switch (wrongguessnum) {
    			case 1 : GOval head = new GOval(getWidth() / 2 - HEAD_RADIUS, getHeight() / 2 - SCAFFOLD_HEIGHT / 2 - HEAD_RADIUS + ROPE_LENGTH, HEAD_RADIUS, HEAD_RADIUS);
    					head.setFilled(false);
    					add(head);
    					break;
    			case 2 : GLine body = new GLine(getWidth() / 2, getHeight() / 2 - SCAFFOLD_HEIGHT / 2 - HEAD_RADIUS + ROPE_LENGTH / 2, getWidth() / 2, getHeight() / 2 + BODY_LENGTH / 2);
    					add(body);
    					break;
    			case 3 :
    			case 4 :
    			case 5 :
    			case 6 :
    			case 7 :
    			case 8 :
    			case 9 :
    			
    		}
    		
    	}
    
    /* Constants for the simple version of the picture (in pixels) */
    	private static final int SCAFFOLD_HEIGHT = 360;
    	private static final int BEAM_LENGTH = 144;
    	private static final int ROPE_LENGTH = 18;
    	private static final int HEAD_RADIUS = 36;
    	private static final int BODY_LENGTH = 144;
    	private static final int ARM_OFFSET_FROM_HEAD = 28;
    	private static final int UPPER_ARM_LENGTH = 72;
    	private static final int LOWER_ARM_LENGTH = 44;
    	private static final int HIP_WIDTH = 36;
    	private static final int LEG_LENGTH = 108;
    	private static final int FOOT_LENGTH = 28;
    	
    	private String incorrectguess;
    	private int wrongguessnum;
    }
    The reason why the maths in the graphics statements is all-over the place is because the canvas appears to behave differently from the reset method. I was getting in a muddle trying to work out why they arent behaving the same. On line 15 I made a test line that, on the normal canvas, would create a line going diagonally across the canvas. As far as I can make out, it appears to be a point in the top left hand corner. Normally the x coordinate should go up left to right and the y should go up top to bottom.

    Is there a reason why the reset method would cause the canvas to operate differently?

    Thanks!

  12. #12
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,321
    Rep Power
    25

    Default Re: Stanford CS106a Hangman exercise

    It's impossible/very difficult to test the code because it uses third party classes.
    If you don't understand my response, don't ignore it, ask a question.

  13. #13
    Join Date
    Jul 2012
    Posts
    33
    Rep Power
    0

    Default Re: Stanford CS106a Hangman exercise

    Quote Originally Posted by Norm View Post
    It's impossible/very difficult to test the code because it uses third party classes.
    Yes, the ACM library. HangmanCanvas imports

    import java.awt.Color;

    import acm.graphics.*;

    and Hangman imports

    import acm.program.*;
    import acm.util.*;

    I was hoping you'd spot something obvious. The course is taken by so many students both at Stanford and online, I figured maybe I was writing the reset method wrong...

  14. #14
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,321
    Rep Power
    25

    Default Re: Stanford CS106a Hangman exercise

    I don't know anything about the acm packages and classes so I can't determine what the code is doing or if it is doing it correctly.

    I guess the forum needs a special section for users of the acm package.
    If you don't understand my response, don't ignore it, ask a question.

  15. #15
    Join Date
    Jul 2012
    Posts
    33
    Rep Power
    0

    Default Re: Stanford CS106a Hangman exercise

    Quote Originally Posted by Norm View Post
    I don't know anything about the acm packages and classes so I can't determine what the code is doing or if it is doing it correctly.

    I guess the forum needs a special section for users of the acm package.
    Ok, no worries.

    Anyone here looking at this thread who knows this course and the acm library? If there is and you have any ideas, let me know! Ta

  16. #16
    Join Date
    Jul 2012
    Posts
    33
    Rep Power
    0

    Default Re: Stanford CS106a Hangman exercise

    Quote Originally Posted by Norm View Post
    I don't know anything about the acm packages and classes so I can't determine what the code is doing or if it is doing it correctly.

    I guess the forum needs a special section for users of the acm package.
    Actually it is the methods from the acm package, in this specific context. For some reason when you use getWidth() and getHeight() in relation to the reset method, they both return 0. Which is confusing cos the PDF specifically tells you to do the scaffold from the reset method. Maybe that's what you're supposed to discover. Even if you write a new drawScaffold method and call it from reset, they still return zero.

  17. #17
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,321
    Rep Power
    25

    Default Re: Stanford CS106a Hangman exercise

    If you rewrite the program using java SE there might be more people that could help you.
    If you don't understand my response, don't ignore it, ask a question.

  18. #18
    Join Date
    Jul 2012
    Posts
    33
    Rep Power
    0

    Default Re: Stanford CS106a Hangman exercise

    Quote Originally Posted by Norm View Post
    If you rewrite the program using java SE there might be more people that could help you.
    You have helped me, a great deal. I wrote a GLabel, which is the graphics package's version of println, to read out the values of getWidth() and getHeight()- which is what you told me to do earlier in this thread on a separate problem. Now I know what it's doing I can write the scaffold accordingly.

    This course is good, as of a couple of months ago I had done no programming whatsoever. Should have finished it in another month or so I think. I'm just trying to learn the fundamentals before moving on to C++...

Similar Threads

  1. Stanford CS106a breakout assignment
    By Newbieprogrammer in forum New To Java
    Replies: 3
    Last Post: 08-14-2012, 10:18 AM
  2. Stanford CS106a GraphicsHeirarchy
    By Newbieprogrammer in forum New To Java
    Replies: 0
    Last Post: 07-15-2012, 07:37 PM
  3. Stanford cs106a
    By D.good in forum Introductions
    Replies: 1
    Last Post: 02-04-2012, 06:18 PM
  4. CS106A Stanford University
    By Learning Java in forum New To Java
    Replies: 116
    Last Post: 07-09-2011, 04:43 PM
  5. Class exercise CS106A (Stanford university)
    By ccie007 in forum New To Java
    Replies: 2
    Last Post: 09-11-2010, 01:47 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •