JamCoders

馃捑 Download
In [ ]:
%config InteractiveShell.ast_node_interactivity="none"
%pip install termcolor
def f(globals, locals):
    import base64
    code="ZGVmIG1ha2VfcHJpbnRfbG9jYWxzKCk6IAogICMgSW4gYSBmdW5jdGlvbiB0byBwcmV2ZW50IGxvY2FscyBhbmQgaW1wb3J0cyBmcm9tIGxlYWtpbmcuCiAgICBnbG9iYWwgbWFrZV9wcmludF9sb2NhbHMKICAgIGRlbCBtYWtlX3ByaW50X2xvY2FscyAgIyBPbmx5IHJ1biB0aGlzIGZ1bmN0aW9uIG9uY2UuCgogICAgaW1wb3J0IElQeXRob24KICAgIGltcG9ydCBhc3QKICAgIGltcG9ydCBpbnNwZWN0CgogICAgY2xhc3MgVmlzaXRvcihhc3QuTm9kZVZpc2l0b3IpOgogICAgICAgIGRlZiBfX2luaXRfXyhzZWxmKToKICAgICAgICAgICAgc2VsZi52YXJpYWJsZXMgPSBzZXQoKQogICAgICAgIGRlZiB2aXNpdF9OYW1lKHNlbGYsIG5hbWUpOgogICAgICAgICAgICBzZWxmLnZhcmlhYmxlcy5hZGQobmFtZS5pZCkKICAgICAgICAjIFRPRE86IFBvc3NpYmx5IGRldGVjdCB3aGV0aGVyIHZhcmlhYmxlcyBhcmUgYXNzaWduZWQgdG8uCgogICAgQUxMT1dfVFlQRVMgPSBbaW50LCBmbG9hdCwgc3RyLCBib29sLCBsaXN0LCBkaWN0LCB0dXBsZSwgcmFuZ2VdCiAgICBkZWYgZmlsdGVyX3ZhcmlhYmxlcyh2YXJpYWJsZXMsIGxvY2Fscyk6CiAgICAgICAgZm9yIHYgaW4gdmFyaWFibGVzOgogICAgICAgICAgICBpZiB2IGluIGxvY2FscyBhbmQgdHlwZShsb2NhbHNbdl0pIGluIEFMTE9XX1RZUEVTOgogICAgICAgICAgICAgICAgeWllbGQgdgogIAogICAgIyBVbmZvcnR1bmF0ZWx5LCB0aGVyZSBkb2Vzbid0IHNlZW0gdG8gYmUgYSBzdXBwb3J0ZWQgd2F5IG9mIGdldHRpbmcKICAgICMgdGhlIGN1cnJlbnQgY2VsbCdzIGNvZGUgdmlhIHRoZSBwdWJsaWMgSVB5dGhvbiBBUElzLiBIb3dldmVyLCBiZWNhdXNlCiAgICAjIHdlIGFyZSBnZXR0aW5nIGNhbGxlZCBmcm9tIElQeXRob24gaXRzZWxmIGFuZCB3ZSBhcmUgYWxyZWFkeSBpbnNwZWN0aW5nCiAgICAjIHRoZSBzdGFja3RyYWNlLCB3ZSBtaWdodCBhcyB3ZWxsIGp1c3QgcGVlayBpbnRvIGl0cyBmcmFtZS4uLgogICAgaWYgSVB5dGhvbi5fX3ZlcnNpb25fXyA9PSAiNS41LjAiOgogICAgICAgICMgY29sYWIKICAgICAgICBkZWYgZ2V0X2FzdChmcmFtZSk6CiAgICAgICAgICAgIHJldHVybiBhc3QuTW9kdWxlKGZyYW1lLmZfYmFjay5mX2JhY2suZl9sb2NhbHNbIm5vZGVsaXN0Il0pCiAgICAgICAgZGVmIGZpbmRfbG9jYWxzKGZyYW1lKToKICAgICAgICAgICAgc2hlbGwgPSBmcmFtZS5mX2JhY2suZl9iYWNrLmZfbG9jYWxzWyJzZWxmIl0KICAgICAgICAgICAgcmV0dXJuIHNoZWxsLnVzZXJfbnMKICAgIGVsaWYgSVB5dGhvbi5fX3ZlcnNpb25fXyA9PSAiOC40LjAiOgogICAgICAgICMgbGFiIGNvbXB1dGVycwogICAgICAgIGRlZiBnZXRfYXN0KGZyYW1lKToKICAgICAgICAgICAgcmV0dXJuIGFzdC5Nb2R1bGUoZnJhbWUuZl9iYWNrLmZfYmFjay5mX2xvY2Fsc1sibm9kZWxpc3QiXSkKICAgICAgICBkZWYgZmluZF9sb2NhbHMoZnJhbWUpOgogICAgICAgICAgICByZXR1cm4gZnJhbWUuZl9sb2NhbHMKICAgIGVsc2U6CiAgICAgICAgcHJpbnQoZiJwcmludF9sb2NhbHMoKSBub3Qgc3VwcG9ydGVkIG9uIElQeXRob24gdmVyc2lvbiB7SVB5dGhvbi5fX3ZlcnNpb25fX30iKQoKICAgIGRlZiBnZXRfY2VsbF9uYW1lcyhmcmFtZSk6CiAgICAgICAgdHJlZSA9IGdldF9hc3QoZnJhbWUpCiAgICAgICAgdmlzaXRvciA9IFZpc2l0b3IoKQogICAgICAgIHZpc2l0b3IudmlzaXQodHJlZSkKICAgICAgICByZXR1cm4gZmlsdGVyX3ZhcmlhYmxlcyh2aXNpdG9yLnZhcmlhYmxlcywgZnJhbWUuZl9sb2NhbHMpCgogICAgZGVmIGZpbmRfd2hpY2goZnJhbWUpOgogICAgICAgICMgRnJhbWUgaXMgdGhlIGZyYW1lIHdob3NlIGxvY2FscyB3ZSBhcmUgaW50ZXJlc3RlZCBpbiBwcmludGluZy4KICAgICAgICBpZiBpbnNwZWN0LmdldG1vZHVsZW5hbWUoZnJhbWUuZl9iYWNrLmZfY29kZS5jb19maWxlbmFtZSkgaXMgbm90IE5vbmU6CiAgICAgICAgICAgICMgVGhlIHBhcmVudCBmcmFtZSBvZiB0aGUgaW50ZXJlc3RlZCBmcmFtZSBpcyBhIG1vZHVsZSwgbW9zdCBsaWtlbHkKICAgICAgICAgICAgIyAiaW50ZXJhY3RpdmVzaGVsbCIuIFRoaXMgbWVhbnMgd2UgYXJlIGluIHRoZSBnbG9iYWwgc2NvcGUsIHNpbmNlCiAgICAgICAgICAgICMgb25seSB0aGUgZ2xvYmFsIHNjb3BlIHNob3VsZCBiZSBkaXJlY3RseSBydW4gYnkgdGhlIGludGVyYWN0aXZlIHNoZWxsLgogICAgICAgICAgICByZXR1cm4gc2V0KGdldF9jZWxsX25hbWVzKGZyYW1lKSkKICAgICAgICAjIFRoZSBwYXJlbnQgZnJhbWUgaXMgbm90IGEgbW9kdWxlLCBzbyB3ZSBhcmUgaW4gYSBsb2NhbCBzY29wZS4KICAgICAgICByZXR1cm4gc2V0KGZyYW1lLmZfbG9jYWxzKQoKICAgIGRlZiBwcmludF9sb2NhbHMoKndoaWNoLCB0eXBlcz1GYWxzZSk6CiAgICAgICAgIiIiUHJpbnQgdGhlIGxvY2FsIHZhcmlhYmxlcyBpbiB0aGUgY2FsbGVyJ3MgZnJhbWUuIiIiCiAgICAgICAgaW1wb3J0IGluc3BlY3QKICAgICAgICAjIGN1cnJlbnRmcmFtZSgpIGZyYW1lIGlzIHByaW50X2xvY2Fscy4gV2Ugd2FudCB0aGUgY2FsbGVyJ3MgZnJhbWUKICAgICAgICBmcmFtZSA9IGluc3BlY3QuY3VycmVudGZyYW1lKCkuZl9iYWNrCiAgICAgICAgbG9jYWxzID0gZmluZF9sb2NhbHMoZnJhbWUpCiAgICAgICAgd2hpY2ggPSBzZXQod2hpY2gpIGlmIHdoaWNoIGVsc2UgZmluZF93aGljaChmcmFtZSkKICAgICAgICBsbCA9IHtrOiB2IGZvciBrLCB2IGluIGxvY2Fscy5pdGVtcygpIGlmIGsgaW4gd2hpY2h9CiAgICAgICAgaWYgdHlwZXM6CiAgICAgICAgICAgIHByaW50KCJcbiIuam9pbihmIntrfToge3R5cGUodikuX19uYW1lX199IOKGkCB7dn0iIGZvciBrLCB2IGluIGxsLml0ZW1zKCkpKQogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHByaW50KCI7ICIuam9pbihmIntrfSDihpAge3Z9IiBmb3IgaywgdiBpbiBsbC5pdGVtcygpKSkKCiAgICByZXR1cm4gcHJpbnRfbG9jYWxzCgpwcmludF9sb2NhbHMgPSBtYWtlX3ByaW50X2xvY2Fscygp"
    exec(base64.b64decode(code), globals, locals)
