import java.applet.*; import java.awt.*; import java.util.*; // A drill on completing the square public class Complete extends Applet { int bnum, bden; //Numerator and denominator of b in sample problem TextField banswer; TextField canswer; Random r; int numerator, denominator; int rightbnumerator, rightbdenominator; int rightcnumerator, rightcdenominator; int state; String usercomm; private Font f; public void setnumbers(){ // Select the coefficients for a problem. // bnum and bden are the numerator and denominator of the // coefficient of x in the quadratic. We make sure that // neither of them is 0. int a, b, rem; bnum = 0; while(bnum == 0){ bnum = Math.abs(r.nextInt()) % 20 - 10; } bden = 0; while(bden == 0){ bden = Math.abs(r.nextInt()) % 10; } // Find the gcd so we can reduce the fraction to lowest terms. a = Math.abs(bnum); b = Math.abs(bden); rem = a % b; while(rem != 0){ a = b; b = rem; rem = a % b; } bnum = bnum / b; bden = bden / b; // Compute the right answers in lowest terms. rightbnumerator = bnum; rightbdenominator = bden*2; if (bnum % 2 == 0) { rightbnumerator /= 2; rightbdenominator /= 2; } rightcnumerator = rightbnumerator * rightbnumerator; rightcdenominator = rightbdenominator * rightbdenominator; } public void init() { // Set the font and background color for the applet. f = new Font("TimesRoman", Font.PLAIN, 14); setBackground(Color.cyan); // Start up a random number generator. r = new Random(); setnumbers(); // Install the graphical components. banswer = new TextField(20); canswer = new TextField(20); add(banswer); add(canswer); // Set the state and the first message to the user. state = 1; usercomm = "Enter the value for the first field."; // Set cursor on the first answer field. banswer.requestFocus(); } public void paint(Graphics g){ // We have to locate the exponents and text fields correctly. String part1 = "x"; String part2; g.setFont( f ); g.drawString(part1, 10, 28); FontMetrics fm = g.getFontMetrics(); int newPosition = fm.stringWidth(part1) + 10; g.drawString("2", newPosition, 20); newPosition += fm.stringWidth("2"); if(bnum > 0 && bden != 1){ part2 = " + " + bnum + "/" + bden + " x = ( x + "; } else if(bnum < 0 && bden != 1){ part2 = " - " + Math.abs(bnum) + "/" + bden + " x = ( x + "; } else if(bnum > 0 && bden == 1){ part2 = " + " + bnum + " x = ( x + "; } else { part2 = " - " + Math.abs(bnum) + " x = ( x + "; } g.drawString(part2, newPosition, 28); newPosition += fm.stringWidth(part2); banswer.reshape(newPosition, 12, 40 ,26); newPosition += 40 + 4; String part3 = ")"; g.drawString(part3, newPosition, 28) ; newPosition += fm.stringWidth(part3); g.drawString("2", newPosition, 20); newPosition += fm.stringWidth("2"); String part4 = " - "; g.drawString(part4, newPosition, 28); newPosition += fm.stringWidth(part4); canswer.reshape(newPosition, 12 ,60, 26); g.drawString(usercomm, 10, 58); } int intParse(String s){ // If s represents an integer, return the integer; otherwise, throw an exception. Integer val; // Try to catch some funny inputs. s = s.trim(); if(s.indexOf('+') == 0) s = s.substring(1, s.length()); if(s.equals("-")) throw new NumberFormatException(); // The Integer(String) method tries to convert the String // object to an integer. If the String object doesn't // represent an integer, it throws an exception, which we // throw on to our caller. try{ val = new Integer(s); } catch(NumberFormatException nef){ throw nef; } // If all went well, our Integer wrapper object has an int value. return val.intValue(); } void getRationalFrom( String s){ // If s represents a rational number, break out the numerator and denominator int where; s = s.trim(); if((where = s.indexOf('/')) < 0){ denominator = 1; try{ numerator = intParse(s); } catch(NumberFormatException nef){ throw nef; } } else{ try{ numerator = intParse(s.substring(0,where)); denominator = intParse(s.substring(where + 1, s.length())); } catch(NumberFormatException nef){ throw nef; } } } // State descriptions // In state 1, we have just posed a problem, and we are waiting // for input in the a field. If that input produces a number // format exception, we stay in state 1. Otherwise we go to state 2. // // In state 2, we give the student the good or bad news on the first // field, and then wait for input in the second field. On valid // (but not necessarily correct) input, we move to state 3. // // In state 3, we give the news on the second field and wait for a // mouseup, whereupon we pose a new problem and move to state 1. // public boolean action(Event e, Object o){ if( (e.target == banswer) && (state == 1 )){ try{ getRationalFrom(e.arg.toString()); } catch(NumberFormatException nef){ usercomm = "Your answer isn't correctly typed. Enter the first field again."; repaint(); return(true); } analyzeFirst(); canswer.requestFocus(); repaint(); state = 2; return(true); } else if((e.target == canswer) && (state == 1)){ usercomm = "You really need to do the first field before the second one." ; banswer.requestFocus(); repaint(); } else if((e.target == canswer) && (state == 2)){ try { getRationalFrom(e.arg.toString()); } catch(NumberFormatException nef){ usercomm = "Your answer isn't correctly typed. Enter the first field again."; repaint(); return(true); } analyzeSecond(); state = 3; repaint(); return(true); } return(false); } public boolean mouseUp(Event e, int x, int y){ if(state == 3){ setnumbers(); state = 1; usercomm = "Enter the value for the first field."; banswer.setText(""); canswer.setText(""); banswer.requestFocus(); repaint(); } return true; } void analyzeFirst(){ String mstail; mstail = ". Enter the second field."; if(bnum * denominator == bden * 2 * numerator){ usercomm = "That's right. " + mstail; } else if(bnum * denominator == - bden * 2 * numerator){ usercomm = "The sign is wrong in " + numerator + "/" + denominator + mstail; banswer.setText("" + rightbnumerator + "/" + rightbdenominator); } else if(bnum * denominator == bden * numerator){ usercomm = "You forgot to divide by 2 in " + numerator + "/" + denominator + mstail; banswer.setText("" + rightbnumerator + "/" + rightbdenominator); } else if(2 * bnum * denominator == bden * numerator){ usercomm = "You multiplied by 2 instead of dividing in " + numerator + "/" + denominator + mstail; banswer.setText("" + rightbnumerator + "/" + rightbdenominator); } else if(bnum * denominator == -bden * numerator){ usercomm = "Correct sign and divide by 2 in " + numerator + "/" + denominator + mstail; banswer.setText("" + rightbnumerator + "/" + rightbdenominator); } else if(2 * bnum * denominator == - bden * numerator){ usercomm = "Correct sign and divide by 2 instead of multiplying in " + numerator + "/" + denominator + mstail; banswer.setText("" + rightbnumerator + "/" + rightbdenominator); } else{ usercomm = "I don't know how you got " + numerator + "/" + denominator + mstail; banswer.setText("" + rightbnumerator + "/" + rightbdenominator); } } void analyzeSecond(){ String mouseit; mouseit = "Click mouse for next problem."; if( rightcnumerator * denominator == rightcdenominator * numerator){ usercomm = "That's right. " + mouseit; } else if(numerator < 0 && denominator > 0){ usercomm = "You don't need a minus sign. " + mouseit; canswer.setText("" + rightcnumerator + "/" + rightcdenominator); } else if(rightcnumerator * denominator * 2 == rightcdenominator * numerator){ usercomm = "You got " + numerator + "/" + denominator + " which is b times b over 2 instead of b times b over 4. " + mouseit; canswer.setText("" + rightcnumerator + "/" + rightcdenominator); } else if(rightcnumerator * denominator * 4== rightcdenominator * numerator){ usercomm = "You got " + numerator + "/" + denominator + ". You forgot to square the 2 in b/2. " + mouseit; canswer.setText("" + rightcnumerator + "/" + rightcdenominator); } else{ usercomm = "I don't know how you got " + numerator + "/" + denominator + ". " + mouseit; canswer.setText("" + rightcnumerator + "/" + rightcdenominator); } } }