Callum Overy
Callum Overy

Reputation: 23

Python Programming 3.4.2, Naughts and Crosses. Best way to check how to see if game is won?

#!/usr/bin/python3.4
import tkinter as tk
import time
import os
root = tk.Tk()




label = tk.Label(root)
root.configure(background='#0C142E')

ButtonTable=[]

Turn = 0 # 0(x) 1(O)
XO=["X","O"]
wins = [
    '111 000 000', '000 111 000', '000 000 111',    # Across
    '100 100 100', '010 010 010', '001 001 001',    # Down
    '100 010 001', '001 010 100',                   # Diagonal
]
GridArray=["","","","","","","","","",] # Gets replaced with x,o to record progress
def CheckWin():
    #something goes here?
def CreateButtonmid(Text,side, Return): 
    return CreateButton
def ChooseButton(xx,b): 
    global Turn
    b.configure(state = "disabled")
    print(xx)
    b.config(text=XO[Turn])
    GridArray[int(xx)]=XO[Turn]
    CheckWon()
    if Turn == 0:
        Turn = 1
    else:
        Turn=0
    label.configure(text="Turn: "+XO[Turn])
    print(GridArray)
def CreateButton(Text,side,Return): 
    b = tk.Button(side,text=Text)
    b.pack(side="left")

    b.config(command=lambda: ChooseButton(Return,b))
    ButtonTable.append(b)
    b.configure(background='#323642',bd=0,fg="white",height=5,width=10)
    return b

label.pack(side = "top")
label.config(bg="#0C142E",fg="#fff",text="(STARTING:X)")

topframe = tk.Frame(root)
topframe.pack( side = "top" )

CreateButton("[]",topframe,("0"))
CreateButton("[]",topframe,("1"))
CreateButton("[]",topframe,("2"))

midframe = tk.Frame(root)
midframe.pack( side = "top" )
CreateButton("[]",midframe,("3"))
CreateButton("[]",midframe,("4"))
CreateButton("[]",midframe,("5"))

bottomframe = tk.Frame(root)
bottomframe.pack( side = "top" )
CreateButton("[]",bottomframe,("6"))
CreateButton("[]",bottomframe,("7"))
CreateButton("[]",bottomframe,("8"))


root.mainloop()

Basically it is a multiplayer game that will require two people to play. What would be the best way to check to see if someone has won. I have no idea and I'm new to programming, any resources to help with this or my coding are always welcome

Upvotes: 2

Views: 619

Answers (2)

BrianO
BrianO

Reputation: 1524

Your data representation makes this harder than it needs to be. Presently, you store a grid as a list of the 9 squares, starting at the upper left and proceeding by rows, across and then down. Just to access the square in (row 1, column 2), for example, you have to do arithmetic.

Better representations let you address squares directly by their row and column indexes. In Python, counting starts at 0, so let's say that the rows are 0, 1, 2, and likewise the columns. Two alternatives to consider:

  • a 3-element list of the rows, each row a 3-element list for the values in the squares at the corresponding columns:

    grid = [["", "", ""], ["", "", ""], ["", "", ""]]

    With this grid, the square in row i, column j is just grid[i][j].

  • A dict:

    dgrid = {(i,j): "" for i in range(3) for j in range(3)}

    With this representation, the square in row i, column j is just dgrid[i,j]. I'll use this in the code that follows.

Checking the grid for a winning state is now much simpler. Here's a function to check whether row i has a win for player (equal to 'X' or 'O', let's say):

def winning_row(i, player):
    '''Return True if all entries in row i are equal to player.
       player is either 'X' or 'O'.
    '''
    return all(dgrid[i,j] == player for j in range(3))

You can define the function winning_column(j, player) similarly. Checking the diagonals is a little different. We can use two functions, winning_main_diagonal(player) and winning_other_diagonal(player). Here's the latter:

def winning_other_diagonal(player):
    return all(dgrid[i,2-i] for i in range(3))

These functions all take a player parameter because you only need to check for a winning configuration after a particular player has moved. You don't need to check the entire grid to see whether some player won, and if so which one.

This function reports whether the player who just moved by marking square (i,j) has just won:

def just_won(i, j, player):
    if winning_row(i, player): 
        return True
    if winning_column(j, player): 
        return True
    if i == j and winning_diagonal(player):
        return True
    if I + j == 2 and winning_other_diagonal(player):
        return True
    return False

Upvotes: 1

Steven Rumbalski
Steven Rumbalski

Reputation: 45552

def get_winner(grid):
    '''returns 'X', 'O', or None'''
    line_dxs = [
        # rows
        (0,1,2),
        (3,4,5),
        (6,7,8),
        # cols
        (0,3,6),
        (1,4,7),
        (2,5,8),
        # diags
        (0,4,8),
        (2,4,6)
    ]
    for dxs in line_dxs:
        line = [grid[dx] for dx in dxs]
        if line == ['X', 'X', 'X']:
            return 'X'
        elif line == ['O', 'O', 'O']:
            return 'O'

In action:

>>> get_winner(['X', 'O', 'X',
...             'O', 'O', 'X',
...             'X', 'O', '' ])
'O'
>>> get_winner(['X', 'O', 'X',
...             'O', 'O', 'X',
...             'X', '' , 'O' ])
>>> get_winner(['X', 'O', 'X',
...             'O', 'O', 'X',
...             'X', '' , 'X' ])
'X'

Upvotes: 2

Related Questions