יום שני, 23 באוקטובר 2017

הבנה טובה של מצביעיםVSמערכים דו מימדיים - ריבוע קסם (שפת C)

ראשית נכתוב תוכנית בסיסית שבודקת האם ריבוע של מספרים הוא ריבוע קסם

הגדרה:
ריבוע של מספרים בו:
- הסכום של כל שורה שווה.
- הסכום של כל עמודה שווה.
- הסכום של שני האלכסונים הגדולים שווה.
- כולם שווים אחד לשני (כלומר סכום האלכסון שווה לסכום השורה ושווה לסכום העמודה)

שימו לב: אפשר להוסיף בדיקה שאף מספר לא חוזר על עצמו פעמיים, אך זה מגביל אותנו לדאוג תמיד לכך שיש יותר מספרים אפשריים מאשר משבצות. אחרת כדי למלא את כל המשבצות תמיד נקבל כפילויות.




לדוגמה:

ריבוע חוקי:
1  8  3
6  4  2
5  0  7



ריבוע לא חוקי:
1  2  3
4  5  6
7  8  9

אם מוסיפים בדיקה שאף מספר לא חוזר על עצמו פעמיים - אז הריבוע לא חוקי. אם לא מוסיפים - כן חוקי:
1  1  1
1  1  1
1  1  1




כך נראה הביצוע:








התוכנית:
#include<stdio.h>
enum status {FALSETRUE};
#define N 3  // (מספר המשבצות (כלומר: 3*3 משבצות
 
enum status Check_if_this_is_a_Magic_Square(int Array[N][N]){
 int i, j, temp=0, sum=0;
 
 for(i=0; i<N; i++)
  temp += Array[i][i]; // אלכסון משמאל עליון לימין תחתון
 sum = temp;
 
 temp = 0;
 for(i=0,j=N-1; i<N; i++,j--) // בדיקת אלכסון מימין עליון לשמאל תחתון
  temp += Array[i][j];
 if(temp != sum) return FALSE;
 
 
 for(i=0; i<N; i++){
  temp = 0;
  for(j=0; j<N; j++){
   temp += Array[i][j]; // בדיקת שורות
  }
  if(temp != sum) return FALSE; 
 }
 
 for(j=0; j<N; j++){
  temp = 0;
  for(i=0; i<N; i++){
   temp += Array[i][j]; // בדיקת עמודות
  }
  if(temp != sum) return FALSE; 
 }
 
 /*
 
 // זו בדיקה שאין כפילות מספר. אסור להוסיף את הבדיקה הזאת אם רוצים פחות ריבועים ממספרים
 // לדוגמה: אם אנחנו מכניסים רק מספרים בין 1-9 ורוצים 4*4 משבצות - תמיד יהיו כפילויות וזה אף פעם לא יהיה ריבוע חוקי
 
 for(i=0; i<N*N-1; i++){
  for(j=i+1; j<N*N; j++){
   if( *(*Array+j) == *(*Array+i) ) return FALSE;
   //מערך דו ממדי הוא סוג של מצביע למצביע. אפשר בצורה הזו להתייחס אליו כמו אל חד ממדי 
  }
 }
 
 return TRUE;
 */
}
 
void main(){
 int Array[N][N] = {0}, i=0, j;
 
 printf("Enter Magic Square (%d*%d):\n",N,N);
 for(i=0; i<N; i++){
  for(j=0; j<N; j++){
   scanf("%d",&Array[i][j]);
  }
 } 
 
 if(Check_if_this_is_a_Magic_Square(Array) == FALSE)
  printf("\nNo! This is NOT a Magic Square.\n\n");
 else
  printf("\nYes! This is a Magic Square.\n\n");
 
 
 scanf("%d",&i); // כדי שהתוכנית לא תיסגר
}











כעת נכתוב משהו הרבה יותר מאתגר:

תוכנית ששומרת בקובץ טקסט את כל הריבועים האפשריים!

