Magic Squares

Hi, trying to set up a boolean return function that lets me know whether the contents of a multidimensional array are a "magic square" (sum of all rows, columns, and diagonals are equal). I set it up and tested it (can't get my VSCode debugger to stop at breakpoints for some reason) and the bool is outputting false when I've verified the array sums visually. Is there something wrong here I'm not seeing? I must have gone over this code like 10 times already.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
 #include <iostream>

using namespace std;

//C++ program to determine if a multidimensional array is a "magic square"
//(sum of all lines and diagonals is the same)

//set the size of the array so it can be modified if desired (9x9 square, 5x5 square, etc)
#define L 3

/** Determines whether a square two-dimensional array is a "perfect" square
 * @param int square_array[][L] (array values to be verified)
 * @return result (true/false boolean result)
*/

bool isMagicSquare(int square_array[][L])
{
    //DIAGONALS
    //check to see if sums of diagonals match
    int sum = 0, sum2 = 0;
    //first diagonal
    for(int i = 0; i < L; i++)
    {
        sum += square_array[i][i];
    }
    //second diagonal
    for(int i = 0; i < L; i++)
    {
        sum2 += square_array[i][L-1-i];
    }
    //equity check
    if(sum != sum2)
    {
        return false;
    }

    //check row sums (nested for loop)
    int rowSum = 0;
    for(int i = 0; i < L; i++)
    {
        for(int j = 0; j < L; j++)
        {
            rowSum += square_array[i][j];
        }
        //check each row sum to make sure it's equal to diagonal sums
        if(rowSum != sum)
        {
            return false;
        }
    }

    //check column sums (another nested loop)
    int colSum = 0;
    for(int i = 0; i < L; i++)
    {
        for(int j = 0; j < L; j++)
        {
            colSum += square_array[j][i];
        }
        //check each column to make sure it's equal to diagonal sums
        if(colSum != sum)
        {
            return false;
        }
    }

    //if boolean is never switched to false, return true result
    return true;
}

int main()
{
    int square[][L] = { { 2, 7, 6 },
                        { 9, 5, 1 },
                        { 4, 3, 8 } };

    if(isMagicSquare(square))
    {
        cout << "Array is a magic square.";
    }
    else 
    {
        cout << "Array is NOT a magic square.";
    }
}
Think about where you're initializing rowSum and colSum.
Maybe those inits should be elsewhere?
Yep, that fixed it. Is that because the conditionals are in a different scope from where the ints were initialized?
It's not about scope. It's that you need to reset the sum to 0 for every iteration of the outer loop, otherwise you're just adding to the sum of the last row/col.

Some little points:
L is better named Size and should be a const int instead of a define.

 
const int Size = 3;

i and j would be better named row and col (in the double-for loops).

1
2
3
4
5
6
7
8
    for (int row = 0; row < Size; row++)
    {
        int rowSum = 0;
        for (int col = 0; col < Size; ++col)
            rowSum += square[row][col];
        if (rowSum != sum)
            return false;
    }
Got it. I'm also having issues with setting it up so the user can input the numbers. For some reason, the array is just filled with the last int entered:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 int square[L][L] = {{2, 7, 6},
                        {9, 5, 1},
                        {4, 3, 8}};

    int count = 0;
    while(count < L * L)
    {
        int input;
        cout << "Enter a number 1-" << L * L << ": ";
        cin >> input;
        for(int i = 0; i < L; i++)
        {
            for(int j = 0; j < L; j++)
            {
                square[i][j] = input;
            }
        }
        count++;
    }


This gives me an output of
8 8 8
8 8 8
8 8 8

uuuuugghhhh!

