Odd Magic Squares in Java

man working at computer
skynesher/E+/Getty Images

Level: Beginner

Focus: Logic, Arrays, Methods

Odd Magic Squares

It's unclear who first came up with a magic square. There is a story about a huge flood in China a long time ago. The people were worried they would be washed away and tried to appease the river god by making sacrifices. Nothing seemed to work until a child noticed a turtle sporting a magic square on its back that kept circling the sacrifice.

The square told the people how big their sacrifice needed to be in order to save themselves. Since then magic squares have been the height of fashion for any discerning turtle.

In case you've never come across one before, a magic square is an arrangement of sequential numbers in a square so that the rows, columns, and diagonals all add up to the same number. For instance, a 3x3 magic square is:

 8 1 6
 3 5 7
 4 9 2

Each row, column and diagonal adds up to 15.

Odd Magic Squares Question

This programming exercise is concerned with creating odd sized magic squares (i.e., the size of the square can only be an odd number, 3x3, 5x5, 7x7, 9x9, and so on). The trick with making such a square is to place the number 1 in the first row and middle column. To find where to place the next number, move diagonally upwards to the right (i.e., one row up, one column across). If such a move means you fall off the square, wrap around to the row or column on the opposite side.

Finally, if the move takes you to a square that is already filled, go back to the original square and move downwards by one. Repeat the process until all the squares are filled.

For example, a 3x3 magic square would start like so:

 0 1 0
 0 0 0
 0 0 0

A move diagonally upwards means we wrap around to the bottom of the square:

 0 1 0
 0 0 0
 0 0 2

Likewise, the next diagonal move upwards means we wrap around to the first column:

 0 1 0
 3 0 0
 0 0 2

Now the diagonal move upwards results in a square that is already filled, so we go back to where we came from and drop down a row:

 0 1 0
 3 0 0
 4 0 2

and it continues on and on until all the squares are full.

Program Requirements

  • a user must be able to enter in the size of the magic square.
  • they must only be allowed to enter in an odd number.
  • use a method to create the magic square.
  • use a method to display the magic square.

The question is can your program create a 5x5 magic square like the one below?

 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 

Hint: Apart from the programming aspects of this exercise it's also a test of logic. Take each step of creating the magic square in turn and figure how it can be done with a two-dimensional array.

Odd Magic Square Solution

Your program should have been capable of creating the 5x5 magic square below:

 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 

Here's my version:

 import java.util.Scanner;
 public class MagicOddSquare {
 
   public static void main(String[] args) {
     Scanner input = new Scanner(System.in);
     int[][] magicSquare;
     boolean isAcceptableNumber = false;
     int size = -1;
 
     //only accept odd numbers
     while (isAcceptableNumber == false)
     {
       System.out.println("Enter in size of square: ");
       String sizeText = input.nextLine();
       size = Integer.parseInt(sizeText);
       if (size % 2 == 0)
       {
         System.out.println("The size must be an odd number");
         isAcceptableNumber = false;
       }
       else
       {
         isAcceptableNumber = true;
       }
     }
 
     magicSquare = createOddSquare(size);
     displaySquare(magicSquare); 
   }
 
   private static int[][] createOddSquare(int size)
   {
     int[][] magicSq = new int[size][size];
     int row = 0;
     int column = size/2;
     int lastRow = row;
     int lastColumn = column;
     int matrixSize = size*size; 
 
     magicSq[row][column]= 1;
     for (int k=2;k < matrixSize+1;k++)
     {
       //check if we need to wrap to opposite row
       if (row - 1 < 0)
       {
         row = size-1;
       }
       else
       {
         row--;
       }
 
       //check if we need to wrap to opposite column
       if (column + 1 == size)
       {
         column = 0;
       }
       else
       {
         column++;
       }
 
       //if this position isn't empty then go back to where we
       //started and move one row down
       if (magicSq[row][column] == 0)
       {
         magicSq[row][column] = k;
       }
       else
       {
         row = lastRow;
         column = lastColumn;
         if (row + 1 == size)
         {
           row=0;
         }
          else
         {
           row++;
         }
         magicSq[row][column] = k;
       }
       lastRow = row;
       lastColumn= column; 
     }
     return magicSq;
   }
 
   private static void displaySquare(int[][] magicSq)
   {
     int magicConstant = 0;
     for (int j=0;j<(magicSq.length);j++)
     {
       for (int k=0;k<(magicSq[j].length);k++)
       {
         System.out.print(magicSq[j][k] + " ");
       }
       System.out.print;
       magicConstant = magicConstant + magicSq[j][0];
     }
      System.out.print("The magic constant is " + magicConstant);
   }
 }