CIT 590 Assignment 10: Magic Squares
Spring 2013, David Matuszek

Purposes of this assignment

Since I want everyone to have some experience coding a GUI, this is an individual assignment. You will not have a partner.

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:

8 1 6
3 5 7
4 9 2

Rows:
8 + 1 + 6 = 15
3 + 5 + 7 = 15
4 + 9 + 2 = 15

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:
    1    
         
         
         
         
    1    
         
         
        3
      2  
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, %.)
    1    
  5      
4        
        3
      2  
    1    
  5      
4 6      
        3
      2  
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.
    1 8 15
  5 7 14  
4 6 13    
10 12     3
11     2 9
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9

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 1, look where the 2 ends up in an adjacent array; this is where it should be in the original array (because it is identical to the "ghost" array).

This is only an aid for understanding; you should not use nine arrays in your program.

17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9

Your assignment

  Write a program that creates and displays magic squares. Here are the specific requirements:

  • Name your project MagicSquares, your package magic, and your main class MagicSquareMaker.
  • Use a BorderLayout, and put:
    • Your name in the NORTH.
    • The magic square in a panel in the CENTER.
    • A panel containing two buttons in the SOUTH .
  • For the magic square,
    • Use a GridLayout with N rows and N columns.
    • Create and install a Label for each number in the magic square.
  • Put these two buttons in the panel in the SOUTH:
    • Smaller: When clicked, creates and displays a new magic square with two fewer rows and two fewer columns. Disabled if an only if the displayed magic square is 1x1.
    • Larger: When clicked, creates and displays a new magic square with two more rows and two more columns. Always enabled.
  • Attach a WindowListener that will close the window and quit the program when the close box is clicked.

The result should look something like this:

Use the following classes:

public class MagicSquareMaker extends JFrame
Contains the public static void main(String args[]) method, which creates an instance of MagicSquareMaker and calls its makeGui method. The makeGui method creates the GUI (adding components and listeners) and displays it.

In addition, MagicSquareMaker contains a method named fillPanel that takes a JPanel and a magic square as arguments, removes the previous contents (if any) of the JPanel, attaches a GridLayout manager to the JPanel, and creates and adds N*N numeric labels to the JPanel, where N is the order of this magic square.

public class MagicSquare
Has a constructor that takes an odd positive integer argument, and creates a magic square of that order. Has a method getMagicSquareArray to return the array representing the magic square.

public class MagicSquareTest
Tests the MagicSquare class.

That is,

public class MagicSquareMaker extends JFrame {
    public static void main(String args[]) {
        new MagicSquareMaker().makeGui(5);
    }
    void makeGui(int n) {...}
    void fillPanel(JPanel panel, MagicSquare square) {...}
}
public class MagicSquare {
    public MagicSquare(int size) {...} // constructor
    public int[][] getMagicSquareArray() {...}
}
public class MagicSquareTest {...}

Necessary information

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()
This message, sent to a Container, will remove all the JComponents in that Container. Use this to remove the old JLabels from your magic square, before changing the layout manager and putting in the new JLabels.
validate()
This message, sent to a Container, will tell Java that you have changed the contents of that Container, and Java needs to redraw it for you.

Due date

Before 6am Friday April 5. Submit your zipped project file to Canvas. No other form of submission will be accepted.