-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconnect_four.py
123 lines (100 loc) · 3.89 KB
/
connect_four.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
import numpy as np
class Table():
def __init__(self):
self.table = np.zeros((6,7), dtype=int)
def _winning_rule(self, arr)-> bool:
win1rule = np.array([1,1,1,1])
win2rule = np.array([2,2,2,2])
# subarrays of len = 4
sub_arrays = [arr[i:i+4] for i in range(len(arr)-3)]
player1wins = any([np.array_equal(win1rule,sub) for sub in sub_arrays])
player2wins = any([np.array_equal(win2rule,sub) for sub in sub_arrays])
if player1wins or player2wins:
return True
else:
return False
def _get_diagonals(self, _table, i, j)-> list:
diags = []
diags.append(np.diagonal(_table, offset=(j - i)))
diags.append(np.diagonal(np.rot90(_table), offset=-_table.shape[1] + (j + i) + 1))
return diags
def _get_axes(self, _table, i, j)-> list:
axes = []
axes.append(_table[i,:])
axes.append(_table[:,j])
return axes
def _winning_check(self, i, j)-> bool:
'''
Checks if there is four equal numbers in every
row, column and diagonal of the matrix
'''
all_arr = []
all_arr.extend(self._get_axes(self.table, i, j))
all_arr.extend(self._get_diagonals(self.table, i, j))
for arr in all_arr:
winner = self._winning_rule(arr)
if winner:
return True
else:
pass
def drop(self, player, column):
'''
Drops a number (same as player) in the column specified
'''
colummn_vec = self.table[:,column]
non_zero = np.where(colummn_vec != 0)[0]
if non_zero.size == 0:
# sets the stone to the last element
i = self.table.shape[0]-1
self.table[i,column] = player
else:
# sets the stone on the last 0
i = non_zero[0]-1
self.table[i,column] = player
# checking if winning for every drop!
if self._winning_check(i, column):
print(f'Player {player} wins!')
else:
return self.table
def drop_sim(self, player)-> bool:
'''
Drop mechanics but faster and bool return for simulation purposes
--------
Args:
* Player: int, player number (1 or 2)
--------
Returns: tuple(bool,bool,int,np.array)
1. State of the game (True when finished)
2. False when tie
3. idx of the last drop
4. final table
--------
To Do:
* Count the first drop column of the player that won the game,
now is only player 1
'''
column = np.random.randint(0,7)
while np.count_nonzero(self.table[:,column]) == 6: # checks if column if full and switch to another
column = np.random.randint(0,7)
if np.count_nonzero(self.table) == 42: # Full table with tie!
self.reset()
return True, True, column, self.table
colummn_vec = self.table[:,column]
non_zero = np.where(colummn_vec != 0)[0]
if non_zero.size == 0:
# sets the stone to the last element
i = self.table.shape[0]-1
self.table[i,column] = player
else:
# sets the stone on the last 0
i = non_zero[0]-1
self.table[i,column] = player
# checking if winning for every drop!
if self._winning_check(i, column):
# we got a winner :)
return True, False, column, self.table
else:
# no winner yet :(
return False, False, column, self.table
def reset(self):
return self.table.fill(0)