본문 바로가기
Computer & Program/잡다한 이모저모

마방진~ Magic square

by TDRemon 2009. 3. 4.
반응형

#include<iostream.h>

class Magic
{
 private :
  int row, col; // 2차 배열의 가로와 세로 값
  int ro, co; // 변환시 가로와 새로 값
  int **p; // 2차 동적 배열의 포인터
 public :
   // 생성자
  Magic(){
   row=col=0;
   ro=co=0;
  }
  //소멸자
  ~Magic(){
   delete[] p;
  }
  void select(); // 초기 선택문
  void evefun(int i); // 짝수 4의 배수 구현 함수
  void oddfun(int i); // 홀수 구현 함수
  void printout(int i); // 출력 함수
  void change(int i); // 홀수 마방진의 이동 제어 함수
  void swap(int i, int k, int n); // 짝수 4의 배수 제어 함수
  void heap(int i); // 동적 할당
};

void main()
{
 Magic *temp;
 temp = new Magic;
 temp->select();
}

void Magic::heap(int i) // 2차배열 동적 할당
{
 p = new int* [i];
 for(int n=0; n<i; n++){
  p[n] = new int [i];
 }
}

void Magic::swap(int i, int k, int j) // 4의 배수 마방진 위치 바꾸는 함수
{
 int temp;
 ro=i-1-k;
 co=i-1-j;
 temp=p[k][j];
 p[k][j]=p[ro][co];
 p[ro][co]=temp;
}

void Magic::change(int i) // 홀수인 경우 자리 이동을 위한 함수
{
 if(row<0){  // row가 0보다 작아지면 가장 큰 값으로 이동
  row += i;
 }
 if(col<0){  // col가 0보다 작아지면 가장 큰 값으로 이동
  col += i;
 }
}

void Magic::select()
{
 int i;
 while(1){ // 무한루프
  cout << "Input number : ";
  cin >> i; // 행열 한 변의 길이 입력
  if(i<=2 || i>17){
   cout<< "Can not make Magic_square. retry(3~17)" <<endl; // 3~17 범위 밖일 경우 출력
  }
  else if(1 == i%2){
   oddfun(i); // 홀수인 경우 호출
  }
  else if(0 == i%4){
   evefun(i); // 짝수 4의 배수인 경우 호출
  }
 }
}

void Magic::evefun(int i) // 4의 배수
{
 heap(i); // 동적 할당
 row=col=i;
 int valu=1;
 // 위에서부터 오른쪽으로 순서대로 숫자 대입
 for(int k=0; k<i; k++){
  for(int j=0; j<i; j++){
   p[k][j]=valu;
   valu++;
  }
 }
 for(k=0; k < i/4; k++){ // 상하 교환
  for(int j = i/4; j < 3*i/4; j++){
   swap(i, k, j);
  }
 }
 for(k = i/4; k < 3*i/4; k++){ // 좌우 교환
  for(int j=0; j < i/4; j++){
   swap(i, k, j);
  }
 }
 printout(i); // 출력 함수 호출
 delete [] p; // 동적 할당 해제
}

void Magic::oddfun(int i)
{
 heap(i);
 row=col=i; // 인자값 복사
 /* 초기값으로 설 */
 for(int k=0; k<i; k++){
  for(int j=0; j<i; j++){
   p[k][j]=0; // 0으로 설
  }
 }

 /* 홀수 마방진 시작 위치 잡는 함수
    즉, 가장 윗칸 한가운데 */
 row = 0;
 col = col/2;
 for(int valu=1; valu <= (i*i); valu++){
  change(i); // 배열에서 칸이 벗어나면 정정
  if(p[row][col] > 0){ // 이동한 자리에 이미
   row = ro;   // 숫자가 들어가 있으면
   col = co;   // 이동하기 전의 자리로 이동하여
   row++;    // 아래로 한칸 이동
   change(i);
  }
  // 배열에 해당 값 입력
  p[row][col] = valu;
  // 이동적의 위치를 임시로 기억
  ro = row;
  co = col;
  // 배열의 대각선 왼쪽 위로 이동
  col--;
  row--; 
 }
 printout(i); // 출력 함수 호출
 delete [] p; // 동적 할당 해제
}

void Magic::printout(int i) // 결과값 출력
{
 // for 문을 2개 이용하여 행열의 모든 값을 출력
 for(int k=0; k<i; k++){
  for(int j=0; j<i; j++){
   cout << p[k][j];
   // 아래의  공백 출력은 칸을 맞춰 주기 위한 것임.
   if(p[k][j]<10){
    cout << "   ";
   }
   else if(p[k][j]>9 && p[k][j]<100){
    cout << "  ";
   }
   else{
    cout << " ";
   }
  }
  cout << endl; // 한 행이 끝나면 줄 바꿈.
 }
}

이것 역시 완벽하지 못한 마방진~ 홀수와 4의 배수 짝수만 된다... 짝수중 4의 배수가 아닌 것은 불가능... 솔직히 시간만 준다면야 못할 껏도 없지만... 하기 싫다... 프로그램의 동작은 얼마만한 크기의 마방진을 만들 것인지 입력 받고 만드는 것이다. 여기서 위에서 말한 안되는 크기를 입력하면 당연히 아무일도 일어 나지 않는다. ㅎㅎ 에러 나던가? ㅋㅋ

반응형

댓글