נגדיר בתוכנית מה גודל הריבוע (3*3 או 4*4 וכו') וכן מה טווח המספרים שלנו (0-8 לדוגמה).


נסו בעצמכם!




התוכנית:
(נעשה שימוש בפונקציה הנפלאה "Increase_the_array" (כל הזכויות שמורות))
התוכנית גם שומרת את כל הריבועים האפשריים בקובץ טקסט, וגם מדפיסה את כולם למסך.
#include<stdio.h>
enum status {FALSETRUE};
#define N 3     // גודל הריבוע
#define MAX_NUM 8  // המספר הגדול ביותר שיכול להיות במשבצת
 
enum status Check_if_this_is_a_Magic_Square(int Array[N][N]){
 int i, j, temp=0, sum=0;
 
  for(i=0; i<N*N-1; i++){ // בדיקת כפילות מספר. הזזתי את הבדיקה הזאת להתחלה משום שזה מקרה נפוץ במיוחד לפסילת ריבוע
  for(j=i+1; j<N*N; j++){
   if( *(*Array+j) == *(*Array+i) ) return FALSE;
   // (מערך דו ממדי הוא סוג של מצביע למצביע. אפשר בצורה הזו להתייחס אליו כמו אל חד ממדי) 
  }
 }
 
 for(i=0; i<N; i++)
  temp += Array[i][i]; // אלכסון משמאל עליון לימין תחתון
 sum = temp;
 
 temp = 0;
 for(i=0,j=N-1; i<N; i++,j--) // בדיקת אלכסון מימין עליון לשמאל תחתון
  temp += Array[i][j];
 if(temp != sum) return FALSE;
 
 
 for(i=0; i<N; i++){
  temp = 0;
  for(j=0; j<N; j++){
   temp += Array[i][j]; // בדיקת שורות
  }
  if(temp != sum) return FALSE; 
 }
 
 for(j=0; j<N; j++){
  temp = 0;
  for(i=0; i<N; i++){
   temp += Array[i][j]; // בדיקת עמודות
  }
  if(temp != sum) return FALSE; 
 }
 
 return TRUE;
 
}
 
void show(int Array[N][N]){
 int i,j;
 for(i=0; i<N; i++){
  for(j=0; j<N; j++){
   printf("%3d",Array[i][j]);
  }
  putchar('\n');
 }
}
 
 
 
int Increase_the_array(int *Arrayint maxint ind){ // חייב לקבל מערך שמאותחל כולו לאפסים
 if(ind<0) return  -1;
 if (Array[ind] == max) {
  Array[ind] = 0;
  return Increase_the_array(Arraymaxind-1);
 }
 Array[ind]++;
 return 1;
}
 
 
 
void square_to_text_file(FILE *fpint Array[N][N], int num){
 int i,j;
 fprintf(fp"%d >>\n",num);
 for(i=0; i<N; i++){
  for(j=0; j<N; j++){
   fprintf(fp"%3d",Array[i][j]);
  }
  fputc( '\n' , fp );
 }
 
}
 
 
 
 
void main(){
 int Array[N][N] = {0}, i=0, j;
 FILE *fp ;
 fp = fopen ("magic squares.txt""w" );
 // זה שם קובץ הטקסט שישמר בתיקייה ממנה רצה התוכנית. בקובץ יאוחסנו התוצאות "magic squares.txt"
 
 printf("All possible magic squares:\n");
 do{
  if(Check_if_this_is_a_Magic_Square(Array)==TRUE){
   i++;
   printf("%d >>\n",i);
   show(Array);
   square_to_text_file(fp, Array, i);
  }
 
 }while(Increase_the_array(*Array, MAX_NUMN*N-1)==1);
 //  ( תתייחס אליו כמו למערך חד ממדי Increase_the_array ככה שולחים מערך דו ממדי באופן שהפונקציה )
 
 
 
 /*
       :הסבר
     .כל העניין זה להתייחס למערך דו ממדי עם משתנה אינדקס אחד בלבד
     :דוגמה
     *(*Array+3) = 9;
 */
 
 
 fclose (fp);
 printf("---End!\n");
 scanf("%d",&i); // כדי שהתוכנית לא תיסגר 
} 






כן זה לא פשוט..

אין תגובות:

הוסף רשומת תגובה