Previous: 11-TypeHints.html
* https://xkcd.com/1638/
* https://www.explainxkcd.com/wiki/index.php/1638:_Backslashes
document.querySelector('video').playbackRate = 1.2
Books:
* 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
Code (to be stepped through in spyder3 and/or pudb3):
12-Strings/00_strings.py
++++++++++++++++++
Cahoot-12.1
https://mst.instructure.com/courses/58101/quizzes/56172
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…
https://en.wikipedia.org/wiki/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.
https://en.wikipedia.org/wiki/OXO
* 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:
https://inventwithpython.com/invent4thed/chapter10.html
Overall strategy
Get computers move (The AI)
The code:
12-Strings/tictactoe.py
#!/usr/bin/python3
# -*- 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("-+-+-")
print(board[4] + "|" + board[5] + "|" + board[6])
print("-+-+-")
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"]
else:
return ["O", "X"]
def whoGoesFirst() -> str:
# Randomly choose the player who goes first.
random.seed(0)
if random.randint(0, 1) == 0:
return "computer"
else:
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:
boardCopy.append(i)
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):
possibleMoves.append(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"
else:
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.
drawBoard(theBoard)
move = getPlayerMove(theBoard)
makeMove(theBoard, playerLetter, move)
if isWinner(theBoard, playerLetter):
drawBoard(theBoard)
print("Hooray! You have won the game!")
gameIsPlaying = False
else:
if isBoardFull(theBoard):
drawBoard(theBoard)
print("The game is a tie!")
break
else:
turn = "computer"
else:
# Computer's turn.
move = getComputerMove(theBoard, computerLetter)
makeMove(theBoard, computerLetter, move)
if isWinner(theBoard, computerLetter):
drawBoard(theBoard)
print("The computer has beaten you! You lose.")
gameIsPlaying = False
else:
if isBoardFull(theBoard):
drawBoard(theBoard)
print("The game is a tie!")
break
else:
turn = "player"
print("Do you want to play again? (yes or no)")
if not input().lower().startswith("y"):
break
if _name_ == "_main_":
main()
A future assignment: https://en.wikipedia.org/wiki/M,n,k-game
++++++++++++++++++
Cahoot-12.2
https://mst.instructure.com/courses/58101/quizzes/56173