AI 체스 봇 개발 일지(2일차)

이동민·2023년 9월 1일
0

체스 봇 개발 일지 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 (input == 224)
//		input = _getch();
	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]) {
	
//	Piece _pBoard[10][10] = ChessBoard::_pBoard;
	int team = _pBoard[ay][ax].team;
	int type =_pBoard[ay][ax].type;
	int tmp_B[10][10] = { 0, };	//0 불가능 1 가능 2 어택
	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) {	// White
		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){		// Black
		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;
}	 //complete
int Pa(int team, int ax, int ay, int bx, int by, Piece _pBoard[][10]) {
	if (team == 1) {	// White
		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){		// Black
		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;
}	 //complete

3. 시각자료

4. 마치며

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

0개의 댓글