user1871071
user1871071

Reputation: 67

How would I find the winner of my Python Tic Tac Toe game?

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

Answers (3)

Rushy Panchal
Rushy Panchal

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

a3f
a3f

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

Cubic
Cubic

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

Related Questions