기술 블로그

틱택토(TICTACTOE) 본문

알고리즘 문제/AlgoSpot

틱택토(TICTACTOE)

parkit 2019. 1. 8. 01:25
728x90
반응형

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


책을 보아도, 복잡했다.


갑자기 return 값에 -1이 곱해지는 경우도 있기 때문이었다.


쉽게 말해, canWin()은 이번 차례인 사람이 이길 수 있으면 1을, 비기면 0, 지면 -1을 반환한다.


참고로, bijection()와, cache 배열이 없어도 된다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#include <iostream>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <cstring>
#include <string>
#include <math.h>
#include <algorithm>
#include <map>
 
using namespace std;
 
int cache[19683= { 0, }; // 3^9
 
vector<string> board;
 
//turn이 한 줄을 만들었는지 반환
bool isFinished(char turn)
{
    // 가로
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            if (board[i][j] != turn) break;
 
            if (j == 2return true;
        }
    }
 
    // 세로
    for (int j = 0; j < 3; j++)
    {
        for (int i = 0; i < 3; i++)
        {
            if (board[i][j] != turn) break;
 
            if (i == 2return true;
        }
    }
 
    // 오른쪽 아래 대각선
    for (int i = 0; i < 3; i++)
    {
        if (board[i][i] != turn) break;
 
        if (i == 2return true;
    }
 
    // 왼쪽 아래 대각선
    for (int i = 0; i < 3; i++)
    {
        if (board[i][2 - i] != turn) break;
 
        if (i == 2return true;
    }
 
    return false;
}
 
// 틱택토 게임이 주어질 때, [0, 19682] 범위의 정수로 변환한다.
int bijection()
{
    int ret = 0;
 
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            ret *= 3;
 
            if (board[i][j] == 'o'++ret;
            else if (board[i][j] == 'x') ret += 2;
        }
    }
 
    return ret;
}
 
// 이번 턴인 내가 이길 수 있으면 1을, 비길 수 있으면 0을, 지면 -1을 리턴한다.
int canWin(char turn)
{
    // 기저 사례 : 마지막에 상대가 둬서 한 줄이 만들어진 경우
    if (isFinished('o' + 'x' - turn)) return -1;
 
    int result = cache[bijection()];
 
    // 모든 반환 값의 min을 취하자.
    int minValue = 2;
 
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            if (board[i][j] == '.')
            {
                board[i][j] = turn;
 
                minValue = min(minValue, canWin('o' + 'x' - turn));
 
                board[i][j] = '.';
            }
        }
    }
 
    // 플레이 할 수 없거나, 어떻게 해도 비기는 것이 최선인 경우
    if (minValue == 2 || minValue == 0return result = 0;
 
    // 최선이 상대가 이기는 거라면 난 무조건 지고, 상대가 지는 거라면 난 이긴다.
    return result = -minValue;
}
 
int main(void)
{
    int T = 0;
 
    scanf("%d"&T);
 
    while (T--)
    {
        string s;
 
        int who = 0;
 
        fill(cache, cache + 19683-2);
 
        if (!board.empty()) board.clear();
 
        for (int i = 0; i < 3; i++)
        {
            cin >> s;
 
            for (int j = 0; j < s.length(); j++)
                if (s.at(j) != '.'++who;
 
            board.push_back(s);
        }
 
        char start = 'x';
 
        if (who % 2 != 0) start = 'o';
 
        int get = canWin(start);
 
        if (get == -1// 상대가 이기는 경우
        {
            printf("%c\n"'x' + 'o' - start);
        }
        else if (get == 0// 무승부
        {
            printf("TIE\n");
        }
        else if (get == 1// 내가 이기는 경우
        {
            printf("%c\n", start);
        }
    }
 
    return 0;
}
cs




728x90
반응형

'알고리즘 문제 > AlgoSpot' 카테고리의 다른 글

Wildcard(Wildcard)  (0) 2019.01.10
외발 뛰기(JUMPGAME)  (0) 2019.01.09
울타리 잘라내기(FENCE)  (0) 2019.01.07
쿼드 트리 뒤집기(QUADTREE)  (0) 2019.01.07
시계 맞추기(Synchronizing Clocks)  (0) 2019.01.06