체스 봇 개발 일지 2일차
2023 09 01
오늘도 저번에 하던 분석을 이어서 할 것이다. 저번에 ChessDisplay 함수를 분석을 했으니 오늘은 GetCommand2 함수 부터 끝까지 분석을 할 것이다. 그럼 오늘도 분석을 시작하겠다.
1. GetCommand2 분석
GetCommand2 는 ChessDisplay에서 현재 체스판 상태를 출력하고 키보드의 입력을 입력 받고 그에 따라 행동하는 함수이다. 여기에 사용된 헤더파일인 Window.h 와 conio.h 는 모두 키보드로부터 입력을 받는 헤더파일이다. Getcommand2 를 선언하기 전 gotoxy 라는 함수를 먼저 선언하는데 이 함수는 커서 이동을 위한 함수이다. 그 다음 Getcommand2 함수를 선언하는데 맨 처음에 ax, ay, bx, by 라는 변수를 만든다. 이 변수들은 기물의 좌표를 저장해주는 함수이다. ax, ay 는 출발 지점의 좌표이고 bx, by 는 도착 지점의 좌표이다. 이 변수들은 MoveTo 함수까지 이어진다. 뒤 코드들은 모드 커서의 이동을 구현한 것이다. 그리고 R(r) 이 입력되면 체스판이 초기화 되도록, Q(q) 가 입력되면 끝나도록 구현이 되어있다.
#include "Board.h"
#include<Windows.h>
#include<conio.h>
using namespace std;
#define UP 72
#define DOWN 80
#define LEFT 75
#define RIGHT 77
#define ENTER 13
#define QUIT 81
#define quit 113
#define RESTART 82
#define restart 114
void gotoXY(int x, int y) {
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos;
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(handle, pos);
}
int ChessBoard::GetCommand2(Piece _pBoard[][10], int* _turn) {
int ax=0, ay=0, bx=0, by=0;
int input = 0;
int x = 3;
int y = 1;
if (*_turn % 2 == 0) {
x = 3;
y = 8;
}
while (input != ENTER) {
gotoXY(x, y);
input = _getch();
if (input == 224)
input = _getch();
switch (input) {
case UP:
if (y > 0)
y--;
break;
case DOWN:
if (y < 10)
y++;
break;
case RIGHT:
if (x < 10*3)
x+=3;
break;
case LEFT:
if (x > 0)
x-=3;
break;
case ENTER:
ax = x / 3;
ay = y;
break;
case RESTART: {
system("cls");
printf("RESTART\n");
*_turn = 1;
Sleep(1000);
system("cls");
ChessBoard RePlay = ChessBoard(_pBoard);
RePlay.ChessDisplay(_pBoard,1);
break;
}
case QUIT:
system("cls");
printf("...Quit The Game...\n");
Sleep(1000);
exit(0);
}
}
input = 0;
while (input != ENTER) {
gotoXY(x, y);
input = _getch();
if (input == 224)
input = _getch();
switch (input) {
case UP:
if (y > 0)
y--;
break;
case DOWN:
if (y < 10)
y++;
break;
case RIGHT:
if (x < 10 * 3)
x += 3;
break;
case LEFT:
if (x > 0)
x -= 3;
break;
case ENTER:
bx = x / 3;
by = y;
break;
case RESTART: {
printf("RESTART\n");
ChessBoard RePlay = ChessBoard(_pBoard);
break;
}
case QUIT:
system("cls");
printf("...Quit The Game...\n");
Sleep(1000);
exit(0);
}
}
return MoveTo(ax,ay,bx,by,_pBoard);
}
2. MoveTo 분석
이 부분이 제일 분석하기 힘들었다. ax, ay 에 있는 즉, 출발 지점에 있는 기물을 종류를 변수에 저장하고 이 변수의 값에 따라 스위치 문으로 기물에 알맞은 함수를 호출하였다. 그리고 각 기물이 움직일 수 있는 경로를 고려하여 함수를 선언하였다. 기물 함수를 보면 0을 리턴 할 때도 있고 1을 리턴 할 때도 있고 2를 리턴 할 때도 있는데 이것이 무엇을 의미하냐면 0은 이동을 실패했다는것을 의미하고 1은 성공 2는 공격을 성공했을 경우를 의미한다. 턴수 증가를 위해 이렇게 경우를 나눠서 리턴을 하는것이다. 폰의 함수를 예시로 보면 첫 이동만 2칸 이동이 가능하고 공격할때는 대각선으로 공격하는 특징을 내포하고 있다. 그리고 또 move 함수가 있는데 이 함수는 이동이 성공했을 경우에만 실행이 된다. ax, ay 를 초기화 하고 bx, by에 ax, ay 에 있던 기구의 정보를 넣는 함수이다.
int Pa(int team, int ax, int ay, int bx, int by,Piece _pBoard[][10]);
int Ro(int team, int ax, int ay, int bx, int by, Piece _pBoard[][10]);
int Kn(int team, int ax, int ay, int bx, int by, Piece _pBoard[][10]);
int Bi(int team, int ax, int ay, int bx, int by, Piece _pBoard[][10]);
int Qu(int team, int ax, int ay, int bx, int by, Piece _pBoard[][10]);
int Ki(int team, int ax, int ay, int bx, int by, Piece _pBoard[][10]);
void gotoXY(int x, int y);
int ChessBoard::MoveTo(int ax, int ay, int bx, int by, Piece _pBoard[][10]) {
int team = _pBoard[ay][ax].team;
int type =_pBoard[ay][ax].type;
int tmp_B[10][10] = { 0, };
gotoXY(0, 13);
if (ax < 1 || ax>8 || bx < 1 || bx>8 || ay < 1 || ay>8 || by < 1 || by>8) {
printf("input error\n");
return 0;
}
switch (type) {
case -1:
printf("empty");
return 0;
break;
case 0:
printf("empty");
return 0;
break;
case 1:
return Pa(team, ax, ay, bx, by,_pBoard);
break;
case 2:
return Ro(team, ax, ay, bx, by, _pBoard);
break;
case 3:
return Kn(team, ax, ay, bx, by, _pBoard);
break;
case 4:
return Bi(team, ax, ay, bx, by, _pBoard);
break;
case 5:
return Qu(team, ax, ay, bx, by, _pBoard);
break;
case 6:
return Ki(team, ax, ay, bx, by, _pBoard);
break;
default:
return 0;
printf(" ");
}
return 0;
}
int Pa(int team, int ax, int ay, int bx, int by, Piece _pBoard[][10]) {
if (team == 1) {
if (_pBoard[by][bx].type > 0) {
if (ay + 1 == by && abs(ax - bx) == 1) {
_move(ax, ay, bx, by, _pBoard);
printf("attack\n");
return 2;
}
}
else if(ay == 2){
if (ax == bx && (by - ay == 1 || (by - ay == 2 && _pBoard[ay + 1][by].type < 1))) {
_move(ax, ay, bx, by, _pBoard);
printf("move\n");
return 1;
}
}
else {
if ((ax == bx && by - ay == 1)) {
_move(ax, ay, bx, by, _pBoard);
printf("move\n");
return 1;
}
}
printf("impossible\n");
return 0;
}
else if(team == 0){
if (_pBoard[by][bx].type > 0) {
if (ay - 1 == by && abs(ax - bx) == 1) {
_move(ax, ay, bx, by, _pBoard);
printf("attack\n");
return 2;
}
}
else if (ay == 7) {
if (ax == bx && (by - ay == -1 || (by - ay == -2 && _pBoard[ay - 1][by].type < 1))) {
_move(ax, ay, bx, by,_pBoard);
printf("move\n");
return 1;
}
}
else {
if ((ax == bx && by - ay == -1)) {
_move(ax, ay, bx, by, _pBoard);
printf("move\n");
return 1;
}
}
printf("impossible\n");
return 0;
}
return 0;
}
int Pa(int team, int ax, int ay, int bx, int by, Piece _pBoard[][10]) {
if (team == 1) {
if (_pBoard[by][bx].type > 0) {
if (ay + 1 == by && abs(ax - bx) == 1) {
_move(ax, ay, bx, by, _pBoard);
printf("attack\n");
return 2;
}
}
else if(ay == 2){
if (ax == bx && (by - ay == 1 || (by - ay == 2 && _pBoard[ay + 1][by].type < 1))) {
_move(ax, ay, bx, by, _pBoard);
printf("move\n");
return 1;
}
}
else {
if ((ax == bx && by - ay == 1)) {
_move(ax, ay, bx, by, _pBoard);
printf("move\n");
return 1;
}
}
printf("impossible\n");
return 0;
}
else if(team == 0){
if (_pBoard[by][bx].type > 0) {
if (ay - 1 == by && abs(ax - bx) == 1) {
_move(ax, ay, bx, by, _pBoard);
printf("attack\n");
return 2;
}
}
else if (ay == 7) {
if (ax == bx && (by - ay == -1 || (by - ay == -2 && _pBoard[ay - 1][by].type < 1))) {
_move(ax, ay, bx, by,_pBoard);
printf("move\n");
return 1;
}
}
else {
if ((ax == bx && by - ay == -1)) {
_move(ax, ay, bx, by, _pBoard);
printf("move\n");
return 1;
}
}
printf("impossible\n");
return 0;
}
return 0;
}
3. 시각자료

4. 마치며
이렇게 2일차에 거쳐서 코드 분석을 마무리를 했다. 이제부터 이 코드에 더 많은 기능들을 추가를 할 것이다. 3일차에는 캐슬링을 구현 할 예정이다.