f(globals(), locals())
del f

import termcolor

Connect Four

Connect Four is a game played on a rectangular board. Each player takes turns placing a piece of their own color at the top of the board in a specific column. After a piece is placed, it falls to the lowest unoccupied square of that column. The winner of the game is the player who first places a piece that connects four pieces of their own color.

By completing this notebook, you will have a working version of a Connect Four game. There are four main parts of the game that you will have constructed.

  1. print_board. This function takes the current positions of pieces on the board and "renders" it into a form that the human can see -- by printing the board out. You should have completed this in Connect Four, Part 1.
  2. update_board. This function takes two arguments: (1) the current board state and (2) the move that a player has just made. It edits the board, placing the new piece in the correct position (the lowest unoccupied square of that column).
  3. winning_player. This function takes the board and checks whether a player has won. It should check every vertical and horizontal line of four pieces to see whether they are all of the same player's color. If there is a winner, it should return the winner.
  4. game_loop. This function uses the three above functions to run the game logic. It should print the board and then ask for the player's move. After the player has entered their move, it should update the board, and then check whether a player has won. If yes, it should exit; otherwise, it should continue the game.

1. Print board

Complete the print_board function below. (If you completed "part one," you should be able to copy your function below and make a few slight changes.)

The render board function should print out a visual representation of the board. Recall that we represent the board as a list of lists. Each list is a row in the board, and the first list is the top row.

