| Eighth Assignment: Magic Squares CIT 591, David Matuszek, Fall 2001 |
Purposes of this assignment:
What a magic square is:
A magic square is an array of numbers from 1 to N squared, such that the sum of the numbers in each row, each column, and each of the two diagonals is the same. For example, here is a 3x3 magic square:
|
Rows: |
Columns: 8 + 3 + 4 = 15 1 + 5 + 9 = 15 6 + 7 + 2 = 15 |
Diagonals: 8 + 5 + 2 = 15 4 + 5 + 6 = 15 |
How to create a magic square:
There is a simple algorithm for creating an odd-order magic square (a magic square with an odd number of rows and columns).
| Start by putting the number 1 in the center of the top row: |
|
|||||||||||||||||||||||||
|
Count upward and to the right. If you go off the top, drop down to the bottom. (That is, if the row number becomes negative, reset it to the array length minus one.) | |||||||||||||||||||||||||
Continue counting upward and to the right. If you go off the right, come
back in on the left. (Hint: use the modulo operator, %.) |
|
|||||||||||||||||||||||||
|
Continue counting upward and to the right. If you reach a square that is already occupied, go directly under the previous number. | |||||||||||||||||||||||||
| Continue in this manner as long as possible. |
|
|||||||||||||||||||||||||
|
When you go off the top right corner, the same rules apply; the next square is already occupied (by 11), so drop directly below the 15. Then continue. This technique works for any odd square. |
|
If you are having trouble understanding how the "wrapping around" works in the above algorithm, it may help to think of the array as being surrounded by identical ghost copies of itself. As you move up and to the right, if you go off the edge of the array, go ahead and put the next number into the surrounding array, and that will show you where the number belongs in the original, "real" array. For example, going diagonally upward from the initial This is only an aid for understanding; you should not use nine arrays in your program. |
|
Your assignment:
Write a program that creates and displays magic squares. Here are the specific requirements:
|
|
The result should look very much like this:
|
Suggestions:
I did several versions of this program before I found an organization that worked well. If you would like to use the same organization, here it is. I used the following three classes:
public class MagicSquareMaker public static void main(String args[])
method, and nothing else. The only thing the main method does
is create an instance of the Gui. (I did it this way because
it's a nuisance trying to do anything inside a static method.)public class Gui extends Framenew MagicSquare, displays the magic square, and adds a listener
to handle window closing events.public class MagicSquareThat is,
public class MagicSquareMaker {
public static void main(String args[]) {
Gui gui = new Gui(5);
}
}
public class Gui extends Frame {
public Gui(int sizeOfMagicSquare) {...} // constructor
class WindowCloser extends WindowAdapter {...}
}
public class MagicSquare {
public MagicSquare(int size) {...} // constructor
public void fillPanel(Panel panel) {...}
}
In this organization, the "Controller" and "View" are merged into the single
class Gui, while the MagicSquare represents the "Model."
This separation is not perfect, however, because some class has to take the
responsibility of creating a Panel full of Labels
from the information in the MagicSquare class. I decided to do
this in the MagicSquare class, because it seemed better to use
a Panel (which is a GUI thing) in the MagicSquare
class than to give the Gui class access to all the numbers inside
the magic square.
Another way to do this would have been to have a separate View
class, and to write a method public int[][] getArray() in
the MagicSquare class; the View class would use this
to get the numbers it needs.
Necessary information:
A Frame, like an Applet, is a Container.
Applets are usually embedded in web pages, while frames are usually used in
applications (stand-alone programs). The most important differences between
a Frame and an Applet are:
Applet is FlowLayout;
the default layout manager for a Frame is BorderLayout.Applet is automatically visible, but you have to tell a
Frame to make itself visible--send it the message setVisible(true).Applet is given by the HTML page. The size of
a Frame is very small unless you tell it to setSize(width, height),
where width and height are given in pixels.
(200, 200) is a reasonable size to start with.For an application, in order to respond to a WindowClosing event,
you need a WindowListener to the Frame:
addWindowListener(new MyWindowCloser());
The actual listener (best implemented as a member class) looks like this:
class MyWindowCloser extends WindowAdapter {
public void windowClosing(WindowEvent e) {
dispose();
System.exit(0);
}
}
Usually, when you create a GUI, you don't keep changing the layout managers or the components. If you do, you have to do a little extra work.
removeAll()Container, will remove all the Components
in that Container. Use this to remove the old Labels
from your magic square, before changing the layout manager and putting in
the new Labels.validate()Container, will tell Java that you
have changed the contents of that Container, and Java needs to
redraw it for you.Due date:
This program is due by midnight on Wednesday, November 14. Please turn in a complete BlueJ package via Blackboard.
Late penalties of 5 points per day will apply. No programs will be accepted after Wednesday, November 21.