CS 124, Spring 2014
Lab 7: Arrays and Objects and Events, Oh My!
There is not a large amount of programming for this lab, but it will require you to work with several new concepts. We are about to move on to object-oriented programming and all the things that go along with it, including arrays and events in GUI programming. This lab introduces arrays, objects, and events in basic form.
You should create a lab6 project. (You will probably want to do this in Eclipse, but you can go back to the Terminal and gedit if you prefer that environment.) You should copy the three files from /classes/cs124/lab7-files into your project: MathQuiz.java, Grid.java, and TextIO.java.
Your work from this lab is due at the beginning of the next lab. Because of Spring Break, that will be on March 25. Note that the first part of the lab should be turned in on paper. For the programming part of the lab, you can copy your entire lab7 Eclipse project into your the homework folder in /classes/cs124/homework. However, I will be happier if you create a new lab7 folder in your homework directory and copy the only .java files from your project into that directory.
Part 1: Program Ideas
In addition to the programming for this lab, there is a written assignment to hand it. You can type or write the assignment. Bring a hard copy, on paper, with you to lab or turn it in in class on Monday or Wednesday.
The assignment is to write about two programs that you might be interested in creating. In each case, you should describe the purpose of the program. What does it do, or what can the user do with it? The first program should be one that you think you should be able to write after taking this course. The second can be more ambitious; it can be a program that you have no idea how to implement. You do not necessarily have to come up with original ideas. You can write about implementing some program that you are familiar with. Or you might know of some problem -- maybe in another class -- that could be solved with a computer program. Or maybe you have a completely original idea for a project.
You are not being asked to design the programs or the algorithms that they would use. But you should say a little about what you think would be involved in programming it, or what you would have to learn in order to write the program. The entire write-up should be about a page, covering both programs.
Part 2: Math Quiz Redux
The first program that you will work on is a reworking of the arithmetic quiz from Lab 3. In this case, however, the program will ask all the quiz questions without telling the user the correct answer or whether the user's answer is correct. At the end, the program will tell the user which problems they got wrong and what their score is. (In this version, you won't give the user a second chance to answer a question.)
To make this possible, you need to save the problems, the correct answers, and the user's answers in variables. With 10 questions, it would be very inconvenient to use a separate variable for every bit of data. The solution is to use arrays. An array is a data structure that contains a numbered list of items. An array is similar to a String, which is a numbered list of characters, but arrays can hold all types of data and, furthermore, the values in an array can be changed. Nevertheless, you will find that working with arrays is similar to working with strings; hopefully, you will be able to adjust quickly!
Open the file MathQuiz.java. A lot of the program is already implemented. There is an array of Strings named questions that holds the problems. There is an array of ints named correctAnswers that holds the correct answers to the problems. And there is a second array of ints named userAnswers that will be used to store the user's answers to each problem.
The questions and correct answers are already created by the subroutine named createQuiz(). You need to write the inside of the subroutine administerQuiz(), which will present each question to the user and get the user's response. And you need to write the inside of reportResults(), which will tell the user the results of the quiz. You will work only on the two subroutines administerQuiz and reportResults.
Here is a transcript of a sample run of my program. I tried to make it compact. The first half comes from the administerQuiz() subroutine. The second half comes from the reportResults() subroutine. You are not required to follow this format.
Question Number 1: What is 23 + 23 ? 46 Question Number 2: What is 92 + 40 ? 132 Question Number 3: What is 61 + 32 ? 93 Question Number 4: What is 67 - 21 ? 46 Question Number 5: What is 4 + 23 ? 27 Question Number 6: What is 28 + 9 ? 35 Question Number 7: What is 83 - 6 ? 77 Question Number 8: What is 28 + 40 ? 58 Question Number 9: What is 74 - 20 ? 54 Question Number 10: What is 34 - 2 ? 32 Question Correct Ans. Your Answer Points ------------------ ------------ ----------- ------ What is 23 + 23 ? 46 46 10 What is 92 + 40 ? 132 132 10 What is 61 + 32 ? 93 93 10 What is 67 - 21 ? 46 46 10 What is 4 + 23 ? 27 27 10 What is 28 + 9 ? 37 35 0 What is 83 - 6 ? 77 77 10 What is 28 + 40 ? 68 58 0 What is 74 - 20 ? 54 54 10 What is 34 - 2 ? 32 32 10 Your score on the quiz is 80
Here is what you need to know about arrays: Consider the questions array. It is actually a list of 10 variables of type String: questions[0], questions[1], ..., questions[9]. Note the use of square brackets! You can assign values to these variables, use them in expressions, and print them out just like regular String variables. The main power of arrays comes from the fact that the value in brackets doesn't have to be a constant; it can be an expression. For example, if you say questions[i], the value of i determines which variable you are talking about. This is like using str.charAt(i) to refer to one of the characters in a string. Compare a loop that prints out all the characters in a string to a loop that prints out all the questions in the array:
for ( i = 0; i < str.length(); i++ ) { System.out.println( str.charAt(i) ); } for ( i = 0; i < 10; i++ ) { System.out.println( questions[i] ); }
Of course, one big difference is that you can also assign a value to one of the variables in an array, as in this statement (which you will not see in the program):
questions[i] = "What is the meaning of life, the universe, and everything?";
When you write the administerQuiz and reportResults subroutines, you will use loops and you will work with variables like questions[i] and userAnswers[i].
Part 3: Creative Grid
In the MathQuiz program, you used a one-dimensional array, which is simply a sequence of variables. In the next program, you will use a two-dimensional array, which is a grid of variables arranged into rows and columns. You will work with a two-dimensional array of Color variables named gridColor. This array holds the colors of a grid of colored squares on the screen. That is, gridColor[r][c] holds the color of the square in row r and in column c in the grid. (Rows are numbered from the top down, starting with 0, and columns are numbered from left to right, starting with 0.) You will see statements that use the array such as
g.setColor( gridColor[row][col] );
and statements that store values into the array, such as
gridColor[row][col] = new Color( (int)(225*Math.random()), (int)(225*Math.random()),(int)(225*Math.random()) );
Open the file Grid.java. You should run the program to see the grid of squares. Initially, all of the squares are white. When you click a square with the mouse, it will be given a new, random color.
Your assignment is to modify Grid.java to make it do something more interesting. You can do one of the following, or you can do something similar as long as you get my approval first:
- Make the grid into a checkerboard, with alternating colors. Allow the user to place different colored checkers in the grid. You will not implement a checkers game! Just let the user create a picture of a checkerboard. There are examples of making checkerboard patterns in the exercises to Chapter 3.
- Let the user design a Sudoku puzzle grid by placing numbers into the squares. You will want to draw thicker lines between some of the squares. Again, you are not being asked to implement a solution of the puzzle!
- Let the user design a crossword puzzle grid by making some of the squares black and by adding small numbers in the corners of some squares. (You might also let them add letters to the squares.)
In all cases, you will have to add at least one additional two-dimensional array to the program. For example, to implement the Sudoku or crossword puzzle, you will need an array of ints or Strings to hold the values that appear in the squares. For checkers, you might use an array of ints where you code the content of a square using, for example, 0 for empty, 1 for red checker, 2 for black checker, and maybe 4 and 5 for kings. You will need to declare the array variable in the same way that gridColor is already declared on line 30, just after main(). For example:
private int[][] squareData;
Also, you will have to initialize the array variable by creating the actual array. As you have presumably noticed, objects are created using the new operator. Arrays are special kinds of objects and are created using a special version of new. The gridColor array is created at the beginning of the "constructor" named Grid with the line
gridColor = new Color[rows][columns];
and you should do pretty much the same thing for your array (replacing Color with int or String, of course).
You will probably also have to change the size of the grid. You can do that by changing the numbers in line 20 in main():
Grid content = new Grid(20,20,30);
The first two parameters give the number of rows and the number of columns in the grid. The third parameter gives the size of each of the little squares, in pixels.
Aside from declaring and initializing the array, there are only two places where you should need to work: In the paintComponent method and in the mousePressed method. You have already seen that paintComponent is the method that draws the content of the window. In this case, it draws the colored squares and the lines between them. Note that the squares are drawn using nested for loops to go through all the rows and all the columns. (It does some fancy calculations to get the square sizes and positions just right, even when it's not assumed that the size of the window is known.) You need to add code to the paintComponent method to draw the extra content that you are adding to some of the squares.
The mousePressed method is something new. GUI programming uses events. An event is generated by something happening outside the control of the program, such as a timer going off or the user presses a key on the keyboard. In this program, we are using mouse events that are generated when the user clicks on the content of the window. When an event occurs, the system can respond by calling a method in the program. The program must designate a method to receive the event. This is called "registering a listener" for the event. This is already set up in the program: When the user clicks, the system calls the mousePressed method. The parameter, evt, in mousePressed contains information from the system about the event. For example, evt.getX() and evt.getY() return the coordinates of the pixel where the user clicked the mouse. You might find evt.isShiftDown() useful—this boolean-valued method returns true if the user was holding down the shift key when the mouse button was pressed. You could use it to test which of two possible actions to take when the user clicks the mouse. (It is also possible to find out which mouse button was pressed; if you want to do that, let me know.)
You might need to get some input from the user, such as the text that the user wants to place in a square. In a GUI program, you can't use TextIO to get input from the user, since you can't expect the user to be using a Terminal. Instead, you can use the oddly named function JOptionPane.showInputDialog to put up a dialog box where the user can answer a question. Here is an example:
String answer; answer = JOptionPane.showInputDialog(this, "What is your number?");
Use this as the first parameter; this will be explained later. The second parameter is the question or prompt for the user. The return value is the user's response. The user has the option of canceling the dialog box instead of entering a response; in that case, the return value will be the special value null (which will also be explained later). You can test for a null value like this:
String answer; answer = JOptionPane.showInputDialog(this, "What is your number?"); if (answer == null) { ... // The user canceled, so don't do anything! } else { ... // The user provided an answer; do something with it! }
You will notice that null and this are used at several other points in the program. You might also want to display a message to the user without getting back an answer. For that, you can use JOptionPane.showMessageDialog. For example:
JOptionPane.showMessageDialog(this, "Sorry, that's not a legal value!");
One final lesson for today in object-oriented programming: A "constructor" is a special subroutine whose purpose is to initialize an object when one is created with the new operator. You can recognize a constructor because it has no return type and its name is the same as the name of the class. Here is the constructor from Grid.java:
public Grid(int rows, int columns, int preferredSquareSize) { gridColor = new Color[rows][columns]; // Create array to store square colors. gridRows = rows; gridCols = columns; lineColor = Color.BLACK; setPreferredSize( new Dimension(preferredSquareSize*columns, preferredSquareSize*rows) ); setBackground(Color.WHITE); // Set the background color for this panel. addMouseListener(this); // Mouse actions will call methods in this object. }
The constructor is where you will initialize your array variable. You might need to do some other work in the constructor, such as putting the colors for a checkerboard into the gridColor array.