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! :)

Recommended Answers

All 3 Replies

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.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.