Python Forum
Start using classes for Four-in-a-row game
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Start using classes for Four-in-a-row game
#1
Hi all,

Yet another newbie here that made a simple game.

The game is the classic four-in-a-row game where you drop down a round brick into one of seven columns and it goes to the bottom. And then the other player drops a brick (with another color) into another column (or in the same column as player one). First to win is when a player have 4 consecutive bricks of the same color in any direction. The size of the board is 7x6

I'm satisfied that the game works as it is now. You can play human-human, human-computer and even computer-computer (even though that makes no sense...)

What I'd love to get some feedback on is what kind of classes I should implement, and with what attributes and methods and so on.
So if anyone has some good advice on that I'd really appreciate it.

import random
import copy

def spaceIfEmpty(listValue):
    if listValue == '':
        return ' '
    else:
        return listValue

def printTheGameBoard(board):
    print (' ======== Enter [q] to quite game ========')
    print ('┌─────┬─────┬─────┬─────┬─────┬─────┬─────┐')
    print ('│  ' + spaceIfEmpty(board[0][0]) + '  │  ' + spaceIfEmpty(board[0][1]) + '  │  ' + spaceIfEmpty(board[0][2]) + '  │  ' + spaceIfEmpty(board[0][3]) + '  │  ' + spaceIfEmpty(board[0][4]) + '  │  ' + spaceIfEmpty(board[0][5]) + '  │  ' + spaceIfEmpty(board[0][6]) + '  │  ')
    print ('├─────┼─────┼─────┼─────┼─────┼─────┼─────┤')
    print ('│  ' + spaceIfEmpty(board[1][0]) + '  │  ' + spaceIfEmpty(board[1][1]) + '  │  ' + spaceIfEmpty(board[1][2]) + '  │  ' + spaceIfEmpty(board[1][3]) + '  │  ' + spaceIfEmpty(board[1][4]) + '  │  ' + spaceIfEmpty(board[1][5]) + '  │  ' + spaceIfEmpty(board[1][6]) + '  │  ')
    print ('├─────┼─────┼─────┼─────┼─────┼─────┼─────┤')
    print ('│  ' + spaceIfEmpty(board[2][0]) + '  │  ' + spaceIfEmpty(board[2][1]) + '  │  ' + spaceIfEmpty(board[2][2]) + '  │  ' + spaceIfEmpty(board[2][3]) + '  │  ' + spaceIfEmpty(board[2][4]) + '  │  ' + spaceIfEmpty(board[2][5]) + '  │  ' + spaceIfEmpty(board[2][6]) + '  │  ')
    print ('├─────┼─────┼─────┼─────┼─────┼─────┼─────┤')
    print ('│  ' + spaceIfEmpty(board[3][0]) + '  │  ' + spaceIfEmpty(board[3][1]) + '  │  ' + spaceIfEmpty(board[3][2]) + '  │  ' + spaceIfEmpty(board[3][3]) + '  │  ' + spaceIfEmpty(board[3][4]) + '  │  ' + spaceIfEmpty(board[3][5]) + '  │  ' + spaceIfEmpty(board[3][6]) + '  │  ')
    print ('├─────┼─────┼─────┼─────┼─────┼─────┼─────┤')
    print ('│  ' + spaceIfEmpty(board[4][0]) + '  │  ' + spaceIfEmpty(board[4][1]) + '  │  ' + spaceIfEmpty(board[4][2]) + '  │  ' + spaceIfEmpty(board[4][3]) + '  │  ' + spaceIfEmpty(board[4][4]) + '  │  ' + spaceIfEmpty(board[4][5]) + '  │  ' + spaceIfEmpty(board[4][6]) + '  │  ')
    print ('├─────┼─────┼─────┼─────┼─────┼─────┼─────┤')
    print ('│  ' + spaceIfEmpty(board[5][0]) + '  │  ' + spaceIfEmpty(board[5][1]) + '  │  ' + spaceIfEmpty(board[5][2]) + '  │  ' + spaceIfEmpty(board[5][3]) + '  │  ' + spaceIfEmpty(board[5][4]) + '  │  ' + spaceIfEmpty(board[5][5]) + '  │  ' + spaceIfEmpty(board[5][6]) + '  │  ')
    print ('├─────┼─────┼─────┼─────┼─────┼─────┼─────┤')
    print ('└──1──┴──2──┴──3──┴──4──┴──5──┴──6──┴──7──┘')

def checkIfColumnIsFull(board, column):
    if board[0][column] == '':
        return False
    return True


def placeBrickInColumn(board, column, character):
    checkRow = 0
    for row in range(0, len(board)):
        #print (board[row][column])
        if row < len(board)-1:
            checkRow = row + 1
        else:
            checkRow = row
        if board[checkRow][column] != '':
            break
        
    board[row][column] = character

def placeBrickForComputer(board, players_):
    NextPlayer = int(players_[2]['NextPlayer'])
    while True:
        randomColumn = random.randint(0, len(board))
        if checkIfColumnIsFull(board, randomColumn):
            continue
        else:
            placeBrickInColumn(board, randomColumn, players_[NextPlayer]['PlayerBrick'])
        break

#
#
#