We would like the printed output to look like:

路 路 路 路 路 路 路 
路 路 路 路 路 路 路 
路 路 路 路 路 路 路 
路 路 O X 路 路 路 
路 路 X O 路 路 路 
路 X O O 路 X 路 

Notice that there is a space between each piece.

In [ ]:
EMPTY_TILE = 0
X_PIECE = 1
O_PIECE = 2

test_board = [
    [0, 0, 0, 0],
    [0, 0, 2, 1],
    [0, 0, 1, 2],
    [0, 1, 2, 2],
]

def print_tile(tile):
    """Given a numerical tile, prints its visual representation."""
    if tile == EMPTY_TILE:
        # No coloring here because we don't know if it's dark or light mode.
        print("路", end = '')
    elif tile == X_PIECE:
        print(termcolor.colored('X', 'red'), end = '')
    elif tile == O_PIECE:
        print(termcolor.colored('O', 'blue'), end = '')
    else:
        raise RuntimeError(f"Error: the tile given was not 0, 1, or 2 (got {tile})")

def print_new_line():
    """Prints a new line."""
    print()

def print_space():
    """Prints a space, without printing a new line."""
    print(' ', end='')

def print_board(board):
    """Prints a visual representation of the board."""
    # YOUR CODE HERE

print_board(test_board)

1.2 Print with coordinates

Running the following code will check whether your print_board function is correct. If it is, then we will define print_board_coords for you. print_board_coords is a function that prints the board called print_board_coords that labels each row and column.

