Reputation: 67
So far, I have a program where 2 players can click to place an X and an O in turns. I'm not sure how to make the program recognize a winner/ draw. If you guys could help me make a function that indicated a win/ draw on the screen in any way, I would love you forever. Thanks.
from graphics import *
import sys
def player_o(win, center):
'''
Parameters:
- win: the window
'''
outline_width = 5
circle = Circle(center, boxsize/2)
circle.setOutline('red')
circle.setWidth(outline_width)
circle.draw(win)
def player_x(win, p1x, p1y):
'''
Parameters:
- win: the window
'''
for i in range(2):
deltaX = (-1) ** i * (boxsize / 2)
deltaY = (boxsize / 2)
line = Line(Point(p1x - deltaX, p1y - deltaY),
Point(p1x + deltaX, p1y + deltaY))
line.setFill('red')
line.setWidth(5)
line.draw(win)
def game():
global win
global boxsize
try:
winsize = int(input("How large would you like the window? (Between 100 and 3000): "))
if winsize < 100 or winsize > 3000:
print("Invalid window size")
quit()
squares = int(input("How many squares per row? (Between 3 and 10):"))
boxsize = winsize/ squares
if squares < 3 or squares > winsize / 10:
print("Invalid number")
quit()
except ValueError:
sys.exit("Not a valid number")
win = GraphWin("Tic Tac Toe", winsize, winsize)
for i in range(squares - 1):
hline = Line(Point(0, (winsize/squares) * (i + 1)), Point(winsize, (winsize/squares) * (i + 1)))
hline.draw(win)
vline = Line(Point((winsize/squares) * (i + 1), 0), Point((winsize/squares) * (i + 1), winsize))
vline.draw(win)
for i in range((squares ** 2) // 2):
print("X, click a square.")
p1mouse = win.getMouse()
p1x = p1mouse.getX()
p1y = p1mouse.getY()
player_x(win, p1x, p1y)
print("O, click a square.")
p2mouse = win.getMouse()
p2x = p2mouse.getX()
p2y = p2mouse.getY()
player_o(win, Point(p2x, p2y))
if squares % 2 == 1:
print("X, click a square.")
p1mouse = win.getMouse()
p1x = p1mouse.getX()
ply = p1mouse.getY()
player_x(win, p1x, p1y)
game()
Upvotes: 1
Views: 2408
Reputation: 17532
With each move in the game, a 2D array or a dictionary (with values being lists) should be used. Then, you can just check each way of winning. This way, you can also check if the move is valid or not--- whether or not the spot on the board is taken.
I would also suggest using a numerical or a coordinate system to dictate movement.
The board would look like this:
1 2 3
4 5 6
7 8 9
The numbers are corresponding spots on the board.
For example:
In the initialization:
moves = 0
positions = {'1': 0, '2': 0, '3': 0, '4': 0, '5': 0, '6': 0, '7': 0, '8': 0, '9':0}
# '1' - '9' are the spots on the board.
# 0 means the spot is empty, 'X' means the spot is taken by 'X', 'O' means the spot is taken by 'O'. You can use any other naming system, but this is simple.
In the movement code:
while 1 == 1: # just a loop until the input is valid. See the 'break' statement below
new_move = input("X, enter what space to move to: ")
if positions[new_move] == 0: # if that board spot is empty
moves += 1 #moves = moves + 1
positions[new_move] == 'X' # board spot is now occupied by 'X'
# code to show the piece on the board
if moves >= 5: # least possible moves to win is 5
win_check(positions)
break
Alternatively, you can use the movement as a function, and have it recursively call itself until the input is valid:
def move_X():
new_move = input("X, enter what space to move to: ")
if positions[new_move] == 0: # if that board spot is empty
moves += 1 #moves = moves + 1
positions[new_move] == 'X' # board spot is now occupied by 'X'
# code to show the piece on the board
if moves >= 5: # least possible moves to win is 5
win_check(positions)
move_O() # this should be defined similarly to 'move_X' except that it would correlate to 'O'.
else:
move_X()
The the win checking method:
def win_check(positions):
if positions['1'] == 'X' and positions['2'] == 'X' and positions['3'] == 'X':
return "Winner: X"
elif # similar things, checking all of the other ways to win.
You need 1 if
statement (in the beginning) and 15 elif
statements, as there are 8 ways to win for each player, so 16 checks have to be made.
Upvotes: 0
Reputation: 8657
After 3 turns (minimum turns to win) check your 2d array if there is a token next to the last played by adding/substracting one, if found repeat same operation to array indices else break out.
If 2nd control structure is reached break and announce winner.
Upvotes: 0
Reputation: 15673
Keep data and representation of data separated. That's how. Right now you're just drawing things, rather than that you should be generating some representation of the playing field (e.g. a list of the boxes and their state, as in, checked by p1, checked by p2, or unchecked), and then use that to draw when needed. The advantage should be immediately obvious - if you know the state of the game, determining if there's a winner (and who it is) is trivial.
Upvotes: 6