Teacher's Choice

Tic Tac Toe (Teacher's Choice)

FROM:Zeph Grunschlag in NY: "Your goal is to make a much more elegant version of the Tic Tac Toe board drawer that uses functions instead of duplicate blocks. Please notice link to "complicated" program. You don't need to re-drag all the blocks (see the link to a pre-written Snap! program). BONUS: If you can make your program especially short (script blocs + function blocks in total) I'll give you extra credit."
From Observation Notes Analysis: U3L4: "We should add a Connect Four project to the curriculum, as an extension / optional project."

In Unit 2, you developed the beginnings of several board games and specialized it to play Tic Tac Toe. Now you'll extend that project to keep track of theTic Tac Toe moves and recognize when someone wins. Later, you'll be able to teach the machine to play, too.

Tic Tac Toe video

  1. Open your project U2L4-TicTacToe and save it as U3L4-TicTacToe. That preserves the old version while you modify it here. Play the game, checking to make sure the sprite centers itself in each cell (tile) before stamping itself, as the animation shows.
  2. Players can see which cells are used but the program doesn't keep track, so players can move into cells that are already taken. Give your program a variable current game variable that will become a list of moves. At the start of the game, this list must be initialized empty.
  3. A move lists the player (x or o) and the cell (1 through 9) that the player moved to.
    1. Build a constructor the move by player: () to cell number: () reporter that takes the two inputs and reports the list of those two.
      • You can determine the player from the costume number. Make a reporter player () reporter that translates a costume number (1 or 2) into a player's symbol (x or o). You can use it like this:
        player (costume #) reporting x
      • You can use which cell? to find the cell number.
    2. Build two selectors:
      • player from move {} selector takes a move (a list like {x, 5}) as input and reports only the player (e.g., x).
      • cell number from move {} selector takes a move as input and reports only the cell number (e.g., 5).
  4. Modify the when I am dropped script so that it adds each move to current game. Start a new game and make three or four moves to make sure that it works.
  5. When a player tries to move into a cell, your program must check the list current game to see if that is a free cell.
    • Create a free cell? predicate that takes a cell number as input and tests it against every move in current game. The free cell? block should use a higher order function to extract just the cell numbers from current game as a list and find out if that list contains the cell number that was given as input.
    • Test free cell? with the numbers of both free and occupied cells.
  6. Now modify the when I am dropped script again so that a move is allowed only if it's to a free cell.
  7. Check to make sure your game works the way you want. Save your result.

The next goal would be to create a way for the program to tell if a player's move has resulted in a win. The following instructions suggest one way, but if you want to experiment and come up with your own method, feel free to do that. Then skip down to the last instruction below.

  1. Each winning combination is a list of three cells.
    1. What triples are winning combinations?
    2. How many winning combinations are there?
    3. Create a reporter that outputs a list of all possible winning combinations of cells. It will look something like this:
      TicTacToe wins partial block definition
  2. Click green flag button to clear your tic-tac-toe board and initialize (empty out) current game. Play one game, deliberately letting x win.
  3. To check for wins, your script will need to know where the players have moved. Experiment with the following scripts, which report information about the game you just played. In each case, figure out what those results tell you about that game, and figure out how the script generated those results.
    1. Talk with Your Partner item (1) of (current game)
    2. keep items such that ((player from move {}) = (x)) from (current game)
    3. map (cell number from move {}) over (kep items such that ((player from move {}) = (x)) from (current game))
    4. Build reporter blocks player x cells and player o cells that report a list of cells that the players occupy.
      player x cells reporting {1, 5, 9} player o cells reporting {2, 6}
  4. Now that you can determine what cells each player is in, you can figure out whether some subset of those cells is a win.
    1. item (1) of (TicTacToe wins)
    2. keep items such that ((list {1, 2, 3}) contains()) from (player x cells)
    3. keep items such that ((item (1) of (TicTacToe wins)) contains ()) from (player x cells)
  5. Create a predicate block do {} satisfy {} ?that takes a list of a player's cells and one winning combination and reports whether those cells contain all three elements of the winning combination. One way to do it could start like this: do {cells} satisfy {winning combination}? : (report ((cells) contains (item (1) of (winning combintion))) and ...)
  6. Test it for three different winning combinations.
  7. What does map (do (player x cells) satisfy {} ?) over (TicTacToe wins) report?
  8. Build a block, win? that takes a player (x or o) as input and checks to see if that player wins.
  9. Modify your when I am dropped script so that when a player wins the game, the program notifies the players.
  1. There are many small improvements you could make. For one thing, when a player wins, the sprite could hide itself so that no more moves are allowed. What else might you want to change or improve?