EDIT: I read the tutorial on this site about filling multidimensional arrays, and my code appears to be solid. Now I'm reaaaal confused
Last edited on
Updated:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
int main()
{
    int square[L][L];

    int count = 0;
    while(count < L * L)
    {
        int input;
        cout << "Enter a number 1-" << L * L << ": ";
        cin >> input;
        //check to make sure the input is within the specified range
        if(inRange(input))
        {
             for(int i = 0; i < L; i++)
             {
                 for(int j = 0; j < L; j++)
                 {
                     square[i][j] = input;
                 }
             }
             count++;
        }
        else 
        {
            cout << "Please make a valid entry (1-" << L * L << ")" << endl; 
        }
    }
    
    
    
    print_array(square);

    return 0;
}
Last edited on
The while loop doesn't make sense.
Just use the double loop that goes through all the elements in square. Put the cin in the inner loop since you need to read a new value for each inner iteration.
Fixed, I have tested this and it seems to be working as intended. Even threw in some input validation just for funsies.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#include <iostream>

using namespace std;

//C++ program to determine if a multidimensional array is a "magic square"
//(sum of all lines and diagonals is the same)

//set the size of the array so it can be modified if desired (9x9 square, 5x5 square, etc)
#define L 3

/** Prints a two-dimensional array
 * @param int args[][] (array to print)
*/

void print_array(int args[L][L])
{
    for(int i = 0; i < L; i++)
    {
        for(int j = 0; j < L; j++)
        {
            cout << args[i][j] << " ";
            if(j == L - 1)
            {
                cout << endl;
            }
        }
    }
}

/**Determines whether an integer is within the range of 1-total amt
 * @param int a (integer to be analyzed)
 * @return true/false based on integer
*/

bool inRange(int a)
{
    if(a < 1 || a > L * L)
    {
        return false;
    }
return true;
}

/** Determines whether a square two-dimensional array is a "perfect" square
 * @param int square_array[][L] (array values to be verified)
 * @return result (true/false boolean result)
*/

bool isMagicSquare(int square_array[][L])
{
    //DIAGONALS
    //check to see if sums of diagonals match
    int sum = 0, sum2 = 0;
    //first diagonal
    for(int i = 0; i < L; i++)
    {
        sum += square_array[i][i];
    }
    //second diagonal
    for(int i = 0; i < L; i++)
    {
        sum2 += square_array[i][L-1-i];
    }
    //equity check
    if(sum != sum2)
    {
        return false;
    }

    //check row sums (nested for loop)
    
    for(int i = 0; i < L; i++)
    {
        int rowSum = 0;
        for(int j = 0; j < L; j++)
        {
            rowSum += square_array[i][j];
        }
        //check each row sum to make sure it's equal to diagonal sums
        if(rowSum != sum)
        {
            return false;
        }
    }

    //check column sums (another nested loop)
    
    for(int i = 0; i < L; i++)
    {
        int colSum = 0;
        for(int j = 0; j < L; j++)
        {
            colSum += square_array[j][i];
        }
        //check each column to make sure it's equal to diagonal sums
        if(colSum != sum)
        {
            return false;
        }
    }

    //if boolean is never switched to false, return true result
    return true;
}

int main()
{
    //initialize array
    int square[L][L];

    //gather input from user and validate
    int input, retry;
    for(int i = 0; i < L; i++)
    {
        for(int j = 0; j < L; j++)
        {
            cout << "Enter a number 1-" << L * L << ": ";
            cin >> input;
            if(inRange(input))
            {
                //if input is in legal range, add to the array
                square[i][j] = input;
            }
            else
            {
                //if the user entered something out of the allowed range, retry input until successful and enter correct input
                while(!inRange(retry))
                {
                    cout << endl << "You have entered an invalid integer. Please try again.\n";
                    cout << "Legal Integer: ";
                    cin >> retry;
                    square[i][j] = retry;
                }
            }
        }
    }
    
        
     cout << endl;

    //print array, just for visibility and to verify values entered
    print_array(square);

    //determine if array is a magic square and let the user know
    if(isMagicSquare(square))
    {
        cout << "\nArray IS a magic square.";
    }
    else
    {
        cout << "\nArray IS NOT a magic square.";
    }
    
    //done!

    return 0;
}
You should avoid doing using namespace std;
@itsArtem, I used to think that, but it's so common in beginner programs that I don't really care anymore. I'm aware of the potential problems, but it's nice to not have std:: all over the place.
Topic archived. No new replies allowed.