-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathConnect4.py
182 lines (128 loc) · 4.07 KB
/
Connect4.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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# Connect 4!
import random
import time
from copy import copy
def print_board(board):
'''Prints the board, along with the number of each column above.
Returns None.
'''
out = [''.join(' {} '.format(n+1) for n in range(BOARDSIZE))]
out.append('+ - '*BOARDSIZE + '+')
for y in range(BOARDSIZE, 0, -1):
next_row = '| '
for x in range(1, BOARDSIZE+1):
next_row += board.get((x,y), ' ') + ' | '
out.append(next_row)
out.append('+ - '*BOARDSIZE + '+')
print('\n' + '\n'.join(out) + '\n')
def get_player_move():
'''Asks the player for their move. Checks that the move is valid,
and then returns it as an int.
'''
move = input("Choose a column to place your piece into. ")
while True:
try:
move = int(move)
except ValueError:
move = input("That's not a valid move. ")
continue
if not 0 < move <= BOARDSIZE:
move = input("That's not a valid move. ")
continue
if (move, 8) in board:
move = input("There's no more room in that column. ")
continue
return move
def get_cpu_move():
'''Chooses a column for any cpu player to place their piece into.
Returns an int.
Currently uses a simple random choice.
'''
# Check if there's a winning move this turn.
for move in range(1, BOARDSIZE+1):
if (move, 8) not in board:
if try_moves([move]):
return move
# Otherwise choose a random column.
moves = [x+1 for x in range(BOARDSIZE)]
move = random.choice(moves)
while (move, 8) in board:
move = random.choice(moves)
return move
def drop_piece(board, move):
'''Accepts a dict, board, to which move will be applied, and
an int, move, and updates the board by placing the player's
piece in the lowest free spot in that number column.
Returns the y co-ordinate it is placed at, as an int.
'''
for y in range(1, BOARDSIZE+1):
if (move, y) not in board:
board[(move, y)] = player
return y
def game_won(board, x, y):
'''Accepts two ints, x and y, which are the x and y co-ordinates of the
last move made. Checks to see if there is a winning line of length WINLEN
on the board by checking every line that includes the last placed piece.
Returns bool.
'''
checkrange = range(1-WINLEN, WINLEN)
horizontal = ''
vertical = ''
forwardslash = ''
backslash = ''
for n in checkrange:
horizontal += board.get((x-n,y), ' ')
vertical += board.get((x,y-n), ' ')
forwardslash += board.get((x+n,y+n), ' ')
backslash += board.get((x+n,y-n), ' ')
lines = [horizontal, vertical, forwardslash, backslash]
win = board[(x,y)]*WINLEN
for line in lines:
if win in line:
return True
return False
def try_moves(moves):
'''Accepts a list of ints, moves, and applies them in order to see
if they result in a win. Returns a bool.
'''
temp_board = copy(board)
for m in moves:
last_y = drop_piece(temp_board, m)
if game_won(temp_board, m, last_y):
return True
return False
def testboard():
'''Used to set a non-blank starting position for the board to
to test.
'''
pass
# Settings
BOARDSIZE = 8
WINLEN = 4
players = ('X', 'O')
YOU = players[0]
test = False
# Start
board = {}
turn = random.choice([n for n in range(len(players))])
if test:
testboard()
print_board(board)
# Game Loop
while True:
player = players[turn % len(players)]
print("\nIt is {}'s turn.".format(player))
if player != YOU:
move = get_cpu_move()
time.sleep(0) # Suspense/Annoyance control
else:
move = get_player_move()
last_y = drop_piece(board, move)
print_board(board)
if game_won(board, move, last_y):
print("{} has won!".format(player))
break
if len(board) == BOARDSIZE**2:
print("No one wins.")
break
turn += 1