Fork me on GitHub

Functionally programming tic tac toe

I am a novice functional programmer. So if you find any areas of suggested improvement on my FP skills, do add a comment below.

Below is a sample Tic Tac Toe written using Functional Programming constructs (or at least whatever I understood about them).

Right now, I've implemented only a simple player who basically marks off a cell randomly. It should be possible to define more intelligent players similarly. Hopefully all the comments in the code should be sufficiently self explanatory.

import random
import functools
import itertools
import copy

def row_gen(board):
    """ 
    Generator which returns tuples of tuples. 
    The outer tuple represents a row.
    The inner tuple represents each cell with 
    its coordinates and data 
    """
    return (
        tuple((row,col,board[row][col]) 
              for col in range(3)) 
        for row in range(3)) 

def col_gen(board):
    """ 
    Generator which returns tuples of tuples. 
    The outer tuple represents a column.
    The inner tuple represents each cell with 
    its coordinates and data 
    """
    return (
        tuple((row,col,board[row][col]) 
              for row in range(3)) 
        for col in range(3)) 

def dia_gen(board):
    """ 
    Generator which returns two tuples of tuples. 
    The outer tuple represents a diagonal.
    The inner tuple represents each cell with 
    its coordinates and data 
    """
    return (
        tuple((i,i,board[i][i]) for i in range(3)),
        tuple((i,2-i,board[i][2-i]) for i in range(3)))

def empty(board):
    """ Gets a list of all empty cells on the board """
    return (
        (row,col) 
        for row in range(3) 
            for col in range(3) 
                if board[row][col] == None)

def is_empty(board):
    """ checks if any cell on the board is still empty """
    for row in range(3) :
        for col in range(3) :
            if board[row][col] is None :
                return False
    return True

def random_player(chr,board):
    """Represents a player who randomly marks his next move """
    empty_cells = list(empty(board))
    play = empty_cells[random.randint(0,len(empty_cells)-1)]
    board = copy.copy(board)
    board[play[0]][play[1]] = chr
    return board

def show(board):
    """ Shows the current representation of the board """
    print '+-+-+-+'
    for row in range(3) :
        print '|%s|' % '|'.join(
            board[row][col]if board[row][col] is not None else ' ' 
            for col in range(3))
        print '+-+-+-+'

if __name__ == '__main__' : 
    # Initialise the board with all values set to None       
    board = list(list(None for i in range(3)) for j in range(3))
    show(board)

    # Initialise the two players. Each is given a separate char
    player1 = functools.partial(random_player,'X')
    player2 = functools.partial(random_player,'O')

    # Setup an iterator to continuously cycle through both players
    players = itertools.cycle((player1,player2))

    # Play game
    over = False
    while not over and not is_empty(board) :
        # Ask the next player to make his move
        board = players.next()(board)
        show(board)

        # Note a cell bag set is all rows, 
        # all cols and all diagonals
        for cell_bag_set in (
                row_gen(board),
                col_gen(board),
                dia_gen(board)) :

            # Note a cell_bag can be a row, column or a dia
            for cell_bag in cell_bag_set :
                vals = set(val[2] for val in cell_bag) 
                if len(vals) == 1 and  \
                        vals.__iter__().next() is not None :
                    over = True
                    print 'Over'
                    break

Comments !

social