[μ•Œκ³ λ¦¬μ¦˜ λ¬Έμ œν’€μ΄] TICTACTOE game

2021. 11. 28. 16:06ㆍProgramming/Algorithms

1. 문제

 

ν‹±νƒν† λŠ” 3x3 크기의 κ²Œμž„νŒμ—μ„œ ν•˜λŠ” 3λͺ© κ²Œμž„μž…λ‹ˆλ‹€. 두 λͺ…이 λ²ˆκ°ˆμ•„κ°€λ©° o와 xλ₯Ό κ²Œμž„νŒμ˜ 빈 칸에 μ“°λ˜, λ¨Όμ € 같은 κΈ€μžλ₯Ό κ°€λ‘œ, μ„Έλ‘œ ν˜Ήμ€ λŒ€κ°μ„ μœΌλ‘œ 3개 쓰이도둝 ν•˜λŠ” μͺ½μ΄ μ΄κΉλ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, λ‹€μŒ κ²Œμž„νŒμ€ xκ°€ 이긴 κ²Œμž„νŒμž…λ‹ˆλ‹€.

xoo
.x.
..x

κ²Œμž„μ€ 항상 xλΆ€ν„° μ‹œμž‘ν•©λ‹ˆλ‹€.

틱택토 κ²Œμž„νŒμ˜ ν˜„μž¬ μƒνƒœκ°€ μ£Όμ–΄μ§‘λ‹ˆλ‹€. 두 μ‚¬λžŒ λͺ¨λ‘ μ΅œμ„ μ„ λ‹€ν•œλ‹€κ³  κ°€μ •ν•  λ•Œ, μ–΄λŠμͺ½μ΄ 이길지 νŒλ‹¨ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ„Έμš”.

 

 

 

 

2. 풀이

 

/*

- canWin(board) : 
κ²Œμž„νŒμ΄ ν˜„μž¬ board일 λ•Œ, 이번 차둀인 μ‚¬λžŒμ΄ 
이길 수 μžˆλ‹€λ©΄ 1,
λΉ„κΈΈ 수 μžˆλ‹€λ©΄ 0,
질 수 밖에 μ—†λ‹€λ©΄ -1을 λ°˜ν™˜ν•œλ‹€.

+ boardλ₯Ό 아홉 자리의 3μ§„μˆ˜λ‘œ λ³Έλ‹€.

- ν•¨μˆ˜μ˜ λ°˜ν™˜ κ°’ 쀑 -1이 μžˆμœΌλ―€λ‘œ,
cache[]λ₯Ό -2둜 μ΄ˆκΈ°ν™”ν•΄μ•Όν•œλ‹€. 

- canWin()에 ν˜„μž¬ κ²Œμž„νŒ 상황과 λ”λΆˆμ–΄ λˆ„κ΅¬ 차둀인지λ₯Ό turn으둜 μ „λ‹¬ν•œλ‹€. 

- canWin()은 λͺ¨λ“  수λ₯Ό μ‹œλ„ν•˜λ©°, λ°˜ν™˜ κ°’ 쀑 κ°€μž₯ μž‘μ€ 것을 μ°ΎλŠ”λ‹€. 
: μ–΄λ–€ 수λ₯Ό λ‘μ—ˆμ„ λ•Œ, -1이 λ°˜ν™˜λœλ‹€λ©΄ λ‚΄κ°€ 이길 수 μžˆλ‹€λŠ” 뜻이고
  -1 없이 0이 μžˆλ‹€λ©΄ 0이 μžˆλ‹€λ©΄ λΉ„κΈΈ 수 μžˆλ‹€λŠ” λœ»μ΄λ‹€. 

*/



bool isFinished(const vector<string>& board, char turn);
// turn이 ν•œ 쀄을 λ§Œλ“€μ—ˆλŠ”μ§€ ν™•μΈν•œλ‹€.


