[Optional Extension] Assignment 4 - Tic Tac Toe

Due: Thursday, May 23, 2024, at 10pm

This assignment is completely optional. If you receive at least 80% of the points, you will gain one extra token. If you receive at least 50% of the points (but not quite 80%), you will gain half of an extra token.

You may work alone or with a partner, but you must type up the code yourself. You may also discuss the assignment at a high level with other students. You should list any student with whom you discussed each part, and the manner of discussion (high-level, partner, etc.) in a comment at the top of each file. You should only have one partner for an entire assignment.

If you worked with a partner for the base version of this assignment, you may not work with another partner for the extension unless neither of you plans to resubmit the base version.

You should submit your assignment as a tictactoeExtension.py file on Moodle.

Parts of this assignment:

Comments and collaboration

As with all assignments in this course, for each file in this assignment, you are expected to provide top-level comments (lines that start with # at the top of the file) with your name and a collaboration statement. For this assignment, you have multiple programs; each needs a similar prelude.

You need a collaboration statement, even if just to say that you worked alone.

Note on style:

The following style guidelines are expected:

  • Variable names should be clear and easy to understand, should not start with a capital letter, and should only be a single letter when appropriate (usually for i, j, and k as indices, potentially for x and y as coordinates, and maybe p as a point, c for a circle, r for a rectangle, etc.).
  • It’s good to use empty lines to break code into logical chunks.
  • Comments should be used for anything complex, and typically for chunks of 3-5 lines of code, but not every line.
  • Don’t leave extra print statements in the code, even if you left them commented out.
  • Make sure not to have code that computes the right answer by doing extra work (e.g., leaving a computation in a for loop when it could have occurred after the for loop, only once).

Note: The example triangle-drawing program on page 108 of the textbook demonstrates a great use of empty lines and comments, and has very clear variable names. It is a good model to follow for style.

Getting started

This assignment comes with modified starter code. You can copy-paste it into a new file in VS Code – just save it as tictactoeExtension.py.

Part 1: Playing a more general game

For Part 1, you should copy your functions from Assignment 4 into the new starter code. Make sure not to overwrite any of the provided functions! The changes to the starter code allow the game to be more general, not just 3x3.

You should modify all of the functions you implemented in Assignment 4 to remove any assumption that the board is 3x3. Instead, your game should support an nxn board.

(Hint: You can check the size of boardState to figure out what n is.)

In the test code at the bottom, you can choose a value of n. Try out n=3 first so that your code from Assignment 4 should behave the same once you’ve copied it over.

if __name__ == "__main__":
    # CHOOSE n :D
    n = int(input("How big is the board (ex: 3)? "))
    
    # Part 1
    testDrawPlayerMarker(n)

    # Part 2
    testPrintBoardState(n)

    # Part 3
    testPlacingValidMarkers(n)

    # Part 4
    playGame(n)

Once you’ve got that working, try out other values of n, like 4 or 5. Make sure your game works for any value of n that is 3 or higher.

Part 2: Adding a win condition

For this part, you will add a new win condition. In addition to winning if a player has an entire n-cell row, column, or diagonal, a player can win if they have an entire mxm square, where m=ceil(n/2). So, for a 3x3 or 4x4 game, a player can win if they get a 2x2 square anywhere on the board.

You should implement the function didPlayerWinWithSquare. The player must have all m**2 pieces within the square for it to count as a victory.

def didPlayerWinWithSquare(boardState, player):
    """
    Returns a Boolean indicating whether the player
    won the game due to an entire square of side-length m=ceil(n/2).

    boardState: a nested list containing the board state
    player: 1 or 2
    returns: a Boolean (True if the player has an mxm square,
             where m=ceil(n/2), and False otherwise)
    """
    # TODO (hint: it may be easier to add a function to check a given square)
    return False # replace with your code

Note that if you try and put this all in didPlayerWinWithSquare you’ll probably end up with something like four nested for loops. I encourage you to define your own helper function to check if a given mxm square contains only pieces of the given player, and call that function for each possible square.

Reflection

Did you learn anything additional that you find interesting? Were there any particular issues or challenges you dealt with in completing this assignment? How long did you spend on this assignment? Write a brief discussion (a sentence or two is fine) at the bottom of your code file.

Grading

This assignment will be graded out of 100 points, as follows:

  • 5 points - submit a valid tictactoeExtension.py file with the right name

  • 5 points - tictactoeExtension.py file contains top-level comments with file name, purpose, author names, and collaboration statement

  • 10 points - code style enables readable programs

  • 50 points - Part 1 (20 pts for a configurable board that allows for placing pieces anywhere, 30 pts for updating win conditions)

  • 25 points - Part 2 (15 pts for handling an mxm square along the top row/column, 10 pts for handling it anywhere)

  • 5 points - reflection in the comments at the bottom of the tictactoeExtension.py file

What you should submit

You should submit a single tictactoeExtension.py file on Moodle.