I head never heard about Magic Squares before and consulted Wikipedia about them. As expected, I found the description of various algorithms for their construction.
I identified the algorithm of de la Loubère as the one which the OP obviously tried to implement. IMHO, the attempt was actually not that bad.
The hints I gave about (missing row wrap-around in) if(magicsq[row][col]!=0) row++;
and (missing iteration step in) for (x=2;x<3*3;x++)
appeared to be reasonable.
Considering this I got the algorithm running. My first result looked not that bad but the result checks showed that it was actually wrong. I switched some directions of row and column counting but without luck. Then, I re-visited the above linked article again and compared what was described with what I had implemented. Finally, I found out that I made another semantical mistake in my implementation. I believe the OP did it as well:
The method prescribes starting in the central column of the first row with the number 1. After that, the fundamental movement for filling the squares is diagonally up and right, one step at a time. If a filled square is encountered, one moves vertically down one square instead, then continues as before. When an "up and to the right" move would leave the square, it is wrapped around to the last row or first column, respectively.
Emphasize of instead was done by me – the detail I missed. So, there was a change necessary: The coordinates of new cell have to be discarded if the cell is already filled. The new coordinates are instead one row down (i.e. ++row
) with the resp. wrap-around. After fixing this the sample computed a correct result:
#include <iostream>
int main()
{
int magicsq[3][3] = {0};
int row = 0, col = 1;
magicsq[row][col] = 1;
for (int x = 2; x <= 9; ++x) {
int rowT = row - 1; if (rowT < 0) rowT += 3;
int colT = col + 1; if (colT >= 3) colT -= 3;
if (magicsq[rowT][colT]) {
if (++row >= 3) row -= 3;
} else {
row = rowT; col = colT;
}
magicsq[row][col] = x;
}
std::cout << "Magic Square:" << std::endl;
for (row = 0; row < 3; ++row) {
for (col = 0; col < 3; ++col) {
std::cout << ' ' << magicsq[row][col];
}
std::cout << std::endl;
}
std::cout << "Row sums:";
for (row = 0; row < 3; ++row) {
int sum = 0;
for (col = 0; col < 3; ++col) sum += magicsq[row][col];
std::cout << ' ' << sum;
}
std::cout << std::endl;
std::cout << "Column sums:";
for (col = 0; col < 3; ++col) {
int sum = 0;
for (row = 0; row < 3; ++row) sum += magicsq[row][col];
std::cout << ' ' << sum;
}
std::cout << std::endl;
std::cout << "Diagonal sums: ";
int sumM = 0, sumC = 0;
for (row = 0; row < 3; ++row) {
sumM += magicsq[row][row];
sumC += magicsq[row][2 - row];
}
std::cout << ' ' << sumM << ' ' << sumC << std::endl;
return 0;
}
The output is:
Magic Square:
8 1 6
3 5 7
4 9 2
Row sums: 15 15 15
Column sums: 15 15 15
Diagonal sums: 15 15
Life demo on ideone
Note:
Implementing such an algorithm from description, you can easily be trapped. The description used "row up", "row down" according to the illustrations. So, a clear mapping is needed to define what "up" and "down" means concerning the matrix storage. In my case, "row up" is row
decrement, "row down" is row
increment. In this specific case, it probably works also vice versa as the linked article mentions that result matrix can be mirrored horizontally and vertically.
if(magicsq[row][col]!=0) row++;
again: Are you sure thatrow
never becomes >= 3? If in doubt, insertassert(row >= 0 && row < 3);
just beforemagicsq[row][col] = x;
. (You have to#include <cassert>
for this.) – Scheff's Catint col=3/2;
is looking innocent to me. It results inint col = 1;
. If the intention was to start in the middle column of first row then this provides exactly what was intended. – Scheff's Cat