◈ 이 글은 강의를 위하여 제가 직접 작성한 내용입니다. 따라서 퍼가실 경우, 출처를 명확히 해주시기 바랍니다!!
◈ This ariticle was written by me for teaching. So if you want to copy this article, please clarify the source!!
◈ This ariticle was written by me for teaching. So if you want to copy this article, please clarify the source!!
2011/01/18 - [강의자료/C/C++] - 054. 오목 프로그램을 작성하자.
(1) 바둑알 위치를 좌표로 입력받는 기존의 형식에 추가하여 화살표로 이동하고 스페이스바로 입력할 수 있도록 기능을 추가한다.
-- (현재 위치를 의미하는 커서 문자는 ☞를 사용한다.)
-- (기본 입력모드는 화살표 모드로 진행하되, 'I'키를 누르면 좌표입력모드로 변경되게 한다.)
(2) 입력모드 중에 ESC키를 누르면 게임을 바로 종료할 수 있는 기능을 추가한다.
(3) 바둑판 그림 옆에 아래 출력화면과 같이 게임에 관한 정보를 출력한다.
(4) 그 외 출력 메시지는 오른쪽 출력화면 아래부분에 출력되도록 작성한다.
(1) 바둑알 위치를 좌표로 입력받는 기존의 형식에 추가하여 화살표로 이동하고 스페이스바로 입력할 수 있도록 기능을 추가한다.
-- (현재 위치를 의미하는 커서 문자는 ☞를 사용한다.)
-- (기본 입력모드는 화살표 모드로 진행하되, 'I'키를 누르면 좌표입력모드로 변경되게 한다.)
(2) 입력모드 중에 ESC키를 누르면 게임을 바로 종료할 수 있는 기능을 추가한다.
(3) 바둑판 그림 옆에 아래 출력화면과 같이 게임에 관한 정보를 출력한다.
(4) 그 외 출력 메시지는 오른쪽 출력화면 아래부분에 출력되도록 작성한다.
/* (1) 바둑알 위치를 좌표로 입력받는 기존의 형식에 추가하여 화살표로 이동하고 스페이스바로 입력할 수 있도록 기능을 추가한다. -- (현재 위치를 의미하는 커서 문자는 ☞를 사용한다.) -- (기본 입력모드는 화살표 모드로 진행하되, 'I'키를 누르면 좌표입력모드로 변경되게 한다.) (2) 입력모드 중에 ESC키를 누르면 게임을 바로 종료할 수 있는 기능을 추가한다. (3) 바둑판 그림 옆에 아래 출력화면과 같이 게임에 관한 정보를 출력한다. (4) 그 외 출력 메시지는 오른쪽 출력화면 아래부분에 출력되도록 작성한다. */ //------------------------------------------------------------------------------- // 헤더파일 선언. //------------------------------------------------------------------------------- #include#include #include using namespace std; //------------------------------------------------------------------------------- // 매크로. //------------------------------------------------------------------------------- #define KEY_NONE 0 #define KEY_ARROW 224 #define KEY_UP 72 #define KEY_LEFT 75 #define KEY_RIGHT 77 #define KEY_DOWN 80 #define KEY_RETURN 13 #define KEY_SPACE 32 #define KEY_ESC 27 #define KEY_BACK 8 #define BOARD_SIZE 19 #define PLAYER_NUM 2 //------------------------------------------------------------------------------- // 오목 클래스 선언. //------------------------------------------------------------------------------- class FiveRow { private: int pieceList[BOARD_SIZE][BOARD_SIZE]; char pieceFigure[3][3]; int player; // 플레이어의 순서.(0 : 노 메시지, 1 : 플레이어1차례, 2 : 플레이어2차례, 3 : 플레이어1승리, 4 : 플레이어2승리) int posX; // 사용자 입력 좌표. int posY; bool pressESC; public: FiveRow() { strcpy_s(pieceFigure[0], _countof(pieceFigure[0]), "╋"); strcpy_s(pieceFigure[1], _countof(pieceFigure[1]), "●"); strcpy_s(pieceFigure[2], _countof(pieceFigure[2]), "○"); } private: void InitGame(); void DisplayBoard(char* str = NULL); bool InputKey(int player); bool InputArrow(); bool InputNumber(); bool CheckFiveRow(int player); bool Ask_Yes_or_No(char* query) { if(query) cout << query << " (Y/N)"; char yes_or_no = _getch(); if(yes_or_no == 'y' || yes_or_no == 'Y') return true; return false; } void ChangePlayer() { player++; if(player > PLAYER_NUM) player = 1; } public: void SetStone(int num, char* figure); void Run(); }; void FiveRow::SetStone( int num, char* figure ) { if(num > 0 && num <= PLAYER_NUM) strcpy_s(pieceFigure[num], _countof(pieceFigure[num]), figure); } void FiveRow::InitGame() { player = 1; posX = 1; posY = 1; pressESC = false; memset(pieceList, 0, sizeof(pieceList)); } void FiveRow::DisplayBoard( char* str ) { // 화면을 지운다. system("cls"); // 바둑판 위쪽 가장자리를 그린다. cout << endl << "┏"; for(int i=0;i < BOARD_SIZE;i++) cout << "┳"; cout << "┓" << endl; // 바둑판 내부를 그린다. // 바둑알이 있다면 바둑알을 그린다. for(int y=0; y < BOARD_SIZE; y++) { // 바둑판 왼쪽 가장자리를 그린다. cout << "┣" ; // 바둑판 안쪽을 그려준다. for(int x=0; x < BOARD_SIZE; x++) { // 현재 커서부분은 손을 그려준다. && 게임이 진행중이라면, if( (x == posX-1 && y == posY-1) && (player <= PLAYER_NUM) ) cout << "☞"; else cout << pieceFigure[ pieceList[y][x] ]; } // 바둑판 오른쪽 가장자리를 그린다. cout << "┫"; // 바둑판 Y좌표를 나타낸다. cout << setw(2) << y+1; // 안내문구를 출력시킨다. if(y == 0) cout << "┌───────────────┐"; else if(y == 1) { cout << "│ Player 1 : " << pieceFigure[1]; cout << " Player 2 : " << pieceFigure[2] << " │"; } else if(y == 2) cout << "└───────────────┘"; else if(y == 3) cout << "┌───────────────┐"; else if(y == 4) cout << "│ >> 화살표키로 이동 후 │"; else if(y == 5) cout << "│ [SPACE BAR]를 누르세요!! │"; else if(y == 6) cout << "│ │"; else if(y == 7) cout << "│ >> 좌표입력을 원하시면 │"; else if(y == 8) cout << "│ [I]를 누르세요!! │"; else if(y == 9) cout << "│ │"; else if(y == 10) cout << "│ >> 프로그램을 종료하시려면 │"; else if(y == 11) cout << "│ [ESC]를 누르세요!! │"; else if(y == 12) cout << "└───────────────┘"; else if(y == 13) cout << "┌───────────────┐"; else if(y == 14) cout << "│ Player " << (player <= PLAYER_NUM ? player : player-PLAYER_NUM) << (player <= PLAYER_NUM ? " 의 차례입니다. │" : "이(가) 이겼습니다. │"); else if(y == 15) cout << "└───────────────┘"; else if(y == 16) if(str != NULL) cout << str; // 다음 라인으로 바꾼다. cout << endl; } // 바둑판 아랫쪽 가장자리를 그린다. cout << "┗"; for(int i=0; i < BOARD_SIZE; i++) cout << "┻"; cout << "┛" << endl; // 바둑판 X좌표를 나타낸다. cout << " "; for(int x=0; x < BOARD_SIZE; x++) cout << setw(2) << x+1; cout << endl; // setw(2) -> printf("%2d",y+1); } bool FiveRow::InputArrow() { // keyInput 변수를 초기화한다. int keyInput = KEY_NONE; // 화살표키로 입력받는다. while(true) { keyInput = _getch(); // 화살표키를 눌렀을 경우, if(keyInput == KEY_ARROW) { // 확장코드를 읽어서 무슨 키인지 판별한다. keyInput = _getch(); // 키에 따라 좌표를 제어한다. if(keyInput == KEY_UP) posY-1 < 1 ? posY : posY--; else if(keyInput == KEY_DOWN) posY+1 > BOARD_SIZE ? posY : posY++; else if(keyInput == KEY_LEFT) posX-1 < 1 ? posX : posX--; else if(keyInput == KEY_RIGHT) posX+1 >BOARD_SIZE ? posX :posX++; // 화면을 갱신한다. DisplayBoard(); } // SpaceBar를 눌렀을 경우, 돌을 놓은 것으로 간주하고 함수를 종료한다. else if(keyInput == KEY_SPACE) return true; // ESC키를 눌렀을 경우, 프로그램을 종료한다. else if(keyInput == KEY_ESC) { pressESC = true; return false; } // I를 눌렀을 경우, 좌표를 직접 입력할 수 있도록 루프를 벗어난다. else if(keyInput == 'I' || keyInput == 'i') return false; // 이외의 키를 눌렀을 경우, 안내메시지를 출력한다. else DisplayBoard(" >> 잘못 누르셨습니다."); } } bool FiveRow::InputNumber() { int keyInput = KEY_NONE; for(int i=0; i < 2; i++) { int& pos = (i==0)?this->posX:this->posY; int backup = pos; pos = 0; // 좌표 초기화. while(true) { char msg[64]; char coord = (i==0)?'X':'Y'; sprintf_s(msg, _countof(msg), " >> %c좌표를 입력(1-%d) : ", coord, BOARD_SIZE); if(pos != 0) sprintf_s(msg, _countof(msg), "%s%d", msg, pos); if(i == 1) sprintf_s(msg, _countof(msg), "%s (X:%d)", msg, posX); DisplayBoard(msg); // 키 입력. keyInput = _getch(); // ESC키를 눌렀을 경우, 프로그램을 종료한다. if(keyInput == KEY_ESC) { pressESC = true; pos = backup; return false; } // Return키를 입력했을 경우, else if(keyInput == KEY_RETURN) { // 좌표의 범위가 정상적일 경우, if(1 <= pos && pos <= BOARD_SIZE) { break; // for()문을 한번 더 돌아야 한다. } else { DisplayBoard(" >> 잘못 입력하였습니다."); pos = 0; _getch(); // 화면을 잠시 멈춘다. } } // 숫자키를 눌렀을 경우, 자리수를 변경해가며 숫자를 맞춰나간다. // '0' -> 48, '1' -> 49, '9' ->57 else if('0' <= keyInput && keyInput <= '9') { pos = (pos*10) + (keyInput-'0'); } // <-키를 눌렀을 경우, 한자리씩 지운다. else if(keyInput == KEY_BACK) { pos /= 10; } else { DisplayBoard(" >> 잘못 입력하였습니다."); pos = 0; _getch(); // 화면을 잠시 멈춘다. } } } return true; } bool FiveRow::InputKey(int player) { if(InputArrow() == false) { if(pressESC) return false; if(InputNumber() == false) return false; } if(pieceList[posY-1][posX-1] == 0) // 바둑알이 없을 경우, { pieceList[posY-1][posX-1] = player; return true; } else { return false; } } void FiveRow::Run() { InitGame(); DisplayBoard(); // 바둑판을 보여준다. while(true) { if(InputKey(player)) // 키입력을 받는다. { if (CheckFiveRow(player)) // 오목이 성립되었는지를 체크한다. 성립되었다면, { player += PLAYER_NUM; // 턴을 끝내고 승리메시지를 출력하기 위해 상태값을 바꾼다. while(true) { DisplayBoard(" >> Enter키를 누르세요."); int inputOK = _getch(); if(inputOK == KEY_RETURN) break; } DisplayBoard(" >> 게임을 더 하시겠습니까? (Y/N)"); if(Ask_Yes_or_No(NULL)) { InitGame(); DisplayBoard(); continue; } else { break; } } else // 오목이 성립되지 않았다면, { ChangePlayer(); DisplayBoard(); // 바둑판을 갱신한다. } } else { if(pressESC) { DisplayBoard(" >> 게임을 종료하시겠습니까? (Y/N)"); if(Ask_Yes_or_No(NULL)) { break; } else { pressESC = false; DisplayBoard(); continue; } } else { DisplayBoard(" >> 돌이 놓여져 있습니다."); // 바둑판을 갱신한다. } } } } bool FiveRow::CheckFiveRow( int player ) { // 연속된 바둑알의 개수. // 현재 위치에 이미 돌이 놓여 있으므로 1을 초기값으로 준다. int sequenceNum = 1; // 현재 위치에서 가로, 세로, 대각선까지 총 4방향에 대해 오목성립을 체크한다. for(int check=1; check <= 8; check++) { int signX = 0; int signY = 0; if(check == 1) signX = 1, signY = 0; // 가로 + 방향 else if(check == 2) signX = -1, signY = 0; // 가로 - 방향 else if(check == 3) signX = 0, signY = 1; // 세로 + 방향 else if(check == 4) signX = 0, signY = -1; // 세로 - 방향 else if(check == 5) signX = 1, signY = 1; // 대각선 315도 방향 else if(check == 6) signX = -1, signY = -1; // 대각선 135도 방향 else if(check == 7) signX = 1, signY = -1; // 대각선 45도 방향 else if(check == 8) signX = -1, signY = 1; // 대각선 225도 방향 // 각 방향의 처음에만 시퀀스를 초기화 한다. if(check%2 == 1) sequenceNum = 1; // 체크할 위치의 오프셋. int offset = 0; while(true) { // 다음 위치의 돌을 체크한다. offset++; // 체크할 위치 계산. int checkPosX = posX + offset*signX; int checkPosY = posY + offset*signY; // 바둑판의 끝에 도달하면 현재 방향에 대해서는 더이상 체크하지 않는다. if( checkPosX < 1 || checkPosX > BOARD_SIZE ) break; if( checkPosY < 1 || checkPosY > BOARD_SIZE ) break; // 같은 바둑알이 있으면 1증가. if( pieceList[checkPosY-1][checkPosX-1] == player ) sequenceNum++; // 없으면 체크 종료. else break; // 오목이 성립하면 함수 종료. if(sequenceNum == 5) return true; } } return false; } //------------------------------------------------------------------------------- // 함수 선언. //------------------------------------------------------------------------------- void DisplayTitle(); // 타이틀을 보여준다. //------------------------------------------------------------------------------- // 메인 함수. //------------------------------------------------------------------------------- void main() { DisplayTitle(); FiveRow game; game.SetStone(1, "☆"); game.SetStone(2, "★"); game.Run(); } //------------------------------------------------------------------------------- // DisplayTitle() // 타이틀을 표시한다. //------------------------------------------------------------------------------- void DisplayTitle() { system("cls"); cout << endl; cout << " ┏★˚━━━━━━━━━━━━━━━━━━━━♡┓" << endl; cout << " ┃ 오목 (Five Row) ┃" << endl; cout << " ┃ ┃" << endl; cout << " ┃ 제 작 일 : 2000-00-00 ┃" << endl; cout << " ┃ 만 든 이 : 이항복 ┃" << endl; cout << " ┃ 이 메 일 : master@uzoo.in ┃" << endl; cout << " ┃ 소 속 : MBC아카데미디지털교육원 ┃" << endl; cout << " ┃ 만든목적 : C/C++ 기초 활용 교육용 ┃" << endl; cout << " ┃ ┃" << endl; cout << " ┃ ▼~~~~~ 나는야~ ┃" << endl; cout << " ┃ *.┏┓ 부디 저희를 ▶⊙◀~~ 천상천하!!┃" << endl; cout << " ┃ ┏┻┫ 거둬주세요~!! ▲~~~ 유아독존!! ┃" << endl; cout << " ┃ ┃━┫ ○ ● \● 푸 ┃" << endl; cout << " ┃ ┃━┫ ┏■┛┏□┛ /> 하 ┃" << endl; cout << " ┃ ┗━┛ ┛┓ ┛┓ 〈\ 하 ┃" << endl; cout << " ┃ ~★" << endl; cout << " ♡˚━○━━━━━━━━━━━━━━━━━━━━┛" << endl; cout << " ┏*******┓" << endl; cout << " ┃ こ ご ┃ \"게임을 시작하고 싶은가??\"" << endl; cout << " ┃...^...┃ \"그럼 아무키나 눌러보게나...후훗..!!\"" << endl; cout << " ~~~~~~~~~~~" << endl; system("pause"); system("cls"); }
수정전 임시 코드
//------------------------------------------------------------------------------- // 헤더파일 선언. //------------------------------------------------------------------------------- #include#include #include using namespace std; //------------------------------------------------------------------------------- // 매크로. //------------------------------------------------------------------------------- #define KEY_NONE 0 #define KEY_ARROW 224 #define KEY_UP 72 #define KEY_LEFT 75 #define KEY_RIGHT 77 #define KEY_DOWN 80 #define KEY_RETURN 13 #define KEY_SAPCE 32 #define KEY_ESC 27 #define KEY_BACK 8 //------------------------------------------------------------------------------- // 오목 클래스 선언. //------------------------------------------------------------------------------- class FiveRow { private: const static int boardSize = 19; const static int eggSize = 3; int pieceList[boardSize][boardSize]; // 바둑알 배열. int playerNum; // 플레이어 수. char** pieceFigure; // 바둑알 모양. int posX; // 사용자 입력 좌표. int posY; int whoseTurn; // 플레이어의 순서.(0 : 노 메시지, 1 : 플레이어1차례, 2 : 플레이어2차례, 3 : 플레이어1승리, 4 : 플레이어2승리) bool pressESC; public: FiveRow(int playerNum): playerNum(playerNum), pieceFigure(NULL) { // 바둑알 배열 생성.(+1 : "╋"도 바둑알로 표현.) pieceFigure = new char*[playerNum+1]; // 바둑알 모양 초기화. for(int i=0; i < playerNum+1; i++) { pieceFigure[i] = new char[eggSize]; } strcpy_s(pieceFigure[0], eggSize, "╋"); InitGame(); } ~FiveRow() { for(int i=0; i < playerNum+1; i++) { delete [] pieceFigure[i]; } delete [] pieceFigure; } private: void InitGame(); bool InputKey(int player); bool InputArrow(); bool InputNumber(); void DisplayBoard(char* str); bool CheckFiveRow(int player); bool CheckPieceFigure(); public: void InitPiece(int num, char* figure); void Run(); }; void FiveRow::InitPiece( int num, char* figure ) { if(num > 0 && num <= playerNum) { strcpy_s(pieceFigure[num], eggSize, figure); } } void FiveRow::InitGame() { posX = 1; posY = 1; whoseTurn = 1; pressESC = false; // boardSize X boardSize 크기의 바둑판을 초기화한다. memset(pieceList, 0, sizeof(pieceList)); } bool FiveRow::InputArrow() { // keyInput 변수를 초기화한다. int keyInput = KEY_NONE; // 화살표키로 입력받는다. while(true) { keyInput = _getch(); // 화살표키를 눌렀을 경우, if(keyInput == KEY_ARROW) { // 확장코드를 읽어서 무슨 키인지 판별한다. keyInput = _getch(); // 키에 따라 좌표를 제어한다. if(keyInput == KEY_UP) posY-1 < 1 ? posY : posY--; else if(keyInput == KEY_DOWN) posY+1 > boardSize ? posY : posY++; else if(keyInput == KEY_LEFT) posX-1 < 1 ? posX : posX--; else if(keyInput == KEY_RIGHT) posX+1 >boardSize ? posX :posX++; // 화면을 갱신한다. DisplayBoard(); } // SpaceBar를 눌렀을 경우, 돌을 놓은 것으로 간주하고 함수를 종료한다. else if(keyInput == KEY_SAPCE) return true; // ESC키를 눌렀을 경우, 프로그램을 종료한다. else if(keyInput == KEY_ESC) { pressESC = true; return false; } // I를 눌렀을 경우, 좌표를 직접 입력할 수 있도록 루프를 벗어난다. else if(keyInput == 'I' || keyInput == 'i') return false; // 이외의 키를 눌렀을 경우, 안내메시지를 출력한다. else DisplayBoard(" >> 잘못 누르셨습니다."); } } bool FiveRow::InputNumber() { int keyInput = KEY_NONE; for(int i=0; i < 2; i++) { int& pos = (i==0)?this->posX:this->posY; int backup = pos; pos = 0; // 좌표 초기화. while(true) { char msg[32]; char coord = (i==0)?'X':'Y'; sprintf_s(msg, _countof(msg), " >> %c좌표를 입력(1-%d) : ", coord, boardSize); DisplayBoard(msg); // 키 입력. keyInput = _getch(); // ESC키를 눌렀을 경우, 프로그램을 종료한다. if(keyInput == KEY_ESC) { pressESC = true; pos = backup; return false; } // Return키를 입력했을 경우, else if(keyInput == KEY_RETURN) { // 좌표의 범위가 벗어났을 경우, if(pos < 1 || pos > boardSize) { DisplayBoard(" >> 잘못 입력하였습니다."); pos = 0; _getch(); } // 좌표의 범위가 정상적일 경우, else { break; // for()문을 한번 더 돌아야 한다. } } // 숫자키를 눌렀을 경우, 자리수를 변경해가며 숫자를 맞춰나간다. // temp-48 -> 1의 아스키코드 값이 49이므로... else if(keyInput >= 48 && keyInput <= 57) { pos = (pos*10) + (keyInput-48); } // <-키를 눌렀을 경우, 한자리씩 지운다. else if(keyInput == KEY_BACK) { pos /= 10; } else { DisplayBoard(" >> 잘못 입력하였습니다."); pos = 0; _getch(); } } } return true; } bool FiveRow::InputKey(int player) { if(InputArrow() == false) { if(pressESC) return false; if(InputNumber() == false) return false; } if(pieceList[posY-1][posX-1] == 0) // 바둑알이 없을 경우, { pieceList[posY-1][posX-1] = whoseTurn; return true; } else { return false; } } void FiveRow::DisplayBoard( char* str ) { // 화면을 지운다. system("cls"); // 바둑판 위쪽 가장자리를 그린다. cout << endl << "┏"; for(int i=0;i < boardSize;i++) cout << "┳"; cout << "┓" << endl; // 바둑판 내부를 그린다. // 바둑알이 있다면 바둑알을 그린다. int printedPlayer = 1; for(int y=0; y < boardSize; y++) { // 바둑판 왼쪽 가장자리를 그린다. cout << "┣" ; // 바둑판 안쪽을 그려준다. for(int x=0; x < boardSize; x++) { // 현재 커서부분은 손을 그려준다. && 게임이 진행중이라면, if( (x == posX-1 && y == posY-1) && (whoseTurn <= playerNum) ) cout << "☞"; else { cout << pieceFigure[ pieceList[y][x] ]; } } // 바둑판 오른쪽 가장자리를 그린다. cout << "┫"; // 바둑판 Y좌표를 나타낸다. cout << setw(2) << y+1; // 안내문구를 출력시킨다. // 0.5f를 더한 이유 : 플레이어 인원수가 홀수명일 경우 반올림 하기 위해서. int playerline = int(playerNum/2.0f + 0.5f); if(y == 0) cout << "┌───────────────┐"; else if(y <= playerline) { cout << "│ Player " << printedPlayer << " : " << pieceFigure[printedPlayer]; printedPlayer++; if(printedPlayer <= playerNum) { cout << " Player " << printedPlayer << " : " << pieceFigure[printedPlayer] << " │"; printedPlayer++; } else { cout << " │"; } } else if(y == 1+playerline) cout << "└───────────────┘"; else if(y == 2+playerline) cout << "┌───────────────┐"; else if(y == 3+playerline) cout << "│ >> 화살표키로 이동 후 │"; else if(y == 4+playerline) cout << "│ [SPACE BAR]를 누르세요!! │"; else if(y == 5+playerline) cout << "│ │"; else if(y == 6+playerline) cout << "│ >> 좌표입력을 원하시면 │"; else if(y == 7+playerline) cout << "│ [I]를 누르세요!! │"; else if(y == 8+playerline) cout << "│ │"; else if(y == 9+playerline) cout << "│ >> 프로그램을 종료하시려면 │"; else if(y == 10+playerline) cout << "│ [ESC]를 누르세요!! │"; else if(y == 11+playerline) cout << "└───────────────┘"; // 턴 또는 승리를 표시한다. else if(y == 12+playerline) cout << "┌───────────────┐"; else if(y == 13+playerline) cout << "│ Player " << (whoseTurn <= playerNum ? whoseTurn : whoseTurn-playerNum) << (whoseTurn <= playerNum ? " 의 차례입니다. │" : "이(가) 이겼습니다. │"); else if(y == 14+playerline) cout << "└───────────────┘"; // 인자로 들어온 문자열을 출력한다. else if(y == 15+playerline) if(str != NULL) { cout << str; if( str[4] == 'X' ) if(posX != 0) cout << posX; if( *(str+4) == 'Y' ) {if(posY != 0) cout << posY; cout << " (X:" << posX << ")";} } // 다음 라인으로 바꾼다. cout << endl; } // 바둑판 아랫쪽 가장자리를 그린다. cout << "┗"; for(int i=0; i < boardSize; i++) cout << "┻"; cout << "┛" << endl; // 바둑판 X좌표를 나타낸다. cout << " "; for(int x=0; x < boardSize; x++) cout << setw(2) << x+1; cout << endl; // setw(2) -> printf("%2d",y+1); } bool FiveRow::CheckFiveRow( int player ) { // 연속된 바둑알의 개수. // 현재 위치에 이미 돌이 놓여 있으므로 1을 초기값으로 준다. int sequenceNum = 1; // 현재 위치에서 가로, 세로, 대각선까지 총 4방향에 대해 오목성립을 체크한다. for(int check=1; check <= 8; check++) { int signX = 0; int signY = 0; if(check == 1) signX = 1, signY = 0; // 가로 + 방향 else if(check == 2) signX = -1, signY = 0; // 가로 - 방향 else if(check == 3) signX = 0, signY = 1; // 세로 + 방향 else if(check == 4) signX = 0, signY = -1; // 세로 - 방향 else if(check == 5) signX = 1, signY = 1; // 대각선 315도 방향 else if(check == 6) signX = -1, signY = -1; // 대각선 135도 방향 else if(check == 7) signX = 1, signY = -1; // 대각선 45도 방향 else if(check == 8) signX = -1, signY = 1; // 대각선 225도 방향 // 각 방향의 처음에만 시퀀스를 초기화 한다. if(check%2 == 1) sequenceNum = 1; // 체크할 위치의 오프셋. int offsetX = 0; int offsetY = 0; while(true) { // 다음 위치의 돌을 체크한다. offsetX++; offsetY++; // 체크할 위치 계산. int checkPosX = posX + offsetX*signX; int checkPosY = posY + offsetY*signY; // 바둑판의 끝에 도달하면 현재 방향에 대해서는 더이상 체크하지 않는다. if( checkPosX > boardSize || checkPosX < 1 ) break; if( checkPosY > boardSize || checkPosY < 1 ) break; // 같은 바둑알이 있으면 1증가. if( pieceList[checkPosY-1][checkPosX-1] == player ) sequenceNum++; // 없으면 체크 종료. else break; // 오목이 성립하면 함수 종료. if(sequenceNum == 5) return true; } } return false; } bool FiveRow::CheckPieceFigure() { bool hasAllFigure = true; for(int i=1; i <= playerNum; i++) { if(pieceFigure[i] == NULL) { cout << "플레이어 " << i << "의 바둑알이 정의되지 않았습니다." << endl; hasAllFigure = false; } } return hasAllFigure; } void FiveRow::Run() { // 플레이어의 바둑알의 모양이 모두 설정되어있지 않으면 종료한다. if(CheckPieceFigure() == false) return; char moregame; DisplayBoard(); // 바둑판을 보여준다. while(true) { if(InputKey(whoseTurn)) // 키입력을 받는다. { if (CheckFiveRow(whoseTurn)) // 오목이 성립되었는지를 체크한다. 성립되었다면, { whoseTurn += playerNum; // 턴을 끝내고 승리메시지를 출력하기 위해 상태값을 바꾼다. while(true) { DisplayBoard(" >> Enter키를 누르세요."); int inputOK = _getch(); if(inputOK == KEY_RETURN) break; } DisplayBoard(" >> 게임을 더 하시겠습니까? (Y/N)"); moregame = _getch(); // 게임을 더 할 것인지 입력을 받는다. if(moregame == 'y' || moregame == 'Y') { InitGame(); DisplayBoard(); continue; } else { break; } } else // 오목이 성립되지 않았다면, { whoseTurn++; // 다음 플레이어에게 턴을 넘긴다. if(whoseTurn > playerNum) whoseTurn = 1; DisplayBoard(); // 바둑판을 갱신한다. } } else { if(pressESC) { DisplayBoard(" >> 게임을 종료하시겠습니까? (Y/N)"); moregame = _getch(); if(moregame == 'y' || moregame == 'Y') { break; } else { pressESC = false; DisplayBoard(); continue; } } else { DisplayBoard(" >> 돌이 놓여져 있습니다."); // 바둑판을 갱신한다. } } } } //------------------------------------------------------------------------------- // 함수 선언. //------------------------------------------------------------------------------- void DisplayTitle(); // 타이틀을 보여준다. //------------------------------------------------------------------------------- // 메인 함수. //------------------------------------------------------------------------------- void main() { DisplayTitle(); FiveRow game(4); game.InitPiece(1, "●"); game.InitPiece(2, "○"); game.InitPiece(3, "★"); game.InitPiece(4, "☆"); game.Run(); } //------------------------------------------------------------------------------- // DisplayTitle() // 타이틀을 표시한다. //------------------------------------------------------------------------------- void DisplayTitle() { system("cls"); cout << endl; cout << " ┏★˚━━━━━━━━━━━━━━━━━━━━♡┓" << endl; cout << " ┃ 오목 (Five Row) ┃" << endl; cout << " ┃ ┃" << endl; cout << " ┃ 제 작 일 : 2000-00-00 ┃" << endl; cout << " ┃ 만 든 이 : 이항복 ┃" << endl; cout << " ┃ 이 메 일 : master@uzoo.in ┃" << endl; cout << " ┃ 소 속 : MBC아카데미디지털교육원 ┃" << endl; cout << " ┃ 만든목적 : C/C++ 기초 활용 교육용 ┃" << endl; cout << " ┃ ┃" << endl; cout << " ┃ ▼~~~~~ 나는야~ ┃" << endl; cout << " ┃ *.┏┓ 부디 저희를 ▶⊙◀~~ 천상천하!!┃" << endl; cout << " ┃ ┏┻┫ 거둬주세요~!! ▲~~~ 유아독존!! ┃" << endl; cout << " ┃ ┃━┫ ○ ● \● 푸 ┃" << endl; cout << " ┃ ┃━┫ ┏■┛┏□┛ /> 하 ┃" << endl; cout << " ┃ ┗━┛ ┛┓ ┛┓ 〈\ 하 ┃" << endl; cout << " ┃ ~★" << endl; cout << " ♡˚━○━━━━━━━━━━━━━━━━━━━━┛" << endl; cout << " ┏*******┓" << endl; cout << " ┃ こ ご ┃ \"게임을 시작하고 싶은가??\"" << endl; cout << " ┃...^...┃ \"그럼 아무키나 눌러보게나...후훗..!!\"" << endl; cout << " ~~~~~~~~~~~" << endl; system("pause"); system("cls"); }