You got here by working your way through building a calculator in the GameEngine, and maybe getting it to (sort of) work. Or not. Now let's make it better. What sorts of things need fixing?
0. Some (or all) buttons do nothing.If you haven't been writing any code, then of course you have nothing to fix or improve. Or you might be dissatisfied with what you have. In either case, you can go back (start over) here.0a. Breakpoints show the events are calculating, but the numbers don't show.
1. It doesn't do anything with the decimal point.
1a. The decimal point works fine, but some fractional results look weird.
2. It doesn't do anything with the Clear button.
3. It should accept 'number + number', but it ignores the first number.
4. It would be nice to see visually what function is pending.
5. Can your calculator accept keystrokes from the physical keyboard?
6. Call for a Mentor to work with you:
-- or use the "Ask" feature in Zoom.
7. Look at my calculator program for comparison8. Try some other program...
If you get the breakpoints, but the numbers you get from the GetInfo method are zero or something else, we can work on that. First try a digit button, say your number 3 button. Did you get a 3 from GetInfo? If so, it is working correctly. Did you get 51? That means you gave GameMaker a quoted '3' for the information field. Quit your program and go back to GameMaker and enter the correct numbers with no apostrophes. Then Build and try again.
What about the function buttons? Did you get 43 from the Plus button? That's normal, 43 is the ASCII code for the Plus symbol. When you cast it to char, the character value will be a '+'. Google "ASCII character chart" (or look at my ASCII Table in the "Need to Know" page) to see the numeric values of all the characters. Step through the ClickEvt method in the debugger to see what it is doing. Is each step what you expected on that line? If not, that is your problem.
Basically, the number that is showing in the "I=" field of a
particular button in GameMaker should be the number you are testing for
in your ClickEvt method. When the IF-test value matches
the value you got from GetInfo, then that command will do whatever
you tell it to do.
What do you think should happen when the user clicks the decimal point? What happens in the 4-function calculator you can buy at Walmart or BestBuy? The dot goes into the number on the display, same as the digits do. Can you make that happen in your program? If you are having trouble thinking about it, perhaps you can get some hints from one of the other students or a Mentor. In the last resort somebody can tell you what to do, but if you want to be a programmer out in the real world, you can't be doing that. Try puzzling it out yourself first. Hint: You will need an IF connected to the other IFs with an else.
Remember, the decimal point is part of the number, not a function operator, so it needs to be handled in the same place the digits are. Once you have the decimal point in the input string, the number conversion will do the right thing with it. It will work.
Still stuck?
Let's assume you now know that your decimal point button is getting its clicks in ClickEvt. Now you should ask yourself, what do you want to do with those clicks? Right now you have no code to respond to it, what do you think you need to add? We are depending on Double.parseDouble to convert from our keyed-in string of digits as a text string, into a (double) floating point number that you can do math on. However, right now the only thing in that string is a sequence of digits, no decimal point. What do you think you need to do to fix that?
Notice that the code we have for building that string of digits concatenates them one digit at a time by (automatic) integer-to-String conversion. That won't work for the decimal point, because it's a chararacter, not an (integer) numeral. But the first thing we did in this subroutine is to convert the operators to character (char) type in variable btnchr. Do you remember that? You can use it here, Java will concatenate characters just fine.
Suppose the user clicks in 1, 2, '.', 3, 4. The digits came in in order with the decimal point between the 2 and the 3, but it got ignored, so all you saw is "1234". If you handled the decimal point when it came in, what would you do with it? It's not a numeral, so you can't just include it somehow in your existing code, you need to add a new line or two to handle it. What do you think that should be? Put it in, then see if it works.
Still stuck? That's what the Mentor is here for.
By the way, Mentors make mistakes too, cut us some slack if we get it wrong.
That's what the Delete key is for
It's a Math thing, people like you and me, we think in decimal, but the computer thinks in binary. The original computers were also decimal, but the engineers figured that doing the math in binary was faster and used less hardware, and they dould do the conversion at the beginning and end, and it would be good enough. Except it wasn't, people got wrong answers like you saw. So the IEEE set up a standard for binary arithmetic (I was on the committee), and now everybody does the internal calculations correctly, but the standard doesn't say anything about conversion, so some people still get that one wrong.
Like I said, it's a math thing. when you divide 10/3 in decimal, you get an unending sequence of digits 3.3333..., but if you divide it by 2 or 5, then it comes out even. That's because 2 and 5 multiplied together is a multiple of ten (ten even, same thing). In binary the divisor must exactly divide a power of two for that to work, and ten doesn't.
2/10 = 0.0011001100110011... in binaryAnyway, so 1/10 = 0.1 (in decimal) = 0.00011001100110011... in binary, and it comes out 0.09999999.. when they convert it to decimal, but they need to notice that and round it correctly, which they didn't in this case. You can fix it yourself, but it's tricky. Perhaps another day
1. The user has been entering digits, and the aWord string is not empty. If that is the case, measure how long the string is, then take a substring exactly one character less.Try it. Remember, this is your program, you get to write the code.Let's think a little about string length. Recall from your English that a string (variable or constant of type String in Java) is a sequence of characters, kind of like an array, but you can't index the characters directly. Instead you use system subroutines to do that. Java has a whole bunch of useful methods in class String that you should eventually become familiar with, and I have corresponding "safe" subroutines to do the same thing without throwing unnecessary exceptions (see "String Tools" in the "Need to Know" page).
Anyway the two you need to know about today are string length (see my StrLength in "String Tools" in the "Need to Know" page), which returns the number of characters in the string, like if the user clicked in 5 digits and a decimal point, you see six characters in the string, and substring (see my Substring in "String Tools" in the "Need to Know" page), which is a little more complicated. Let's say the user entered "123.45". Or rather let's do a little test program like this:
String word = "123.45";In the case of fraction, you can think of it as "skip over four characters (the '123.') then take the next two." The next line skips over no characters, and takes the length less 1, that is, all but the last digit.
int lxx = JavaGame.StrLength(word); // =6
String fraction = JavaGame.Substring(4,2,word); // ="45"
String allbutlast = JavaGame.Substring(0,lxx-1,word);If the length is only one digit to start with, then clear it to empty (""). The display code you already have should handle it fine.
2. The user has not yet entered any digits after the function, or else has not yet even entered a new function. The aWord string is empty in both cases, so that is how you tell this case from #1; just set the res value to 0.0 and (again) the display code you already have will work fine. You might also want to set the operator to '+' like at ther beginning.
The second use case is where the user has completed the previous calculation with '=', and now wants to start over. Formally they should press Clear, then proceed as if they had just started (with res=0), but you can offer them a shortcut: just type the initial value of the next calculation and your calculator will do the Right Thing.
Me, I was thinking like our previous text-based calculator, that every input must have an operrator, even the first, so I was going to insert an implied Plus if no function was given, or rather initialize the operator to '+'. I like your solution better, because mine does The Wrong Thing after an equal.
See? You can do this, but you do need to think about it. IBM's corporate
motto for many years was "THINK". That's what programmers
have always needed to do.
You can give your function buttons a (slightly) animated appearance of staying pressed by changing the color slightly when clicked, then back again when you finish the operation being saved. Darker looks more pushed, and the ClickEvt parameter whom gives you a reference to the rectangle widget being clicked, and there's a SetColor method you can use to change its color. You will need another persistent instance variable -- I called mine FnPressed -- declared type GameWgt at the top with the other three persistent variables and initialized = null (shown in blue here):
/// (..$) End generated class variables ($) (do not modify this line)char optor = ' '; // added instance variables..
double res = 0.0;
String aWord = "";
GameWgt FnPressed = null;public String toString() {return "(CalcGE)";} //~toString
When you get a function key click (not equal, but that test is already
there) you save not only the key code in optor, but also the reference
whom in FnPressed, and change the color of that widget. Then when
you actually do that function, you lighten the (saved) rectangle's color
and reset FnPressed back to null.
} // end of doing pending op
if (FnPressed != null) {
FnPressed.SetColor(0x666666);
FnPressed = null;}
if (btnchr != '=') {
FnPressed = whom;
if (whom != null) whom.SetColor(0x333333);
optor = btnchr;}
else optor = ' '; // already did it
Does that make sense? Put it in and see if it works, then convince
yourself that you know why it works.
OK, what happens if the user clicks minus then changes their mind and
clicks the Clear button to start a new calculation instead? The minus key
is still operative and button remains highlighted, even after the result
on the display is cleared (try it). What can your program do to prevent
that? I think you can figure it out.
Call a Mentor, or...
<<Previous | ToC | Next >>
Revised: 2023 March 1