In [ ]:
import base64
code = "ZGVmIHByaW50X2JvYXJkc19jb3JyZWN0KCk6CiAgICBmcm9tIGNvbnRleHRsaWIgaW1wb3J0IHJlZGlyZWN0X3N0ZG91dAogICAgZnJvbSBpbyBpbXBvcnQgU3RyaW5nSU8KCgogICAgZGVmIHByaW50X3NwYWNlKCk6CiAgICAgICAgIiIiUHJpbnRzIGEgc3BhY2UsIHdpdGhvdXQgcHJpbnRpbmcgYSBuZXcgbGluZS4iIiIKICAgICAgICBwcmludCgnICcsIGVuZD0nJykKCiAgICBkZWYgb3VyX3ByaW50X2JvYXJkKGJvYXJkKToKICAgICAgICAiIiJQcmludHMgYSB2aXN1YWwgcmVwcmVzZW50YXRpb24gb2YgdGhlIGJvYXJkLiIiIgogICAgICAgIGZvciByb3cgaW4gYm9hcmQ6CiAgICAgICAgICAgIGZvciB0aWxlIGluIHJvdzoKICAgICAgICAgICAgICAgIHByaW50X3RpbGUodGlsZSkKICAgICAgICAgICAgICAgIHByaW50X3NwYWNlKCkKICAgICAgICAgICAgcHJpbnQoKQoKICAgIHRoZWlycywgb3VycyA9IFN0cmluZ0lPKCksIFN0cmluZ0lPKCkKICAgIHdpdGggcmVkaXJlY3Rfc3Rkb3V0KHRoZWlycyk6CiAgICAgICAgcHJpbnRfYm9hcmQodGVzdF9ib2FyZCkKCiAgICB3aXRoIHJlZGlyZWN0X3N0ZG91dChvdXJzKToKICAgICAgICBvdXJfcHJpbnRfYm9hcmQodGVzdF9ib2FyZCkKICAgIAogICAgdGhlaXJzLCBvdXJzID0gdGhlaXJzLmdldHZhbHVlKCksIG91cnMuZ2V0dmFsdWUoKQogICAgY29ycmVjdCA9IFRydWUKICAgIGZvciBpLCAodCwgbykgaW4gZW51bWVyYXRlKHppcCh0aGVpcnMuc3BsaXRsaW5lcygpLCBvdXJzLnNwbGl0bGluZXMoKSkpOgogICAgICAgIGlmIHQuc3RyaXAoKSAhPSBvLnN0cmlwKCk6CiAgICAgICAgICAgIHByaW50KGYicHJpbnRfYm9hcmQ6IG91dHB1dCByb3cge2l9IGlzIG5vdCBjb3JyZWN0LiIpIAogICAgICAgICAgICBwcmludChmInByaW50X2JvYXJkOiBvdXRwdXQgcm93IHtpfSB3YW50ICd7b30nLCBidXQgZ290ICd7dH0nIikKICAgICAgICAgICAgY29ycmVjdCA9IEZhbHNlCgogICAgaWYgY29ycmVjdDoKICAgICAgICBnbG9iYWwgcHJpbnRfYm9hcmRfY29vcmRzCgogICAgICAgIGRlZiBwcmludF9ib2FyZF9jb29yZHMoYm9hcmQpOgogICAgICAgICAgICBmb3IgaSwgcm93IGluIGVudW1lcmF0ZShib2FyZCk6CiAgICAgICAgICAgICAgICBwcmludChsZW4oYm9hcmQpIC0gaSAtIDEsIGVuZD0iICIpCiAgICAgICAgICAgICAgICBmb3IgdGlsZSBpbiByb3c6CiAgICAgICAgICAgICAgICAgICAgcHJpbnRfdGlsZSh0aWxlKQogICAgICAgICAgICAgICAgICAgIHByaW50X3NwYWNlKCkKICAgICAgICAgICAgICAgIHByaW50KCkKCiAgICAgICAgICAgIGlmIGxlbihib2FyZCkgPiAwOgogICAgICAgICAgICAgICAgbnVtX2l0ZW1zID0gbGVuKGJvYXJkWzBdKQogICAgICAgICAgICAgICAgcHJpbnRfc3BhY2UoKQogICAgICAgICAgICAgICAgcHJpbnRfc3BhY2UoKQogICAgICAgICAgICAgICAgcHJpbnQoIiAiLmpvaW4oc3RyKGkpIGZvciBpIGluIHJhbmdlKG51bV9pdGVtcykpKQoKICAgIHJldHVybiBjb3JyZWN0"
exec(base64.b64decode(code), globals(), locals())
    
