Created
April 19, 2020 04:17
-
-
Save Levi-Lesches/3c439e2e2d436f3f304ce1610744a68d to your computer and use it in GitHub Desktop.
A Python implementation of Battleship (deliberately avoiding OOP)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Battleship | |
Concepts used: | |
- constants | |
- functions (I/O) | |
- if on one line | |
- random.choice and random.shuffle | |
- printing with an `end` | |
- tuples | |
- is | |
- break | |
- ternary operator | |
- 2-d lists | |
- any and all | |
- list comprehension | |
- map and lambda | |
""" | |
from random import choice, shuffle | |
BOARD_SIZE = 10 | |
EMPTY_CELL = "_" | |
SHIP_OR_HIT = "!" | |
MISS = "X" | |
SHIPS = [5, 4, 3, 3, 2] | |
def generate_map() -> [list]: | |
return [[None for _ in range(BOARD_SIZE)] for __ in range(BOARD_SIZE)] | |
def print_board(board): | |
for row in board: | |
for col in row: | |
if col is None: letter = EMPTY_CELL | |
elif col is True: letter = SHIP_OR_HIT | |
elif col is False: letter = MISS | |
print(letter, end = " ") | |
print() | |
def place_ship(board, ship_length): | |
horizontal = choice([True, False]) | |
available_rows = list(range(len(board))) | |
shuffle(available_rows) | |
for row in available_rows: | |
ship_coordinates = None | |
available_cols = list(range(len(board [row]))) | |
shuffle(available_cols) | |
for col in available_cols: | |
if (horizontal and len(board [row]) - col >= ship_length): | |
available_coordinates = [ | |
(row, col + offset) for offset in range(ship_length) | |
] | |
if all( | |
board [coordinate [0]] [coordinate [1]] is None | |
for coordinate in available_coordinates | |
): ship_coordinates = available_coordinates | |
elif(not horizontal and len(board) - row >= ship_length): | |
available_coordinates = [ | |
(row + offset, col) for offset in range(ship_length) | |
] | |
if all( | |
board [coordinate [0]] [coordinate [1]] is None | |
for coordinate in available_coordinates | |
): ship_coordinates = available_coordinates | |
if ship_coordinates is not None: break | |
if ship_coordinates is not None: | |
for coordinate in ship_coordinates: | |
board [coordinate [0]] [coordinate [1]] = True | |
break | |
return ship_coordinates | |
def pick_coordinate(guesses): | |
available_coordinates = [ | |
(row, col) | |
for row in guesses | |
for col in row | |
if col is None | |
] | |
return choice(available_coordinates) | |
def did_hit(coordinate, board): | |
return board [coordinate [0]] [coordinate [1]] is True | |
def mark_result(coordinate, result, guesses): | |
guesses [coordinate [0]] [coordinate [1]] = result | |
def setup_board(board): | |
return [ | |
place_ship(board, ship) | |
for ship in SHIPS | |
] | |
def still_playing(ship_positions): | |
return any(ship for ship in ship_positions) | |
def get_coordinate_from_user(): | |
return tuple(map(lambda num: int(num) - 1, input("Enter a coordinate [row, col]: ").split(", "))) | |
def main(): | |
computer_board = generate_map() | |
computer_guesses = generate_map() | |
user_guesses = generate_map() | |
ship_positions = setup_board(computer_board) | |
computer_turn = False | |
print_board(computer_board) | |
print() | |
while still_playing(ship_positions): | |
if not computer_turn: | |
print_board(user_guesses) | |
coordinate = get_coordinate_from_user() | |
result = did_hit(coordinate, computer_board) | |
print("Hit!" if result else "Miss!") | |
mark_result(coordinate, result, user_guesses) | |
if result: | |
for ship in ship_positions: | |
if coordinate in ship: | |
ship.remove(coordinate) | |
if not ship: print("You sunk my ship!") | |
print("Game over! You win!") | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment