battleship_visualizer.py 5.43 KB
Newer Older
Adam Blank's avatar
Adam Blank committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
"""
CS1 24fa - Assignment 1
Visualization functions for an implementation of the battleship game.
"""

from battleship_helpers import *


BLUE = "\033[34m"
GREEN = "\033[32m"
RED = "\033[31m"
DEFAULT = "\033[0m"
CELL_WIDTH_WITH_BORDERS = 6
CELL_WIDTH = 4


def print_board_header(board):
    """
    Print the header of the board, showing the column numbers.
     
    Args:
        board (list[list[bool]]): 2D list representing player's ship board.
    """
    print('\n       ' + '     '.join([str(i+1) for i in range(len(board))]))


def make_visual_ship_board(board):
    """
    Create visual representation of ship board.
     
    Args:
        board (list[list[bool]]): 2D list representing player's ship board. 
        False represents an empty space, and True represents a ship.

    Returns:
        (list[list[str]]): 2D list representing the visual state of the board.
    """
    visual_board = []
    for i in range(len(board)):
        visual_board.append([])
        for j in range(len(board)):
            if not board[i][j]:
                visual_board[i].append(' ')
            else:
                visual_board[i].append(f"{BLUE}S{DEFAULT}")
    return visual_board


def print_board_rows(visual_board):
    """
    Print the rows of the board based on the visual representation.
     
    Args:
        visual_board (list[list[str]]): 2D list representing the visual state 
        of the board.
    """
    for i in range(len(visual_board)):
        print(CELL_WIDTH*' ' + '-' * (CELL_WIDTH_WITH_BORDERS*len(visual_board)+1))
        print(f"  {i+1} |  {'  |  '.join(visual_board[i])}  |")
    print(CELL_WIDTH*' ' + '-' * (CELL_WIDTH_WITH_BORDERS*len(visual_board)+1) + '\n')


def visualize_ship_board(board):
    """
    Display the current player's ship board.
     
    Args:
        board (list[list[bool]]): 2D list representing player's ship board. 
        False represents an empty space, and True represents a ship.
    """
    print_board_header(board)
    visual_board = make_visual_ship_board(board)
    print_board_rows(visual_board)


def get_sunk_ships(ships, board_hits, player):
    """
    Determine which ships have been sunk based on the hits received.
     
    Args:
        ships (list[list[tuple[int, int]]]): ships' coordinates.
        board_hits (list[list[list[bool]]]): players' hit boards.
        player (int): index of player (0 for Player 1, 1 for Player 2).

    Returns:
        (list[tuple[int, int]]): coordinates of sunk ships.
    """
    sunk_ships = []
    for ship in ships:
        sunk = True
        for coord in ship:
            if board_hits[player][coord[1]][coord[0]] == 0:
                sunk = False
                return
        if sunk:
            sunk_ships.extend(ship)
    return sunk_ships


def make_visual_playing_board(board_ships, board_hits, sunk_ships, player, board_no):
    """
    Create a visual representation of the game board for display.
     
    Args:
        board_ships (list[list[list[bool]]]): players' ship boards. 
        False indicates no ship, and True indicates a ship.
        board_hits (list[list[list[bool]]]): players' hit boards. 
        False indicates no hit, and True indicates a hit.
        sunk_ships (list[tuple[int, int]]): coordinates of sunk ships.
        player (int): index of player (0 for Player 1, 1 for Player 2).
        board_no (int): index of board to visualize (0 for opponent's board 
        without ships, 1 for opponent's board with ship visibility)

    Returns:
        (list[list[str]]): visual state of the board.
    """
    visual_board = []
    for i in range(len(board_ships[player])):
        visual_board.append([])
        for j in range(len(board_ships[player])):
            if not board_ships[get_opponent(player)][i][j] and \
                not board_hits[player][i][j]:
                visual_board[i].append(' ')
            elif not board_ships[get_opponent(player)][i][j] and \
                board_hits[player][i][j]:
                visual_board[i].append('*')
            elif board_ships[get_opponent(player)][i][j] and \
                not board_hits[player][i][j] and board_no == 0:
                visual_board[i].append(' ')
            elif board_ships[get_opponent(player)][i][j] and \
                not board_hits[player][i][j]:
                visual_board[i].append(f"{BLUE}S{DEFAULT}")
            elif (j, i) in sunk_ships:
                visual_board[i].append(f"{RED}*{DEFAULT}")
            else:
                visual_board[i].append(f"{GREEN}*{DEFAULT}")
    return visual_board


def visualize_boards(board_ships, board_hits, player, ships):
    """
    Display a visualization of the current player's ship board and hit boards.
     
    Args:
        board_ships (list[list[list[bool]]]): players' ship boards. 
        False indicates no ship, and True indicates a ship.
        board_hits (list[list[list[bool]]]): players' hit boards. 
        False indicates no hit, and True indicates a hit.
        player (int): index of player (0 for Player 1, 1 for Player 2).
        ships (list[list[tuple[int, int]]]): ships' coordinates.
    """
    for x in range(2):
        print_board_header(board_ships[player])
        sunk_ships = get_sunk_ships(ships, board_hits, player)
        visual_board = make_visual_playing_board(board_ships, board_hits, sunk_ships, player, x)
        print_board_rows(visual_board)

        if x == 0:
            print('=' * (CELL_WIDTH_WITH_BORDERS*(len(board_ships[player])+1)+1))
            player = get_opponent(player)