1 12-Strings

Previous: 11-TypeHints.html

* https://xkcd.com/1638/
* https://www.explainxkcd.com/wiki/index.php/1638:_Backslashes

1.1 Screencasts

1.2 Extra reading

* https://automatetheboringstuff.com/2e/chapter6/
* https://books.trinket.io/pfe/06-strings.html
* https://inventwithpython.com/invent4thed/chapter11.html
* https://www.learnpython.org/en/Basic_String_Operations
* https://www.learnpython.org/en/String_Formatting
* https://www.python-course.eu/python3_formatted_output.php
* https://www.tutorialspoint.com/python3/python_strings.htm
* https://realpython.com/python-formatted-output/
* https://realpython.com/python-f-strings/

Python docs:
* https://docs.python.org/3/library/string.html
* https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting
* https://docs.python.org/3/library/stdtypes.html#str.format
* https://docs.python.org/3/library/string.html#formatstrings
* https://docs.python.org/3/library/string.html#formatspec
* https://docs.python.org/3/reference/lexical_analysis.html#f-strings

1.3 Code

Code (to be stepped through in spyder3 and/or pudb3):


String processing is kind of boring, and there’s no need to string it on forever.
So, today we’ll just trace a game instead…

1.4 Extra topic today: tic-tac-toe

* Tic-tac-toe (American English), noughts and crosses (British English), or Xs and Os is a paper-and-pencil game for two players, X and O, who take turns marking the spaces in a 3×3 grid.
* The player who succeeds in placing three of their marks in a horizontal, vertical, or diagonal row is the winner.

* In 1952, OXO (or Noughts and Crosses), developed by British computer scientist Sandy Douglas for the EDSAC computer at the University of Cambridge, became one of the first known video games.
* The computer player could play perfect games of tic-tac-toe against a human opponent (wow, that must be AI!)

Today, we trace the tic-tac-toe game code:

Overall strategy

Get computers move (The AI)

The code:

# -*- coding: utf-8 -*-
Tic Tac Toe

import random
from typing import List

def drawBoard(board: List[str]) -> None:
    # This function prints out the board that it was passed.

    # "board" is a list of 10 strings representing the board
    # (ignore index 0)
    print(board[7] + "|" + board[8] + "|" + board[9])
    print(board[4] + "|" + board[5] + "|" + board[6])
    print(board[1] + "|" + board[2] + "|" + board[3])

def inputPlayerLetter() -> List[str]:
    # Lets the player type which letter they want to be.
    # Returns a list with the player's letter as the first item,
    # and the computer's letter as the second.
    letter = ""
    while not (letter == "X" or letter == "O"):
        print("Do you want to be X or O?")
        letter = input().upper()

    # the first element in the list is the player's letter,
    # the second is the computer's letter.
    if letter == "X":
        return ["X", "O"]
        return ["O", "X"]

def whoGoesFirst() -> str:
    # Randomly choose the player who goes first.
    if random.randint(0, 1) == 0:
        return "computer"
        return "player"

def makeMove(board: List[str], letter: str, move: int) -> None:
    board[move] = letter

def isWinner(bo: List[str], le: str) -> bool:
    # Given a board and a player's letter,
    # this function returns True if that player has won.
    # We use bo instead of board and le instead of letter
    # so we don't have to type as much.
    return (
        (bo[7] == le and bo[8] == le and bo[9] == le)
        or (bo[4] == le and bo[5] == le and bo[6] == le)  # across the top
        or (bo[1] == le and bo[2] == le and bo[3] == le)  # across the middle
        or (bo[7] == le and bo[4] == le and bo[1] == le)  # across the bottom
        or (bo[8] == le and bo[5] == le and bo[2] == le)  # down the left side
        or (bo[9] == le and bo[6] == le and bo[3] == le)  # down the middle
        or (bo[7] == le and bo[5] == le and bo[3] == le)  # down the right side
        or (bo[9] == le and bo[5] == le and bo[1] == le)  # diagonal
    )  # diagonal

def getBoardCopy(board: List[str]) -> List[str]:
    # Make a copy of the board list and return it.
    boardCopy = []
    for i in board:
    return boardCopy

def isSpaceFree(board: List[str], move: int) -> bool:
    # Return true if the passed move is free on the passed board.
    return board[move] == " "

def getPlayerMove(board: List[str]) -> int:
    # Let the player type in their move.
    move = " "
    while move not in "1 2 3 4 5 6 7 8 9".split() or not isSpaceFree(board, int(move)):
        print("What is your next move? (1-9)")
        move = input()
    return int(move)

def chooseRandomMoveFromList(board: List[str], movesList: List[int]) -> int:
    # Returns a valid move from the passed list on the passed board.
    # Returns None if there is no valid move.
    possibleMoves = []
    for i in movesList:
        if isSpaceFree(board, i):

    assert len(possibleMoves) > 0, "Must have space on board"
    return random.choice(possibleMoves)

def getComputerMove(board: List[str], computerLetter: str) -> int:
    # Given a board and the computer's letter,
    # determine where to move and return that move.
    if computerLetter == "X":
        playerLetter = "O"
        playerLetter = "X"

    # Here is our algorithm for our Tic Tac Toe AI:
    # First, check if we can win in the next move
    # This is entertaining a possible future world.
    # Who says computers don't have imagination?
    for i in range(1, 10):
        boardCopy = getBoardCopy(board)
        if isSpaceFree(boardCopy, i):
            makeMove(boardCopy, computerLetter, i)
            if isWinner(boardCopy, computerLetter):
                return i

    # Check if the player could win on his next move, and block them.
    for i in range(1, 10):
        boardCopy = getBoardCopy(board)
        if isSpaceFree(boardCopy, i):
            makeMove(boardCopy, playerLetter, i)
            if isWinner(boardCopy, playerLetter):
                return i

    # Try to take one of the corners, if they are free.
    move = chooseRandomMoveFromList(board, [1, 3, 7, 9])
    if move is not None:
        return move

    # Try to take the center, if it is free.
    if isSpaceFree(board, 5):
        return 5

    # Move on one of the sides.
    return chooseRandomMoveFromList(board, [2, 4, 6, 8])

def isBoardFull(board: List[str]) -> bool:
    # Return True if every space on the board has been taken.
    # Otherwise return False.
    for i in range(1, 10):
        if isSpaceFree(board, i):
            return False
    return True

def main() -> None:
    print("Welcome to Tic Tac Toe!")

    while True:
        # Reset the board
        theBoard = [" "] * 10
        playerLetter, computerLetter = inputPlayerLetter()
        turn = whoGoesFirst()
        print("The " + turn + " will go first.")
        gameIsPlaying = True

        while gameIsPlaying:
            if turn == "player":
                # Player's turn.
                move = getPlayerMove(theBoard)
                makeMove(theBoard, playerLetter, move)

                if isWinner(theBoard, playerLetter):
                    print("Hooray! You have won the game!")
                    gameIsPlaying = False
                    if isBoardFull(theBoard):
                        print("The game is a tie!")
                        turn = "computer"

                # Computer's turn.
                move = getComputerMove(theBoard, computerLetter)
                makeMove(theBoard, computerLetter, move)

                if isWinner(theBoard, computerLetter):
                    print("The computer has beaten you! You lose.")
                    gameIsPlaying = False
                    if isBoardFull(theBoard):
                        print("The game is a tie!")
                        turn = "player"

        print("Do you want to play again? (yes or no)")
        if not input().lower().startswith("y"):

if _name_ == "_main_":

A future assignment: https://en.wikipedia.org/wiki/M,n,k-game


Next: 13-AlgorithmsSoftware.html