def checkFor4InARow(board):
    FourInARow = []

    # Horizontal answers
    for row in range(0, len(board)):
	    for column in range(0, 4):
		    FourInARow.append(''.join(board[row][column:column+4]))

    # Vertical answers
    verticalString = ''
    for outerColumn in range(0, len(board[0])): ## for all columns in board
        for n in range(0, 3): ## loop 3 times for each outerColumn
            for column in range(n, n+4): ## loop all 
                verticalString += board[column][outerColumn]
            FourInARow.append(verticalString)
            verticalString = ''
    
    # Diagonal answers: down-right  (starting at top far left)
    diagonalString = ''
    for outerRow in range(0, 3):
            for innerColumn in range(0, 4):
                    for n in range(0, 4):
                            diagonalString += board[outerRow + n][innerColumn + n]
                    FourInARow.append(diagonalString)
                    diagonalString = ''


    # Diagonal answers: down-left (starting at top far right)
    diagonalString = ''
    for outerRow in range(0, 3):
            for innerColumn in range(6, 2, -1):
                    for n in range(0, 4):
                            diagonalString += board[outerRow + n][innerColumn - n]
                    # print ('[' + str(outerRow+0) + '][' + str(innerColumn-0) + ']' + '[' + str(outerRow+1) + '][' + str(innerColumn-1) + ']' + '[' + str(outerRow+2) + '][' + str(innerColumn-2) + ']' + '[' + str(outerRow+3) + '][' + str(innerColumn-3) + ']')
                    FourInARow.append(diagonalString)
                    diagonalString = ''

    # Diagonal answers
    # How the heck do I do that without specifying every combo????
    if 'XXXX' in FourInARow:
        return 'X'
    elif 'OOOO' in FourInARow:
        return 'O'
    else:
        return None

    # print (FourInARow)


def initiateGame():
    players_ = [{'PlayerType': 'human', 'PlayerBrick': 'X'}, {'PlayerType': 'computer', 'PlayerBrick': 'O'}]
    print ('\n'*10)
    print ('Welcome to For-In-A-Row!\n\n')
    print ('This is a two player game, and we start off by choosing player type (human/computer) for each player.\n')


    while True:
        playerType = input('Player 1 is human. Press enter to confirm or type [c] to set player 1 as computer: ')
        
        if playerType.lower() == 'c':
            players_[0]['PlayerType'] = 'computer'
        break

    while True:
        playerType = input('Player 2 is computer. Press enter to confirm or type [h] to set player 2 as human: ')
        if playerType.lower() == 'h':
            players_[1]['PlayerType'] = 'human'
        break


    # default player 1 i X
    # if random number is 1 player brick is swapped
    r = random.randint(0, 1)

    if r == 1:
        players_[0]['PlayerBrick'] = 'O'
        players_[1]['PlayerBrick'] = 'X'

    NextPlayer = random.randint(0, 1)
    
    print ('Player ' + str(NextPlayer + 1) + ' starts the game and was randomly chosen to play with ' + players_[NextPlayer]['PlayerBrick'])

    # adding NextPlayer dict in players list
    players_.append({'NextPlayer': NextPlayer})

    return players_

def placeBrick(board, players_):
    nextPlayer = int(players_[2]['NextPlayer']) #Index 2 holds value 0 or 1 which is pointing to index 0 or 1 in players_

    #check if next player is human or computer
    if players_[nextPlayer]['PlayerType'] == 'human':
        chosenColumn = input ('Player ' + str(nextPlayer+1) + ': Enter column to release brick into: ')
        if chosenColumn == 'q':
            return 'q'
        
        if chosenColumn.isdigit():
            if int(chosenColumn) in [1, 2, 3, 4, 5, 6, 7]:
                chosenColumn = int(chosenColumn) - 1
                if checkIfColumnIsFull(board, chosenColumn):
                    print ('column full')
                else:
                    placeBrickInColumn(board, chosenColumn, players_[nextPlayer]['PlayerBrick'])
                    nextPlayer = (1, 0)[nextPlayer] # this is flipping to next player
                    players_[2]['NextPlayer'] = nextPlayer
                    # placeBrickForComputer(theGameBoard)
            else:
                return None
        else:
            return None
    else:
        placeBrickForComputer(board, players_)
        nextPlayer = (1, 0)[nextPlayer] # this is flipping to next player
        players_[2]['NextPlayer'] = nextPlayer
    printTheGameBoard(board)
    return None
        

def gamePlay():

    initiatePlayers = initiateGame()
    players = copy.deepcopy(initiatePlayers)

    # theGameBoard = [
    #     ['     ', '     ', '     ', '     ', '     ', '     ', '     '],
    #     ['     ', '     ', '     ', '     ', '     ', '     ', '     '],
    #     ['     ', '     ', '     ', '     ', '     ', '     ', '     '],
    #     ['     ', '     ', '     ', '     ', '     ', '     ', '     '],
    #     ['     ', '     ', '     ', '     ', '     ', '     ', '     '],
    #     ['     ', '     ', '     ', '     ', '     ', '     ', '     ']
    #     ]

    # Create an empty list board with size 7 column * 6 rows. This way creates it with no reference oppose to:
    # [['']*7]*6 that will have a refence between each element so if one "cell" is set, the entire column is set to the same value
    theGameBoard =  [
                    ['' for i in range(7)] for x in range(6)
                    ]  ## 7 columns x 6 rows with no reference


    printTheGameBoard(theGameBoard)
    winner = None

    while True:
        chosenColumn = placeBrick(theGameBoard, players)
        if chosenColumn == 'q':
            return 'q'
                    
        winner = checkFor4InARow(theGameBoard)

        if winner == 'X':
            print ('X-player won!')
            break
        elif winner == 'O':
            print ('O-player won!')
            break


while True:
    if gamePlay() == 'q':
        break
    else:
        reMatch = input ('Enter [y] to play again: ')
        if reMatch.lower() not in ['y', 'yes']:
            break
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020