//========================================================================= #define PROGRAMMER "SOLUTIONS, NoFrills" #define PROG_CODE "soln" #define COURSE "ECE-1021" #define YEAR (2003) #define TERM "Fall" #define SECTION (0) #define ASSIGNMENT "HW #5B" #define REVISION (0) #define TITLE "Magic Square" #define SUBTITLE "Problem 7.19" #define EMAIL "wbahn@eas.uccs.edu" #define FILENAME "05b0soln.c" //========================================================================= // PROBLEM: // // Write a program to generate a 5x5 Magic Square using the following // set of rules: // // 1) Place 1 in the middle of the top row. // 2) Place successive numbers in the square up and to the left of the // present square subject to the following special cases: // Wrap around to the bottom or right side as necessary. // If the square is already occupied, drop to the square directly // below the present square instead. // If the present square is the top left corner, drop to the // square directly below it. // SOLUTION: // // DEVIATIONS OF SOURCE CODE FROM SUBMITTED PSEUDOCODE: // // The Display of the Magic Square contents was incorporated into the // Generation of the Magic Square - so they are displayed as they // are generated. // // The code that determines the cell to move to now computes nextrow // and nextcol regardless of the situation and then explicitly sets // row and col equal to these values. Is a bit less efficient this // way, but more readable. // // The loop that places the code has the increment at the beginning // of the loop so that the value of n for the bulk of the loop runs // from 1 to 25 instead of 0 to 24 using the normal loop initialization // and test conventions. // // HIGH LEVEL DECOMPOSITION: // 1) TASK: Draw the empty boxes for the Magic Square // 1.1) LOOP: for each element // 1.1.1) TASK: Place cursor at position where number will be printed // 1.1.2) TASK: Draw character box around the center // 1.1.3) TASK: Initial the box contents to zero // 2) TASK: Generate the Magic Square // 2.1) TASK: Set cursor to middle box of top row // 2.2) LOOP: for each value of n from 1 to size^2 // 2.2.1) TASK: Set present box equal to n // 2.2.2) TASK: Print out contents of present box // 2.2.3) TASK: Determine NextBox // 2.2.4) TASK: Set present box equal to NextBox //== INCLUDE FILES ======================================================== #include // printf() #include // gotoxy() //== MACRO DEFINITIONS ==================================================== #define SIZE (5) #define ROW_PITCH ( 2) #define FIRST_ROW (10) #define COL_PITCH ( 5) #define FIRST_COL (20) #define CellRow(row) (ROW_PITCH*(row) + FIRST_ROW) #define CellCol(col) (COL_PITCH*(col) + FIRST_COL) #define index(row,col) ((row)*SIZE+(col)) //== TOP LEVEL SUPPORE FUNCTION PROTOTYPES ================================ void PrintHeader(void); void InitializeMagicSquare(int *array, int size); void GenerateMagicSquare(int *array, int size); //== MAIN FUNCTION ======================================================== int main(void) { int MagicSquare[SIZE][SIZE]; PrintHeader(); printf("\n"); // Print a blank line // The type casts in the following function calls suppress a compiler // warnings due to suspicious pointer conversions. The compiler sees // that MagicSquare is really a pointer to an array of integer pointers // but the functions compute the offsets based on the knowledge that // the entire array is packed into a contiguous block of memory so this // warning can be safely ignored and/or suppressed. InitializeMagicSquare((int *)MagicSquare, SIZE); GenerateMagicSquare((int *)MagicSquare, SIZE); return(0); } //== SUPPORT FUNCTIONS ==================================================== void PrintHeader(void) { printf("========================================" "=======================================\n"); printf("Course....... %s-%i (%s %i)\n", COURSE, SECTION, TERM, YEAR); printf("Programmer... %s (%s)\n", PROGRAMMER, PROG_CODE); printf("Assignment... %s (Rev %i) (Source Code in %s)\n", ASSIGNMENT, REVISION, FILENAME); printf("Description.. %s\n", TITLE); printf(" %s\n", SUBTITLE); printf("========================================" "=======================================\n"); return; } //== LOWER LEVEL FUNCTION PROTOTYPES ====================================== //== TOP LEVEL SUPPORT FUNCTION DEFINITIONS =============================== void InitializeMagicSquare(int *array, int size) { int row, col; int r,c; for(row = 0; row < size; row++) for(col = 0; col < size; col++) { // Place cursor at position where number will be printed r = CellRow(row); c = CellCol(col); // Draw character box around the center gotoxy(c-2, r-1); printf("+----+"); gotoxy(c-2, r ); printf("| |"); gotoxy(c-2, r+1); printf("+----+"); // Initial the box contents to zero array[index(row,col)] = 0; } return; } void GenerateMagicSquare(int *array, int size) { int row, col; int nextrow, nextcol; int n, max_n; // Set cursor to middle box of top row row = 0; col = size/2; // relying on integer division // Place each number starting with 1 n = 0; max_n = size*size; // to prevent calculating square in each loop pass do { // Advance to next value n++; // Set present box equal to n array[index(row,col)] = n; // Print out present box contents gotoxy(CellCol(col), CellRow(row)); printf("%2i", array[index(row,col)]); // Determine next box to move to if((0==row)&&(0==col)) // present box is corner box { // Impose special case for corner nextrow = 1; nextcol = 0; } else { // Determine the "preferred" next box nextrow = row - 1; nextcol = col - 1; // Take care of any wrap-around issues if(nextrow < 0) // wrap around to bottom edge of square nextrow = size - 1; if(nextcol < 0) // wrap around to right edge of square nextcol = size - 1; // Take care of case where preferred cell is already filled. if(array[index(nextrow,nextcol)]) { // Move to cell directly below present cell nextrow = row + 1; nextcol = col; } } // Update row and col to next box and increment n row = nextrow; col = nextcol; } while(n < max_n); return; }