In this workshop we will make an interactive Abacus:
Download and extract the archive file Workshop3.zip., and put your solutions to Tasks 1-10 inside it.
1.1).Inside the Task1 folder, create a new java file called AbacusModel.java. In this file, make the empty class of this name, and make an empty contructor.
1.2) Add the following instance variables as follows:
1.3) Give the contructor have two integer parameters, num_pegs and num_counters, and inside the constructor method, add the following lines:
max_num_counters = num_counters;
num_of_pegs = num_pegs;
peg_array = new int[num_of_pegs]
Your class should compile ok now. If we were to make this object, using these numbers in the constructor:
AbacusModel myAbacus = new AbacusModel(7, 9);
the object myAbacus would contain an array that is 7 elements long - we can store 7 numbers in it, going from the element peg_array up to (and including) the element peg_array.
The max_num_counters variable is used to control the maximum number that can be stored in each of these elements. Obviously, we can make arrays of other sizes by setting the variable num_of_pegs to have other values. In this case, we care indicating that the maximum number to be stored in each element of the array is '9'.
In this program, we can think of peg_array storing the number of counters that are present in each of the pegs of the abacus. So, for example, if peg_array stored the value 5, then the second peg has five counters (remember! the first peg is peg_array).
Now we'll include methods to add and remove 1 counter from any one of the pegs (i.e. the elements in the array)
boolean addCounter(int thisPeg)
boolean removeCounter (int thisPeg)
Each of these methods needs an implementation. The parameter thisPeg is an integer that can refer to any of the pegs in the abacus. In these implementation, you will need to refer to the requested element of the array as peg_array[thisPeg]. Hint: use ++ to add 1.
Why have we made our method a boolean return value? So that we can report any problems we had, by returning false.to the method that called this method. (Returning a value of true means that there were no problems.) There are three types of problems we could have:
In your implementation of this method, add checks for the above three types of problems. If any check fails, then don't change the abacus, and return false.
Now add a method that retreives how many counters are stored at any one particular column:
int getNumCounters(int thisPeg)
This method should return the number of counters stored in the element of the array, indexed by the variable thisPeg. Your method should first test that thisPeg is a valid index (not negative, or too big for the array). If thisPeg is invalid, then just return 0.
You can test your class by using the test program contained in the Task4 folder. Copy your AbacusModel.java file into the folder called YourSolutionHere. Double-click the file called runme, and this program will run tests on your solution, giving you a mark out of 20. Good Luck! Here are a couple of common problems, with their solutions:
You'll be using your solution to this class in the subsequent Tasks.
Now we work on another class, called AbacusPanel, that will display (and control) the data stored in the AbacusModel class. The starting version is in the Task5 folder, along with the AbacusFrame class. These two classes are similar to the Workshop 2 work, although no counter positions are stored (that is now the job of the AbacusModel).
Copy your AbacusModel class from the Task4 folder into the Task5 folder.
Add a member 'instance variable' to the AbacusPanel class, which is a reference to a AbacusModel object:
In the constructor for AbacusPanel, assign the variable myAbacus to a new AbacusModelobject. We pass in two numbers to the AbacusModel constructor: the numCols (which will set the number of pegs) and numRows (which will set the maximum number of counters per peg).
myAbacus = new AbacusModel(numCols,numRows);
Your code should now compile, although it won't yet do anything different.
Copy three .java files in Task5 folder, into Task6. In the mouseClicked method of the AbacusPanel class, do the following. Find out which column the user clicked in (you should have this already). If it is a left-button click, call the addCounter method (of the myAbacus object). If it is a right button click, call the removeCounter method (of the myAbacus object). In both cases, include as a method parameter, the variable which stores which column the user clicked in. Finally, make sure you have called repaint() - because the state of the program has changed and so the display needs to be refreshed.
Unfortunatwly, we have to wait until Task7 for the code that draws the counters. So, for the moment, still in the mouseClicked method, use a System.out.println statement to print out how many counters are contained in the peg which has just been changed. This is a simple way of testing that the program works as expected so far.
Copy three .java files in Task6 folder, into Task7. In the paint method of the AbacusPanel class, after the grid has been drawn, we write the new code to draw the right number of counters for each column. All of the new code will take place inside a loop over the columns:
for(thisCol= 0; thisCol < numCols; thisCol++)
// new code to paint the counters will go here
Inside this loop, at each column, you must find out the number of counters to draw (use the getNumCounters method of the myAbacus object). To draw these counters, you must use another loop (an 'inner loop') that will loop over this number of counters, and draw them, one per row, in this column.
If you start drawing your counters at row 0, then they will start from the top. To draw them from the bottom, you can start at numRows-1 and work backwards. There are a couple of ways your code can be arranged to do this.
So, this shows a model class (AbacusModel) linked up to a view class (AbacusPanel) with basic functionality. The next few tasks suggest some modifications to the 'look and feel' of the application.
Make the first three pegs a different colour to the rest of the pegs.
Make the pegs horizontal, rather than vertical. You don't need to change the model class.
Rather than have the counters appearing and disappearing, put the currently unused counters on the other side of the screen. A left-click moves the counter to the left, and a right-click moves the counter to the right.
A++ Solution for workshop 3