Compare commits
2 Commits
7f6a01e2fb
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| a28dfac7a8 | |||
| 335836b03e |
@@ -60,7 +60,9 @@ class AIPlayer(Player):
|
||||
def guess(self, opponent: Player) -> Coordinate:
|
||||
for guess in self.guesses:
|
||||
if self.coord_status(guess, opponent) == CoordStatus.HIT:
|
||||
return self.guess_near(guess, opponent)
|
||||
candidate = self.guess_near(guess, opponent)
|
||||
if candidate:
|
||||
return candidate
|
||||
|
||||
while True:
|
||||
guess = random.choice(opponent.board.columns), random.choice(opponent.board.rows)
|
||||
|
||||
@@ -4,15 +4,30 @@ from typing import List
|
||||
|
||||
from .player import Player
|
||||
from .ship import ShipType
|
||||
from .ui import clear_screen, format_board, opponent_cell_fn
|
||||
from .ui import clear_screen, opponent_cell_fn, format_boards
|
||||
|
||||
|
||||
def show_boards(players: List[Player], active: Player):
|
||||
players = list(sorted(players, key=lambda p: p.name))
|
||||
active_idx = players.index(active)
|
||||
|
||||
cell_fns = [
|
||||
opponent_cell_fn(players[0], players[1], players[0].last_guess),
|
||||
opponent_cell_fn(players[1], players[0], players[1].last_guess)
|
||||
]
|
||||
boards = [players[1].board, players[0].board]
|
||||
titles = [player.name for player in players]
|
||||
titles[active_idx] = f"[ {titles[active_idx]} ]"
|
||||
print(format_boards(cell_fns, boards, titles))
|
||||
|
||||
|
||||
def play_turn(player: Player, opponent: Player):
|
||||
guess = player.guess(opponent)
|
||||
player.last_guess = guess
|
||||
player.guesses.add(guess)
|
||||
|
||||
clear_screen()
|
||||
print(format_board(opponent_cell_fn(player, opponent, guess), opponent.board))
|
||||
show_boards([player, opponent], player)
|
||||
print()
|
||||
|
||||
ship = opponent.ship_at(guess)
|
||||
@@ -23,8 +38,7 @@ def play_turn(player: Player, opponent: Player):
|
||||
else:
|
||||
print(f"{player.name}: Hit!")
|
||||
|
||||
print("\n")
|
||||
input("Press ENTER to continue.")
|
||||
input("\nPress ENTER to continue.")
|
||||
|
||||
|
||||
def play_battleship(player_1: Player, player_2: Player, ship_types: List[ShipType]):
|
||||
|
||||
@@ -5,8 +5,7 @@ from typing import List
|
||||
from .bs_types import Coordinate
|
||||
from .player import Player, PlacementError
|
||||
from .ship import Ship, ShipType
|
||||
from .ui import read_coordinate, format_board, player_cell_fn, read_orientation, opponent_cell_fn, \
|
||||
clear_screen
|
||||
from .ui import read_coordinate, format_board, player_cell_fn, read_orientation, clear_screen
|
||||
|
||||
|
||||
class HumanPlayer(Player):
|
||||
@@ -17,7 +16,7 @@ class HumanPlayer(Player):
|
||||
clear_screen()
|
||||
|
||||
def place_ship(self, ship_type: ShipType) -> Ship:
|
||||
current_board = format_board(player_cell_fn(self), self.board)
|
||||
current_board = format_board(player_cell_fn(self), self.board, self.name)
|
||||
|
||||
while True:
|
||||
clear_screen()
|
||||
@@ -40,12 +39,7 @@ class HumanPlayer(Player):
|
||||
input()
|
||||
|
||||
def guess(self, opponent: Player) -> Coordinate:
|
||||
current_board = format_board(opponent_cell_fn(self, opponent), opponent.board)
|
||||
while True:
|
||||
clear_screen()
|
||||
print(current_board)
|
||||
print()
|
||||
|
||||
coord = read_coordinate(f"{self.name}, where would you like to aim your cannons? ", opponent.board)
|
||||
|
||||
if coord not in self.guesses:
|
||||
|
||||
@@ -20,6 +20,7 @@ class Player:
|
||||
self.board = board
|
||||
self.guesses: Set[Coordinate] = set()
|
||||
self.ships: List[Ship] = []
|
||||
self.last_guess: Optional[Coordinate] = None
|
||||
|
||||
def place_ships(self, ship_types: List[ShipType]):
|
||||
for ship_type in ship_types:
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import itertools
|
||||
import os
|
||||
import re
|
||||
from string import ascii_uppercase
|
||||
from typing import Optional
|
||||
from typing import Optional, List
|
||||
|
||||
from .board import Board
|
||||
from .ship import Ship, ShipOrientation, ShipType
|
||||
@@ -95,12 +96,20 @@ def opponent_cell_fn(player, opponent, latest: Optional[Coordinate] = None) -> C
|
||||
return _cell
|
||||
|
||||
|
||||
def format_board(cell_fn: CellFn, board: Board, row_separator="-", column_separator="|", intersection="+") -> str:
|
||||
def format_board(
|
||||
cell_fn: CellFn,
|
||||
board: Board,
|
||||
title: str,
|
||||
row_separator="-",
|
||||
column_separator="|",
|
||||
intersection="+"
|
||||
) -> str:
|
||||
"""
|
||||
Formats the current board state as a string.
|
||||
|
||||
:param cell_fn: A rendering function that takes a cell coordinate and returns a string.
|
||||
:param board: The board we're rendering.
|
||||
:param title: A title to place at the top
|
||||
:param row_separator: A character to render between rows.
|
||||
:param column_separator: A character to render between columns.
|
||||
:param intersection: A character to render at intersections.
|
||||
@@ -109,8 +118,8 @@ def format_board(cell_fn: CellFn, board: Board, row_separator="-", column_separa
|
||||
y_label_width = len(str(board.width+1))
|
||||
cell_width = 3
|
||||
|
||||
rendered_board = ""
|
||||
divider = " " * y_label_width + column_separator + (row_separator*cell_width + intersection) * board.width + "\n"
|
||||
rendered_board = title.center(len(divider)) + "\n"
|
||||
|
||||
# Render the header with tickmarks for the X axis
|
||||
# We use letters to represent the X axis so that each header will always be a single cell
|
||||
@@ -137,6 +146,27 @@ def format_board(cell_fn: CellFn, board: Board, row_separator="-", column_separa
|
||||
return rendered_board
|
||||
|
||||
|
||||
def format_boards(
|
||||
cell_fns: List[CellFn],
|
||||
boards: List[Board],
|
||||
titles: List[str],
|
||||
row_separator="-",
|
||||
column_separator="|",
|
||||
intersection="+",
|
||||
padding=4,
|
||||
) -> str:
|
||||
rendered_boards = [format_board(fn, board, title, row_separator, column_separator, intersection).splitlines(keepends=False)
|
||||
for fn, board, title in zip(cell_fns, boards, titles)]
|
||||
max_row_length = max(len(row) for row in itertools.chain(*rendered_boards))
|
||||
spaces = " " * padding
|
||||
|
||||
merged_rows = [spaces.join(row.ljust(max_row_length) for row in rows)
|
||||
for rows in zip(*rendered_boards)]
|
||||
render = "\n".join(merged_rows)
|
||||
|
||||
return render
|
||||
|
||||
|
||||
def print_test_board():
|
||||
from .player import Player
|
||||
board = Board(7, 7)
|
||||
|
||||
Reference in New Issue
Block a user