-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprog1.py
145 lines (119 loc) · 3.43 KB
/
prog1.py
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
import math
# we want X to win
S0 = [
['X', 'O', 'O'],
[' ', ' ', 'X'],
[' ', 'X', 'O']
]
# who is currently playing
def Player(state):
X_count = sum(row.count('X') for row in state)
O_count = sum(row.count('O') for row in state)
if X_count > O_count:
return 'O'
if O_count > X_count:
return 'X'
if O_count == X_count:
return 'X'
# return legal moves in state
# return all empty places where the current player could go
def Actions(state):
moves = []
for i in range(3):
for j in range(3):
if state[i][j] == ' ':
moves.append((i, j))
return moves
# check if the game ended
def Terminal(state):
for i in range(3):
if state[i][0] == state[i][1] == state[i][2]:
return True
if state[0][i] == state[1][i] == state[2][i]:
return True
empt = sum(row.count(' ') for row in state)
if empt == 0:
return True
else:
return False
return False
# final numerical value for a terminal state
def Utility(state):
for i in range(3):
# check match in rows
if state[i][0] == state[i][1] == state[i][2]:
if state[i][0] == 'X':
return 1
elif state[i][0] == 'O':
return -1
# check match in columns
if state[0][i] == state[1][i] == state[2][i]:
if state[0][i] == 'X':
return 1
elif state[0][i] == 'O':
return -1
# check match in diagonals
if state[0][0] == state[1][1] == state[2][2]:
if state[0][0] == 'X':
return 1
elif state[0][0] == 'O':
return -1
if state[0][2] == state[1][1] == state[2][0]:
if state[0][2] == 'X':
return 1
elif state[0][2] == 'O':
return -1
return 0
# returns state after an action / move
def Result(state, action):
cur_player = Player(state)
board = state
board[action[0]][action[1]] = cur_player
return board
# minimax algorithm
# given a state a:
# MAX picks action a in Actions(s) that produces highest value of MIN-VALUE(Result(s,a))
# prune if alpha>= beta
def MAX_VALUE(state, Alpha, Beta):
if Terminal(state):
return Utility(state)
v = -math.inf
for action in Actions(state):
v = max(v, MIN_VALUE(Result(state, action), Alpha, Beta))
# pruning
if v >= Beta:
return v
Alpha = max(Alpha, v)
return v
# MIN picks action a in Actions(s) that produces smallest value of MAX-VALUE(Result(s,a))
def MIN_VALUE(state, Alpha, Beta):
if Terminal(state):
return Utility(state)
v = math.inf
for action in Actions(state):
v = min(v, MAX_VALUE(Result(state, action), Alpha, Beta))
# pruning
if v <= Alpha:
return v
Beta = min(Beta, v)
return v
# assuming current player is X and we want to maximise X
def minimax_alpha_beta(state):
v = -math.inf
alpha = -math.inf
for action in Actions(state):
min_val = MIN_VALUE(Result(state, action), alpha, math.inf)
if min_val > v:
v = min_val
move = action
alpha = max(alpha, v)
return move, v
print(S0)
move, chance = minimax_alpha_beta(S0)
if chance == 1:
chance = 'win'
if chance == 0:
chance = 'draw'
if chance == -1:
chance = 'lose'
print("For X to",chance, "current move of X should be :",move)