For those of us who like to make the computer do all of our work, here is a C++ implementation of the algorithm explained by Eternal Shroud. This version also prints out the totals of each row, column, and diagonal (which are all the same by definition, but it was handy for debugging). It was tested with g++ 3.2.2.
#include <iomanip>
#include <iostream>
using namespace std;
class cMagicSquare {
private:
int **m_ippMagicSquare;
const int m_iDim;
int m_iOtherDiagonal;
public:
cMagicSquare(int iInput);
~cMagicSquare();
void print() const;
};
cMagicSquare::cMagicSquare(int iInput):m_iDim(iInput) {
int iCol, iRow;
m_ippMagicSquare = new int *[m_iDim+1];
for(int i = 0; i <= m_iDim; m_ippMagicSquare[i++] = new int[m_iDim+1]);
for(iRow = 0; iRow <= m_iDim; iRow++)
for(iCol = 0; iCol <= m_iDim; m_ippMagicSquare[iRow][iCol++] = 0);
iRow = 1;
iCol = m_iDim / 2 + 1;
m_iOtherDiagonal = 0;
for(int iValue = 1; iValue <= m_iDim * m_iDim; iValue++) {
if(m_ippMagicSquare[iRow][iCol] > 0) {
iRow += 2;
if(iRow > m_iDim)
iRow -= m_iDim;
if(--iCol < 1)
iCol = m_iDim;
}
m_ippMagicSquare[iRow][iCol] = iValue;
m_ippMagicSquare[0][iCol] += iValue;
m_ippMagicSquare[iRow][0] += iValue;
if(iRow == iCol)
m_ippMagicSquare[0][0] += iValue;
if(iRow+iCol == m_iDim+1)
m_iOtherDiagonal += iValue;
if(--iRow < 1)
iRow = m_iDim;
if(++iCol > m_iDim)
iCol = 1;
}
}
cMagicSquare::~cMagicSquare() {
for(int i = 0; i <= m_iDim; delete [] m_ippMagicSquare[i++]);
delete [] m_ippMagicSquare;
}
void cMagicSquare::print() const {
cout<<"\nThe number you selected was "<<m_iDim<<", and the matrix is:\n\n";
int iCol, iRow;
for(iRow = 1; iRow <= m_iDim; iRow++) {
cout<<" ";
for(iCol = 1; iCol <= m_iDim; cout<<setw(5)<<m_ippMagicSquare[iRow][iCol++]);
cout<<" = "<<setw(5)<<m_ippMagicSquare[iRow][0]<<"\n";
}
for(iCol = 0; iCol <= m_iDim; iCol++, cout<<"-----");
cout<<"\n"<<setw(5)<<m_iOtherDiagonal;
for(iCol = 1; iCol <= m_iDim; cout<<setw(5)<<m_ippMagicSquare[0][iCol++]);
cout<<" "<<setw(5)<<m_ippMagicSquare[0][0]<<endl;
}
int main() {
cout<<"\nMagic Squares: This program produces an NxN matrix where\n"
"N is some positive odd integer. The matrix contains the\n"
"values 1 to N*N. The sum of each row, each column, and\n"
"the two main diagonals are all equal. Not only does this\n"
"program produce the matrix, it also computes the totals for\n"
"each row, column, and two main diagonals.\n\n"
"Because of display constraints, this program can work with\n"
"values up to 13 only.\n"<<endl;
for(int iInput = 1; iInput != -1;) {
cout<<"\nEnter a positive, odd integer (-1 to exit program): "<<flush;
cin>>iInput;
if(cin.good()) {
if(iInput <= 0) {
if(iInput != -1)
cerr<<"Sorry, but the integer has to be positive."<<endl;
} else if(iInput % 2 == 0) {
cerr<<"Sorry, but the integer has to be odd."<<endl;
} else if(iInput > 13) {
cerr<<"Sorry, but the integer has to be less than 14"<<endl;
} else {
cMagicSquare *mspMySquare = new cMagicSquare(iInput);
mspMySquare->print();
delete mspMySquare;
}
} else {
cerr<<"Sorry, but a number must be entered."<<endl;
cin.clear();
}
cin.ignore(100,'\n');
}
cout<<"\nBye bye!"<<endl;
return 0;
}
Thanks to OldMiner for some efficiency modifications and help in editing this code so that it also works in Microsoft Visual C++ 6.0 (which doesn't handle variable scope correctly).
Thank you, node your homework!