%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 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.
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.
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)
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.
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.")
Here we will define functions to update the board given a player's move.
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.
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)
Complete the function below to set a position on the board to the given piece. Hint: this should look similar to get_piece
above!
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)
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.
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)