if print_boards_correct():
    print_board_coords(test_board)
else:
    print("The output of print_boards does not match our reference")
    print("implementation. See the above errors.")

2 Update board

Here we will define functions to update the board given a player's move.

2.1 Get piece on board

Complete the function below which returns the board piece at the given row and column. Note that the bottom row is number 0; not the top.

In [ ]:
get_piece_test_board = [
    [0, 0, 0, 0],
    [0, 0, 2, 1],
    [0, 0, 1, 2],
    [0, 1, 2, 2],
]

def get_piece(board, row, column):
    """Retrieves the piece at the given row and column in the board."""
    # YOUR CODE HERE

print_board_coords(get_piece_test_board)

print()
print("Tests (want all True):")
print(get_piece(get_piece_test_board, 0, 0) == EMPTY_TILE)
print(get_piece(get_piece_test_board, 0, 1) == X_PIECE)
print(get_piece(get_piece_test_board, 1, 3) == O_PIECE)

2.2 Set piece on board

Complete the function below to set a position on the board to the given piece. Hint: this should look similar to get_piece above!

In [ ]:
set_piece_test_board = [
    [0, 0, 0, 0],
    [0, 0, 2, 1],
    [0, 0, 1, 2],
    [0, 1, 2, 2],
]


def set_piece(board, row, column, piece):
    """Sets the piece on the board at the given row and column."""
    # YOUR CODE HERE

print_board_coords(set_piece_test_board)

print()
print("Tests (want all True):")

set_piece(set_piece_test_board, 0, 0, X_PIECE)
print(get_piece(set_piece_test_board, 0, 0) == X_PIECE)

set_piece(set_piece_test_board, 0, 1, O_PIECE)
print(get_piece(set_piece_test_board, 0, 1) == O_PIECE)

set_piece(set_piece_test_board, 0, 1, X_PIECE)
print(get_piece(set_piece_test_board, 0, 1) == X_PIECE)

set_piece(set_piece_test_board, 0, 1, EMPTY_TILE)
print(get_piece(set_piece_test_board, 0, 1) == EMPTY_TILE)

2.3 Update board

Given a board, a column, and a piece, update the board as if a player inserted that piece at the top of the board. Recall that the piece's position should be set to the bottommost empty tile of the column the player dropped it in. Use get_piece and set_piece to help you write this function.

In [21]:
update_board_test_board = [
    [0, 0, 0, 0],
    [0, 0, 2, 1],
    [0, 0, 1, 2],
    [0, 1, 2, 2],
]

def update_board(board, column, piece):
    """Updates the board as if a player dropped piece into the given column.
    
    If there is no empty tile in that column, does not change the board.
    """
    # YOUR CODE HERE
print_board_coords(update_board_test_board)

print()
print("Tests (want all True):")

update_board(update_board_test_board, 0, X_PIECE)
print(get_piece(update_board_test_board, 0, 0) == X_PIECE)

update_board(update_board_test_board, 0, O_PIECE)
print(get_piece(update_board_test_board, 1, 0) == O_PIECE)

update_board(update_board_test_board, 0, X_PIECE)
print(get_piece(update_board_test_board, 2, 0) == X_PIECE)

update_board(update_board_test_board, 0, O_PIECE)
print(get_piece(update_board_test_board, 3, 0) == O_PIECE)

update_board(update_board_test_board, 1, O_PIECE)
print(get_piece(update_board_test_board, 1, 1) == O_PIECE)
3 路 路 路 路 
2 路 路 O X 
1 路 路 X O 
0 路 X O O 
  0 1 2 3

Tests (want all True):
False
False
False
False
False