Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- """
- Prototype made by Gabriel Lisaca 2017-10-19 11:06pm
- Made for the discord bot for the '4D' tic tac toe"""
- from typing import Tuple
- # TODO: check this with mypy + run tests if you want to
- # Constants used to access the rows and columns (for the internal boards) in an easy manner
- ROW_ONE = 0
- ROW_TWO = 1
- ROW_THREE = 2
- COLUMN_ONE = 0
- COLUMN_TWO = 1
- COLUMN_THREE = 2
- # Constants used to access the internal boards from the main board
- BOARD_UPPER_LEFT = 0
- BOARD_UPPER_MID = 1
- BOARD_UPPER_RIGHT = 2
- BOARD_MIDLEFT = 3
- BOARD_MID = 4
- BOARD_MIDRIGHT = 5
- BOARD_BOTTOM_LEFT = 6
- BOARD_BOTTOM_MID = 7
- BOARD_BOTTOM_RIGHT = 8
- class OutOfBoardBoundsError(Exception):
- pass
- class InternalBoard:
- row_max_idx = 2
- col_max_idx = 2
- def __init__(self, upper_row_num:int):
- self._board = [
- [0, 0, 0],
- [0, 0, 0],
- [0, 0, 0]
- ]
- self._upper_global_row_num = upper_row_num
- self._mid_global_row_num = upper_row_num + 1
- self._bottom_global_row_num = upper_row_num + 2
- def get_row(self, row_num:int):
- if self._is_in_row_bounds(row_num):
- return self._board[row_num]
- else:
- raise OutOfBoardBoundsError("in `get_row` in `InternalBoard` with row_num={}".format(row_num))
- def get_row_num_from_global_num(self, row_num:int) -> int:
- """Takes a row number from the main board and translates it to this boards own internal row number"""
- if row_num == self._upper_global_row_num:
- return ROW_ONE
- elif row_num == self._mid_global_row_num:
- return ROW_TWO
- elif row_num == self._bottom_global_row_num:
- return ROW_THREE
- else:
- raise ValueError("`row_num` is not in the row numbers of this `InternalBoard` object")
- # These 3 properties may be unnecessary. Decide whether to remove later.
- @property
- def row_1(self):
- return self._board[0]
- @property
- def row_2(self):
- return self._board[1]
- @property
- def row_3(self):
- return self._board[2]
- def _is_in_row_bounds(self, row:int) -> bool:
- return row <= InternalBoard.row_max_idx and row >= 0
- def _is_in_column_bounds(self, col:int) -> bool:
- return col <= InternalBoard.col_max_idx and col >= 0
- def _mark_row(self, row:int, mark:int, idx:int):
- if self._is_in_row_bounds(row) and self._is_in_column_bounds(idx):
- self._board[row][idx] = mark
- else:
- raise OutOfBoardBoundsError("in `_mark_row` in `InternalBoard`")
- def mark_first_row(self, mark:int, idx:int):
- self._mark_row(ROW_ONE, mark, idx)
- def mark_second_row(self, mark:int, idx:int):
- self._mark_row(ROW_TWO, mark, idx)
- def mark_third_row(self, mark:int, idx:int):
- self._mark_row(ROW_THREE, mark, idx)
- class GameBoard4DTicTacToe:
- board_max_idx = 8
- board_row_num = 9
- def __init__(self, num_players:int=0):
- self._upper_boards = (InternalBoard(0) for _ in range(3))
- self._mid_boards = (InternalBoard(3) for _ in range(3))
- self._bottom_boards = (InternalBoard(6) for _ in range(3))
- self._boards = [*self._upper_boards, *self._mid_boards, *self._bottom_boards]
- self._upper_board_range = range(0, 3) # Rows 0-2 internally
- self._mid_board_range = range(3, 6) # Rows 3-5 internally
- self._bottom_board_range = range(6, 9) # Rows 6-8 internally
- def place_mark(self, mark:int, place:int, row:int, column:int):
- self.get_board(place)._mark_row(row, mark, column)
- def get_board(self, board_num:int) -> InternalBoard:
- if board_num <= GameBoard4DTicTacToe.board_max_idx and board_num >= 0:
- return self._boards[board_num]
- else:
- raise OutOfBoardBoundsError("in `get_board` in `GameBoard4DTicTacToe")
- def _stringify_board_row(self, row_num:int, board_num:int) -> str:
- """Example return value:
- -----------------------
- '[1][2][3]'"""
- board = self.get_board(board_num)
- board_local_row_num = board.get_row_num_from_global_num(row_num)
- column_1 = board.get_row(board_local_row_num)[COLUMN_ONE]
- column_2 = board.get_row(board_local_row_num)[COLUMN_TWO]
- column_3 = board.get_row(board_local_row_num)[COLUMN_THREE]
- return "[{}][{}][{}]".format(column_1, column_2, column_3)
- def _get_board_nums_in_row(self, row_num:int) -> Tuple[int, int, int]:
- if row_num in self._upper_board_range:
- return (BOARD_UPPER_LEFT, BOARD_UPPER_MID, BOARD_UPPER_RIGHT)
- elif row_num in self._mid_board_range:
- return (BOARD_MIDLEFT, BOARD_MID, BOARD_MIDRIGHT)
- elif row_num in self._bottom_board_range:
- return (BOARD_BOTTOM_LEFT, BOARD_BOTTOM_MID, BOARD_BOTTOM_RIGHT)
- else:
- raise OutOfBoardBoundsError("in `_get_boards_in_row` in `GameBoard4DTicTacToe`")
- def _stringify_whole_board_row(self, row_num:int) -> str:
- """Example return value:
- -----------------------
- '[1][2][3]|[4][5][6]|[7][8][9]'"""
- board_1, board_2, board_3 = self._get_board_nums_in_row(row_num)
- str_board_1 = self._stringify_board_row(row_num, board_1)
- str_board_2 = self._stringify_board_row(row_num, board_2)
- str_board_3 = self._stringify_board_row(row_num, board_3)
- return "{}|{}|{}".format(str_board_1, str_board_2, str_board_3)
- def _stringify_whole_board(self) -> str:
- """Stringifies all the boards in `self._boards`"""
- upper_boards = "\n".join(self._stringify_whole_board_row(row) for row in self._upper_board_range)
- mid_boards = "\n".join(self._stringify_whole_board_row(row) for row in self._mid_board_range)
- bottom_boards = "\n".join(self._stringify_whole_board_row(row) for row in self._bottom_board_range)
- joiner = "\n{}\n".format("-" * 30)
- return joiner.join((upper_boards, mid_boards, bottom_boards))
- def __str__(self):
- return "{0}\n" \
- "{1}\n" \
- "{0}\n".format("-" * 30, self._stringify_whole_board())
- board_inputs = {
- "UL": BOARD_UPPER_LEFT,
- "UM": BOARD_UPPER_MID,
- "UR": BOARD_UPPER_RIGHT,
- "ML": BOARD_MIDLEFT,
- "M" : BOARD_MID,
- "MR": BOARD_MIDRIGHT,
- "BL": BOARD_BOTTOM_LEFT,
- "BM": BOARD_BOTTOM_MID,
- "BR": BOARD_BOTTOM_RIGHT
- }
- row_inputs = {
- "TOP": ROW_ONE,
- "MID": ROW_TWO,
- "BOT": ROW_THREE
- }
- col_inputs = {
- "LEFT" : COLUMN_ONE,
- "MID" : COLUMN_TWO,
- "RIGHT": COLUMN_THREE
- }
- if __name__ == "__main__":
- done = False
- mark = 5
- game = GameBoard4DTicTacToe()
- while not done:
- print(game)
- board_input = input("Which board? (UL|UM|UR|ML|M|MR|BL|BM|BR)").strip().upper()
- row_input = input("Which row? (TOP|MID|BOT)").strip().upper()
- col_input = input("Which column? (LEFT|MID|RIGHT)").strip().upper()
- try:
- board_input_ = board_inputs[board_input]
- row_input_ = row_inputs[row_input]
- col_input_ = col_inputs[col_input]
- except:
- print("Invalid input.")
- continue
- else:
- try:
- game.place_mark(mark=mark, place=board_input_, row=row_input_, column=col_input_)
- except OutOfBoardBoundsError:
- print("Invalid input: Not in board")
- continue
Add Comment
Please, Sign In to add comment