/*

bijection (전단사 ν•¨μˆ˜)
: 두 집합 사이λ₯Ό 쀑볡 없이 λͺ¨λ‘ μΌλŒ€μΌλ‘œ λŒ€μ‘μ‹œν‚€λŠ” ν•¨μˆ˜, μΌλŒ€μΌ λŒ€μ‘.
: κ²Œμž„νŒ(board)κ°€ μ£Όμ–΄μ‘Œμ„ λ•Œ, [0 ~ 19682 ~=3^9 ] λ²”μœ„μ˜ μ •μˆ˜λ‘œ λ³€ν™˜ν•œλ‹€. 

*/

int bijection(const vector <string>&board) {
	int ret = 0;
	for (int y = 0; y < 3; ++y) {
		for (int x = 0; x < 3; ++x) {
			ret = ret * 3;
			if (board[y][x] == 'o') {
				++ret;
			}
			else if (board[y][x] == 'x') {
				ret += 2;
			}
		}
	}
	return ret;
}


 
int cache[19683];
int canWin(vector<string>& board, char turn) {
	// board μš”μ†Œ λ³€ν™˜μ΄ 있기 λ•Œλ¬Έμ—, const μ„ μ–ΈX

	if (isFinished(board, 'o' + 'x' - turn) == true ) {
		return -1;
		// 기저사둀: λ§ˆμ§€λ§‰μ— μƒλŒ€κ°€ 두어 ν•œ 쀄이 λ§Œλ“€μ–΄μ§„ 경우 -> -1 λ°˜ν™˜
		// λ‚΄κ°€ x이면 input parameter이 o, λ‚΄κ°€ o이면 input parameter이 x! 
	}

	int& ret = cache[bijection(board)];
	if (ret != -2) {
		return ret;
	}

	int minValue = 2;
	for (int y = 0; y < 3; ++y) {
		for (int x = 0; x < 3; ++x) {
			if (board[y][x] == '.') {
				board[y][x] = turn;
				// 빈 칸에 λ‚˜μ˜ 수λ₯Ό λ‘μ—ˆμ„ λ•Œ, κ²°κ³Όλ₯Ό μž„μ‹œλ‘œ λ„μΆœν•΄λ³Έλ‹€.
				// λ°˜λ³΅λ¬Έμ„ ν†΅ν•˜μ—¬ 9가지 경우의 수 λͺ¨λ‘ μˆœνšŒν•˜λ©° νŒλ³„ν•œλ‹€. 
				minValue = min(minValue, canWin(board, 'o' + 'x' - turn));
				board[y][x] = '.';
				// λ‹€μ‹œ 되돌렀 λ†“λŠ” κ³Όμ •!
			}
		}
	}

	if (minValue == 2 || minValue == 0) {
		return ret = -minValue;
		// ν”Œλ ˆμ΄ ν•  수 μ—†κ±°λ‚˜, λΉ„κΈ°λŠ” 것이 μ΅œμ„ μΈ 경우 
		// μƒλŒ€κ°€ μ΄κΈ°λŠ” 것 -> λ‚΄κ°€ μ§€λŠ” 것
	}
}

 

 

 

 

 

3. impartial game 

 

In combiantional game theory, an impartial game is a game in which the allowable moves depend

only on the position and not on which of the two players is currently moving, and where the payoffs are symmetric.

the only difference between player 1 and player 2 is that player 1 goes first.

The game is played until a terminal position is reached.

A terminal position is one from which no moves are possible.

Then one of the players is declared the winner and the other the loser.

Furthermore, impartial games are played with perfect information and no chance moves, meaning all information about the game and operations for both players are visible to both players.

 

 

 

 

 

4. git-hub

 

- https://github.com/SohyeonKim-dev/AlgorithmicProblem/blob/main/DynamicProgramming_technique/tictactoe.cpp 

 

 

 

 

 

5. 좜처

- https://www.algospot.com/judge/problem/read/TICTACTOE