Midterm Review Eric Roberts CS 106A February 7, 2010 Karel—Practice #1 Karel Plays Breakout /* * File: BreakoutKarel.java * -----------------------* The BreakoutKarel class solves the Karel problem from the * first practice midterm exam. */ import stanford.karel.*; public class BreakoutKarel extends SuperKarel { public void run() { while (beepersInBag()) { if (beepersPresent()) { pickBeeper(); bounce(); } while (frontIsBlocked()) { bounce(); } stepDiagonally(); } } page 1 of 2 Karel Plays Breakout /* /* * Causes Karel to perform a ricochet bounce, which requires * File: BreakoutKarel.java * no more than turning left. * -----------------------*/ * The BreakoutKarel class solves the Karel problem from the private void bounce() { * first practice midterm exam. turnLeft(); */ } import stanford.karel.*; /* * Step diagonally. The precondition for this call is that public class BreakoutKarel extends SuperKarel { * Karel's front must be clear. The postcondition has Karel * facing in the same direction. public void run() { */ while (beepersInBag()) { private void stepDiagonally() { if (beepersPresent()) { move(); pickBeeper(); if (leftIsClear() && noBeepersPresent()) { bounce(); turnLeft(); } move(); while (frontIsBlocked()) { turnRight(); bounce(); } } } stepDiagonally(); } } } page 2 of 2 Karel—Practice #2 Valentine Karel import stanford.karel.*; public class ValentineKarel extends SuperKarel { /* Runs the program */ public void run() { for (int i = 0; i < 4; i++) { moveUp2Rows(); deliverValentinesToOneRow(); returnToStartOfRow(); } } /* * Moves Karel to the same column, two rows above where * it currently is. The precondition and postcondition * both have Karel facing east. */ private void moveUp2Rows() { turnLeft(); move(); move(); turnRight(); } page 1 of 2 Valentine Karel /* import stanford.karel.*; * Returns Karel to the beginning of the row on which it * begins. The precondition and postcondition both public class ValentineKarel extends SuperKarel { * have Karel facing east. */ /* Runs the program */ private void returnToStartOfRow() { public void run() { turnAround(); for (int i = 0; i < 4; i++) { moveToWall(); moveUp2Rows(); turnAround(); deliverValentinesToOneRow(); } returnToStartOfRow(); } /* * } Drives Karel along the row, placing beepers whenever * there is a "desk" to the right, signified by a wall. /* * The precondition is that Karel must be facing east Moves to the column, two rows aboveis where * at theKarel beginning ofsame a row. The postcondition that * it currently is. The precondition and postcondition * Karel will be in the same location after having * have Karel facing east. * both delivered all the valentines. */ */ private void void deliverValentinesToOneRow() moveUp2Rows() { private { turnLeft(); while (frontIsClear()) { move(); move(); move(); if (rightIsBlocked()) { turnRight(); putBeeper(); } } } } page 2 of 2 Expression Tracing 1.25 1.25 5.0 / Both of these operands are integers so the result is truncated to an int. 0 4 - 4 / 5 Because the left operand of the && operator is false, Java does not evaluate the right operand, thereby avoiding the division-by-zero error. false false 4 7 < 9 - 5 && 3 % 0 + 8 3 This generates an error because subtraction is undefined for strings. "B84" "B8" "B" == + 4 "E" - "A" Algorithmic Tracing—Practice #1 private String mystery(String s) { String result = ""; int len = s.length(); int j = 0; int k = 9; while (j < k) { if (j < 4) { result += s.charAt(k % len); } if (j / 2 != 1) { result += s.charAt(j % len); } j++; k--; } return result; len j k } 7 0 1 2 3 4 5 9 8 7 6 5 4 result str "cabbage" "cabbag" "cabba" "cabb" "cab" "ca" "c" "" "abcdefg" Algorithmic Tracing—Practice #2 private int mystery(int n) { while (n >= 10) { int k = 0; while (n > 0) { k += n % 10; n /= 10; } n = k; } return n; } k n 11 18 19 10 9 0 1 1729 172 17 19 10 1 0 Method Tracing—Practice #1 public void run() { String String s1 = "To err"; private forgive(String me, String you) { String = "is Strings2 heart = human!"; me.substring(0, you.length() - me.length()); private char understanding(String you, int num) { s1 = forgive(s1, s2); you = "" (char)(you.charAt(0) + you.charAt(me.length()); return + num); println(s1 + " " + s2); } int amount = heart.length(); } me = me.substring(amount + 2) s2 s1 + me.charAt(amount); 'c' heart += understanding(you, 2) + you + me; "is human!" "To "To care" err" return heart; } amount heart me you you num "To err" "is human!" 3 "To "To care" " "re" "a" 2 "a" Problem2c To care is human! Method Tracing—Practice #2 public void run() { String String s1 = "Heart"; private valentine(String s1, String s2) { String s2 valentine("candy", s1); int num == (s1.substring(1, 2)).length(); private String cupid(String s1, char ch) { println("s1 = " + s1); s1return = s2.substring(num); (s1 + Character.toLowerCase(ch)); println("s2 = " + s2); s2.charAt(0)); } s2 = cupid(s1, } return (s2); s2 s1 } "earth" "Heart" s2 num s1 s1 ch 1 "candy" "eart" Problem2c s1 = Heart s2 = earth "Heart"'H' "eart" "earth" Problem 3—Practice #1 In Assignment #2, you wrote a program to find the largest and smallest integers in a list entered by the user. For this problem, write a similar program that instead finds the largest and the second-largest integer. As in the homework problem, you should use 0 as a sentinel to indicate the end of the input list. Thus, a sample run of the program might look like this: FindTwoLargest This program finds the two largest integers in a list. Enter values, one per line, using a 0 to signal the end of the list. ? 17 ? 42 ? 11 ? 19 ? 35 ? 0 The largest value is 42 The second largest value is 35 Finding the Two Largest Values public void run() { println("This program finds the two largest integers in a"); println("list. Enter values, one per line, using a " + SENTINEL + " to"); println("signal the end of the list."); int largest = -1; int secondLargest = -1; This code handles the case when while (true) { the input value is larger than any value yet seen. It then becomes the int input = readInt(" ? "); largest, and the old maximum is if (input == SENTINEL) break; now the second largest. if (input > largest) { secondLargest = largest; It is also necessary to check for the largest = input; case in which the new value is larger than the previous candidate } else if (input > secondLargest) { for second-largest, even if it isn’t secondLargest = input; the largest so far. } } println("The largest value is " + largest); println("The second largest is " + secondLargest); } Problem 3—Practice #2 As you undoubtedly learned in school, the Pythagorean Theorem holds that the length of the hypotenuse (z) of a right triangle with sides x and y is given by the following formula: x2 + y2 = z2 Write a Java program that prints out all Pythagorean triples in which both x and y are less than or equal to a named constant LIMIT and x is less than y For example, if LIMIT is 25, your program should generate the following sample run:: PythagoreanTriples 3, 4, 6 5, 12, 13 6, 8, 10 7, 24, 25 8, 15, 17 9, 12, 15 10, 24, 26 12, 16, 20 15, 20, 25 18, 24, 30 20, 21, 29 Finding Pythagorean Triples import acm.program.*; import acm.graphics.*; public class PythagoreanTriples extends ConsoleProgram { public void run() { for (int a = 1; a <= LIMIT; a++) { for (int b = a; b <= LIMIT; b++) { int csq = a * a + b * b; int c = GMath.round(Math.sqrt(csq)); if (c * c == csq) { println(a + ", " + b + ", " + c); } } } } /* Maximum value for a and b */ private static final int LIMIT = 25; } Problem 4—Practice #1 Write a GraphicsProgram that does the following: 1. Creates the following cross as a rectangles: GCompound containing two filled 2. Adds the cross to the canvas so that it appears at the center of the window. 3. Moves the cross at a speed of 3 pixels every 20 milliseconds in a random direction, which is specified as a random real number between 0 and 360 degrees. 4. Every time you click the mouse inside the cross, its direction changes to some new random direction; its velocity remains the same. Clicks outside the cross have no effect. Red Cross /* * File: RandomlyMovingRedCross.java * --------------------------------* This program solves the practice midterm problem. */ import acm.program.*; import acm.util.*; import java.awt.event.*; public class RandomlyMovingRedCross extends GraphicsProgram { /* Sets up the program at the beginning */ public void init() { cross = new RedCross(); add(cross, getWidth() / 2, getHeight() / 2); chooseRandomDirection(); addMouseListeners(); } page 1 of 4 Red Cross /* Runs the simulation */ /* public void run() { * File: RandomlyMovingRedCross.java while (true) { * --------------------------------cross.movePolar(VELOCITY, direction); * This program solves the practice midterm problem. pause(PAUSE_TIME); */ } } import acm.program.*; import acm.util.*; /* Called when the mouse is clicked */ import java.awt.event.*; public void mouseClicked(MouseEvent e) { publicif class RandomlyMovingRedCrosse.getY())) extends GraphicsProgram { (cross.contains(e.getX(), { chooseRandomDirection(); /* Sets up the program at the beginning */ } public void init() { } cross = new RedCross(); add(cross, getWidth() 2, getHeight() /* Resets the direction to a/random value */ / 2); chooseRandomDirection(); private void chooseRandomDirection() { addMouseListeners(); direction = rgen.nextDouble(0, 360); } } page 2 of 4 Red Cross /* Runs Private theconstants simulation */*/ public void private static run() final { double PAUSE_TIME = 20; private whilestatic (true)final { double VELOCITY = 2; cross.movePolar(VELOCITY, direction); /* Private pause(PAUSE_TIME); instance variables */ private } RedCross cross; } private double direction; private RandomGenerator rgen = RandomGenerator.getInstance(); /* Called when the mouse is clicked */ } public void mouseClicked(MouseEvent e) { if (cross.contains(e.getX(), e.getY())) { chooseRandomDirection(); } } /* Resets the direction to a random value */ private void chooseRandomDirection() { direction = rgen.nextDouble(0, 360); } page 3 of 4 Red Cross /* * File: RedCross.java * ------------------* This class defines a red cross whose size is specified * by the constants CROSSBAR_LENGTH and CROSSBAR_WIDTH. */ import acm.graphics.*; import java.awt.*; public class RedCross extends GCompound { /* Constructs a red cross centered at the origin */ public RedCross() { GRect hCrossbar = new GRect(CROSSBAR_LENGTH, CROSSBAR_WIDTH); GRect vCrossbar = new GRect(CROSSBAR_WIDTH, CROSSBAR_LENGTH); hCrossbar.setFilled(true); vCrossbar.setFilled(true); add(hCrossbar, -CROSSBAR_LENGTH / 2, -CROSSBAR_WIDTH / 2); add(vCrossbar, -CROSSBAR_WIDTH / 2, -CROSSBAR_LENGTH / 2); setColor(Color.RED); } private static final double CROSSBAR_LENGTH = 60; private static final double CROSSBAR_WIDTH = 20; } page 4 of 4 Problem 4—Practice #2 As you may recall, the winner in the aesthetic division of this year’s Karel Contest played the game of Frogger . . . Your first task in this problem is to place the frog at the bottom of the graphics window. The frog itself is the easy part because all you need to do is create a GImage object with the appropriate picture, as follows: GImage frog = new GImage("frog.gif"); The harder part is getting the image in the appropriate place in the bottom of the window. In Frogger, the frog image cannot be just anywhere on the screen but must instead occupy a position in an imaginary grid. . . . The second part of the problem is getting the frog to jump when the user clicks the mouse. The goal is to get the frog to jump one square in the direction that moves it closest to the mouse. . . . Frogger /* * File: SimpleFrogger.java * -----------------------* This program solves the Frogger problem from the practice midterm. */ import import import import acm.graphics.*; acm.program.*; java.awt.*; java.awt.event.*; /* * This program gets a frog to jump one square in the closest * direction to a mouse click. */ public class SimpleFrogger extends GraphicsProgram { public void run() { frog = new GImage("frog.gif"); fx = (NCOLUMNS / 2 + 0.5) * SQUARE_SIZE; fy = (NROWS - 0.5) * SQUARE_SIZE; add(frog, fx - frog.getWidth() / 2, fy - frog.getHeight() / 2); addMouseListeners(); } page 1 of 4 Frogger /* /* Responds to a mouse click */ void mouseClicked(MouseEvent e) { * public File: SimpleFrogger.java double mx = e.getX(); * -----------------------double my = e.getY(); * This program solves the Frogger problem from the practice midterm. */ if (Math.abs(mx - fx) > Math.abs(my - fy)) { if (mx > fx) { import acm.graphics.*; moveFrog(SQUARE_SIZE, 0); import acm.program.*; } else { import java.awt.*; moveFrog(-SQUARE_SIZE, 0); import java.awt.event.*; } } else { /* if (my > fy)a{frog to jump one square in the closest * This program gets * directionmoveFrog(0, to a mouse SQUARE_SIZE); click. */ } else { public classmoveFrog(0, SimpleFrogger extends GraphicsProgram { -SQUARE_SIZE); } public void run() { } } frog = new GImage("frog.gif"); fx = (NCOLUMNS / 2 + 0.5) * SQUARE_SIZE; fy = (NROWS - 0.5) * SQUARE_SIZE; add(frog, fx - frog.getWidth() / 2, fy - frog.getHeight() / 2); addMouseListeners(); } page 2 of 4 Frogger /* Responds Moves theto frog a mouse by dx/dy click as*/ long as it remains inside the world */ public void private voidmouseClicked(MouseEvent moveFrog(double dx, double e) {dy) { double if (insideFroggerWorld(fx mx = e.getX(); + dx, fy + dy)) { double fx += mydx; = e.getY(); if fy (Math.abs(mx += dy; - fx) > Math.abs(my - fy)) { if (mx > fx) {dy); frog.move(dx, } moveFrog(SQUARE_SIZE, 0); } } else { moveFrog(-SQUARE_SIZE, 0); /* Returns } true if the point (x, y) is inside the frog's world */ private } else boolean { insideFroggerWorld(double x, double y) { return if (my (x > >=fy) 0 && { x <= NCOLUMNS * SQUARE_SIZE && moveFrog(0, y >= 0 && SQUARE_SIZE); y <= NROWS * SQUARE_SIZE); } } else { moveFrog(0, -SQUARE_SIZE); } } } page 3 of 4 Frogger /* Moves Private the constants frog by */ dx/dy as long as it remains inside the world */ private static void moveFrog(double final int SQUARE_SIZE dx, double = 75; dy) { private if (insideFroggerWorld(fx static final int NROWS + dx, = 4;fy + dy)) { private fxstatic += dx;final int NCOLUMNS = 7; fy += dy; /* Private frog.move(dx, instance variables dy); */ private } GImage frog; /* The image of the frog */ } private double fx; /* The x-coordinate of the frog's center */ private double fy; /* The y-coordinate of the frog's center */ /* Returns true if the point (x, y) is inside the frog's world */ /* private Sets theboolean graphics insideFroggerWorld(double window size */ x, double y) { public return static (x >= final 0 &&int x <= APPLICATION_WIDTH NCOLUMNS * SQUARE_SIZE = NCOLUMNS && * SQUARE_SIZE; public static y >= final 0 &&int y <= APPLICATION_HEIGHT NROWS * SQUARE_SIZE); = NROWS * SQUARE_SIZE; } } page 4 of 4 Problem 5—Practice #1 Write a method removeDoubledLetters that takes a string as its argument and returns a new string with all doubled letters in the string replaced by a single letter. For example, if you call removeDoubledLetters("tresidder") your method should return the string "tresider". Similarly, if you call removeDoubledLetters("bookkeeper") your method should return "bokeper". Remove Doubled Letters /* * Removes any doubled letters from a string. */ private String removeDoubledLetters(String str) { String result = ""; for (int i = 0; i < str.length(); i++) { char ch = str.charAt(i); if (i == 0 || ch != str.charAt(i - 1)) { result += ch; } } return result; } Problem 5—Practice #2 Write a method removeDoubledLetters that takes a string as its argument and returns a new string with all doubled letters in the string replaced by a single letter. For example, if you call private int countLove(String str) that takes a string as its argument and returns the number of times the word love appears in that string, ignoring differences in case, but making sure that love is not just part of a longer word like clover, glove, pullover, or slovenly. For example, if you were to call countLove("Love in the clover.") your method should return 1. The word Love counts as a match because your method should ignore the fact that Love starts with an uppercase L. The word clover doesn’t match because the letters love are merely part of a larger word. Count Love /* Counts the occurrences of the word "love" in a string */ private int countLove(String str) { String lowerCaseString = str.toLowerCase(); int count = 0; int start = lowerCaseString.indexOf("love"); while (start != -1) { if (isSeparator(lowerCaseString, start - 1) && isSeparator(lowerCaseString, start + 4)) { count++; } start = lowerCaseString.indexOf("love", start + 4); } return count; } /* Checks to see if the ith char of str is a separator */ private boolean isSeparator(String str, int i) { if (i < 0 || i >= str.length()) return true; return !Character.isLetter(str.charAt(i)); } The End