I thought I'd set myself a challenge as I've been programming in Python a little while now (nothing too heavy, mind you!) and make a 4-in-a-row game which I could play against the computer or another person, on a grid which i specify how big. I though I had the grid sorted, but now I'm coming to put in the gameplay and it's not working. :(

#!/usr/bin/env python
import sys

def main():
        quit = False
        global x
        x = raw_input("How wide would you like your game? (4 - 8) ")
        if x.isdigit():
                x  = int(x)
        else:
                print "Please enter a non-negative integer!"
                main()
        # Any smaller than 4 and the game is not very playable, any larger than 8 and it could go on $
        global y
        y = raw_input("And how tall? (4 - 8) ")
        if y.isdigit():
                y = int(y)
        else:
                print "Please enter a non-negative integer between 4 and 8!"
                main()
        inputPlayerParameters()

def inputPlayerParameters():
        z = raw_input("Enter '1' to play the computer or enter '2' to play another human: ")
        if z.isdigit():
                z = int(z)
                if z == 1:
                        print "You will play the computer"
                        gameBoard = initialiseGrid(x, y)
                        while True:
                                drawGrid(gameBoard)
                                player1Go(gameBoard)
                                computerGo(gameBoard)
                elif z == 2:
                        print "You will play another person"
                        gameBoard = initialiseGrid(x,y)
                        while True:
                                drawGrid(gameBoard)
                                player1Go(gameBoard)
                                player2Go(gameBoard)
                else:
                        print "You did not enter 1 or 2."
                        inputPlayerParameters()
        else:
                print "ERROR: DID NOT ENTER '1' OR '2'"
                inputPlayerParameters()

def initialiseGrid(x,y):                  
        rows = [0] * x
        i = 0
        grid = [0] * y
        while i < y:
                grid[i] = rows
                i=i+1
        return grid

def drawGrid(grid):
        for element in grid:
                print element
        for i in range(x):
                print "",i+1,

def player1Go(grid):
        print "Enter the column number you wish to go in: "
        userInput = raw_input(">>> ")
        if userInput == "quit":
                confirm = raw_input("Are you sure you want to quit? y/n ")
                if confirm == "y":
                        sys.exit(0)
        elif userInput == "save":
                confirm = raw_input("Save the game? y/n ")
                if confirm == "y":
                        filename = open("connect4game.txt", "wb")
                        filename.dump(grid)
                        filename.close()
        elif userInput.isdigit():
                userInput = int(userInput)
                print "You went in column", userInput
                if (userInput > x):
                        print "Please enter a valid column number!"
                        player1Go(grid)
                else:
                        grid[userInput-1][0] = "o"
                        checkForWin()
        else:
                print "Input not recognised! Try again."
                player1Go()

def player2Go(grid):
        print "Enter the column number you wish to go in: "
        userInput = raw_input(">>> ")
        if userInput == "quit":
                confirm = raw_input("Are you sure you want to quit? y/n ")
                if confirm == "y":
                        sys.exit(0)
        else:
                checkForWin()

def computerGo(grid):
        print "Computer thinking.."
        checkForWin()

def quitGame(message, draw = True):
        if draw == True:
                setGrid()
        print message
        exit()

def checkForWin():
        print "Checking state..."
#       if win = True:
#               print "GAME OVER!"

main()

For example, if I set the grid to 4x4 and play against myself: when I specify that I want to go in column 1, the entire column fills with "o" instead of just the bottom square.

I would very much appreciate any help! :)

The problem is here
rows = [0] * x
run the following code and see what you get

rows = [0] * x
for row in rows:
   print id(row)
##
##   you should see that all of the memory addresses are the same
##   meaning that you have the same object in the list several times,
##   so when you change one, they all change because they are
##   the same object.  Instead, try the following
##
rows = [[0] for x in range(0, 3)]
for row in rows:
   print id(row)

Also, you don't allow for errors, as in these lines for example.
z = raw_input("Enter '1' to play the computer or enter '2' to play another human: ")
if z.isdigit():
Do this instead:

z = 0
while z not in ["1", "2"]:
    z = raw_input("Enter '1' to play the computer or enter '2' to play another human: ")
z = int(z)
if z == 1:
    etc.

And your input for x and y can be done the same way, but consider using one function and passing the string literal "How wide would you like your game? (4 - 8) ", and the check list ["4", "5", "6", "7", "8"] and letting it return the choice, instead of the redundant code.

The final thing that I see, and I didn't take a close look at your code, is

def drawGrid(grid):
        for element in grid:
                print element
        for i in range(x):
                print "",i+1,

You do no pass "x" to the function, so it is getting the value from somewhere else (global variables, etc), which is never a good idea. You want to control which variables are used where (which brings up classes. This would be much better in a class structure, but I am guessing that you haven't gotten that far yet).

Thankyou very much for your help! :) It's really appreciated. The first tip has saved me quite a few lines of code and definitely makes the program more robust.

I have changed the way the grid is intialised, as I realised I was just creating the same element multiple times. Silly!

I currently have x and y set to be global variables. Is this not good syntax?

Anyway, this is the new version:

def initialiseGrid(x,y):                   
        grid = []                          
        for i in range(x):
                grid.append([0])
        for i in range(x):                 
                for j in range(y-1):
                        grid[i].extend([0])
        return grid

Notice the duplicate line
for i in range(x):
You should be able to use

def initialiseGrid(x,y):                   
        grid = []                          
        for h in range(x):
                grid.append([0])
                for j in range(y-1):
                        grid[h].extend([0])
        return grid

Generally, it is considered bad practice to use "i", "l", or "o" as single digit variable names as they can look like numbers.

This article has been dead for over six months. Start a new discussion instead.