Search code examples
javamagic-square

Creating a magic square (Java)


I'm kinda stuck on what to do with this square matrix coding project.

Whenever I try to input any values, the results always turn out as true and that the square matrix is a magic square. For example, this would turn out true:

16 03 02 13
05 10 11 08
09 06 07 12
04 15 14 01

but when I input values like:

03 04 16 02
05 01 02 10
05 08 07 12
03 14 13 09

This should return false but it still returns true saying that it is a magic square.

The requirements are that I need all the methods

"public void add(int i, int row, int col)": Adds an integer to the matrix at the specified location.

public

"public boolean allInRange": Determines whether all values in the matrix are in the proper range

"public boolean allUnique": Determines whether all values in the matrix appear only once

"public boolean isMagic": Determines whether the matrix illustrates a magic square. This means:

  • The user entered n^2 numbers for some number n

  • The numbers are only between 1 and n^2, inclusive

  • Each of the numbers occurs exactly once in the matrix

  • The sums of the elements in each row, column, and the two diagonals are equal

    public class SquareMatrix {

    private int[][] array; 
    
    
    public SquareMatrix(int size) 
    { 
      array = new int[size][size]; 
    }
    
    
    public void add(int i, int row, int column) {array[row][column] = i;} 
    
    
    //Just checks if the #of rows & columns are between 1-n^2
    public boolean allInRange()
    {
      int n = array.length;
    
      for (int row = 0; row < n; row++)
      {
        for (int col = 0; col < array[row].length; col++)
        {
          if (array[row][col] < 1 || array[row][col] > n*n)
            return false; 
        }
      }
    
      return true;
    }
    
    public boolean allUnique()
    {
      for (int i =0; i < array.length - 1; i++)
      {
        for (int j = i + 1; j < array.length; j++)
        {
          if(array[i]==array[j])
            return false;
        }
      }
      return true;
    }
    
    
    //Supposed to call the other methods (allInRange & allUnique)
    public boolean isMagic()
    {
    
      for(int[] row : array)
      {
        for (int num : row)
        {
          if (num == 0)
            return false;
        }
      }
    
    
      boolean range = allInRange();
      if (range == true)
        return true;
      if (range == false)
        return false;
    
      boolean unique = allUnique();
      if (unique == true)
        return true;
      if (unique == false)
        return false;
    
    
    
      int sumRow;
      int sumCol;
      int sum1 = 0;
      int sum2 = 0;
    
      //Sum of Left to Right Diaganol
      for (int i = 0; i < array.length; i++)
      {
        sum1 += array[i][i];
      }
    
      //sum of right to left diaganol
      for (int j = 0; j < array.length; j++)
      {
        sum2 += array[j][array.length-1-j];
      }
    
      if (sum1 != sum2)
        return false;
    
    
      //Sum of Rows
      for (int row = 0; row < array.length; row++)
      {
        sumRow = 0;
        for (int col = 0; col < array[row].length; col++)
          sumRow += array[row][col];
    
        if (sumRow != sum1)
          return false;
      }
    
    
      //Sum of Col
      for (int i = 0; i < array.length; i++)
      {
        sumCol = 0;
        for (int j = 0; j < array.length; j++)
          sumCol = array[j][i];
    
        if (sumCol != sum1)
          return false;
    
      }
    
      return true;    
    }
    
    
    
    public String toString()
    {
      int n = array.length;
    
      String lol = "";
    
      for (int[] row : array)
      {
        for (int num : row)
        {
          String hi = String.format("%0"+(n*n+"").length()+"d",num);
    
          lol += hi + " ";
        }
        lol += "\n";
      }
      return lol;
    }
    

    }

Here is my driver class

 import javax.swing.*;


public class SquareMatrixDriver { 
  
  public static void main(String[] args) { //My favorite line in history  
    
    
    JFrame bot = new JFrame(); //We can use JFrame to read the inputs 
    
    do 
    {
      //We have to make sure that it is a valid input or else I am doomed
      int size = 0;
      do 
      {
        size = Integer.parseInt(JOptionPane.showInputDialog(bot, "Enter the size of the matrix."));
        if (size < 1) 
        {
          JOptionPane.showMessageDialog(bot, "Invalid size! Enter a number greater than 0.");
        }
      } 
      while(size < 1);
      
      SquareMatrix matrix = new SquareMatrix(size);
      
      for (int i=0; i<size; i++) 
      {
        //Gets thhe User's Input
        
        String[] stringInput;
        do 
        {
          stringInput = JOptionPane.showInputDialog(bot, "Enter the row number" + (i + 1) + ", with " + size + " elements, split by commas.").split(",");
          if (stringInput.length != size) 
          { //In this code we basically enter the numbers with commas
            JOptionPane.showMessageDialog(bot, "Invalid size! " + stringInput.length + " elements entered but " + size + " required.");
          }
        } 
        while(stringInput.length != size);
        
        int[] intInput = new int[size];
        for (int o=0; o<size; o++) 
        { 
          
        }
        
        for (int o=0; o<size; o++) 
        {
          matrix.add(Integer.parseInt(stringInput[o]), i, o); //Here we would put everything into the Matrix
        }
      }
      
      
      JOptionPane.showMessageDialog(bot, "The matrix is " + (matrix.isMagic()? "very" : "not") + " correct"); //This line will output if the Matrix works or doesnt work 
      
      JOptionPane.showMessageDialog(bot, matrix); // Enters out the final output
    } while (JOptionPane.showConfirmDialog(bot, "Do you wish to exit?", "Exit", JOptionPane.YES_NO_OPTION) == 1); //Asks the User if they would like to exit the program
  }
}






      
      
     

Solution

  • Errors that I could find by visual inspection:

    allUnique() is completely wrong, you have to check if each number occurs only once in the matrix, but you are comparing row arrays that is something totally different, the best way to check unicity would be normally to use an hashset, but since here you have a very defined range of numbers (from 1 to n2), then use any array of n2 booleans. Scan the square matrix and test/set the corresponding element in the array, if already set return false.

    public boolean allUnique() {
      int n=array.length;
      boolean[] set=new boolean[n*n];
      for (int i=0; i < n; i++) {
        for (int j=0;j < n; j++) {
          //Here assuming that you already sucessfully called allInRange, 
          //otherwise we must check bounds to avoid an index out of bounds exception
          if(set[array[i][j]-1]) {
            return false;
          }
          set[array[i][j]-1] = true;
        }
      }
      return true;
    }
    

    In method isMagic() all this part is wrong and redundant

     boolean range = allInRange();
      if (range == true)
        return true;  //WRONG, this will immediately return with true, without further checks
      if (range == false)
        return false;
    
      boolean unique = allUnique();
      if (unique == true)
        return true;  //WRONG, same as before
      if (unique == false)
        return false;
    

    Just replace it with

    if (!allInRange()) {
        return false;
    }
    if (!allUnique()) {
        return false;
    }
    

    Finally in isMagic() when you calculate the column's sum, the addition is missing

    sumCol = array[j][i];
    

    must be replaced with

    sumCol += array[j][i];