commit c529e6dde62a4f8c4749ef8192efcf4249902e72 Author: 409 Date: Fri May 17 16:46:36 2024 +0200 feat: working version diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bee8a64 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__ diff --git a/constants.py b/constants.py new file mode 100644 index 0000000..833c2cf --- /dev/null +++ b/constants.py @@ -0,0 +1,4 @@ +BOARD_WIDTH = 6 +BOARD_HEIGHT = 6 +ROW_NUMBERS = ['1', '2', '3', '4', '5', '6'] +COLUMN_LETTERS = ['A', 'B', 'C', 'D', 'E', 'F'] diff --git a/main.py b/main.py new file mode 100644 index 0000000..c24b64d --- /dev/null +++ b/main.py @@ -0,0 +1,160 @@ +from constants import BOARD_WIDTH, BOARD_HEIGHT, COLUMN_LETTERS, ROW_NUMBERS +from print_helper import printBoard, bcolors +import random + + +def generateShips(): + ships: list[int] = [] + + for x in range(BOARD_WIDTH): + for y in range(BOARD_HEIGHT): + ships.append(0) + + return ships + + +def fillShipsRandomly(ships: list[int], shipCount: int = 6): + indicies: list[int] = [] + + for i in range(BOARD_WIDTH * BOARD_HEIGHT): + indicies.append(i) + + for i in range(shipCount): + randomIndex = random.randint(0, len(indicies) - 1) + ships[indicies[randomIndex]] = 1 + + indicies.pop(randomIndex) + + +def getShipIndex(x: int, y: int): + return x + y * BOARD_WIDTH + + +def isShip(ship: int): + return ship == 1 + + +def parseBoardInput(boardInput: str): + if len(boardInput) != 2: + return None + + column = boardInput[0] + + if column not in COLUMN_LETTERS: + return None + + row = boardInput[1] + + if row not in ROW_NUMBERS: + return None + + return (COLUMN_LETTERS.index(column), ROW_NUMBERS.index(row)) + + +def printPlayerBoard(board: list[int]): + print("\nYour board:") + printBoard(board) + + +def printEnemyBoard(board: list[int], hideShips: bool = True): + print("\nEnemy's board:") + printBoard(board, hideShips) + + +def remainingShips(board: list[int]): + ships = list(filter(isShip, board)) + + return len(ships) + + +def __main__(): + print(f"{bcolors.FAIL}{bcolors.BOLD}Battleships{bcolors.ENDC}") + # 0 -> our board + # 1 -> the enemy board + boards = [generateShips(), generateShips()] + fillShipsRandomly(boards[1]) + + ships = list(filter(isShip, boards[0])) + + while (len(ships) < 6): + printBoard(boards[0]) + shipInput = input("Where would you like to place a ship (e.g. C4)?\n") + + parsed = parseBoardInput(shipInput) + + if parsed is None: + print("Invalid input. Please provide a location from A1-F6") + continue + + (x, y) = parsed + + boards[0][getShipIndex(x, y)] = 1 + ships = list(filter(isShip, boards[0])) + + print("\n") + + turnIndex = 0 + while remainingShips(boards[(turnIndex + 1) % 2]) > 0: + newTurnIndex = (turnIndex + 1) % 2 + validTargetIndices: list[int] = [] + + enemyBoard = boards[(turnIndex + 1) % 2] + for i in range(len(enemyBoard)): + if enemyBoard[i] < 2: + validTargetIndices.append(i) + + targetIndex = -1 + + if turnIndex == 1: + randomIndex = random.randint(0, len(validTargetIndices) - 1) + targetIndex = validTargetIndices[randomIndex] + else: + printEnemyBoard(boards[(turnIndex + 1) % 2]) + + parsed = None + + while parsed is None: + targetInput = input( + "\nWhere would you like to shoot (e.g. C4)?\n") + + parsed = parseBoardInput(targetInput) + + if parsed is None: + print("Invalid input. Please provide a location from A1-F6") + continue + + (x, y) = parsed + targetIndex = getShipIndex(x, y) + + cellValue = enemyBoard[targetIndex] + newCellValue = 3 + + # hit + if cellValue == 1: + newCellValue = 2 + newTurnIndex = turnIndex + + enemyBoard[targetIndex] = newCellValue + + if cellValue != 1: + if turnIndex == 0: + printEnemyBoard(boards[(turnIndex + 1) % 2]) + else: + printPlayerBoard(boards[(turnIndex + 1) % 2]) + + turnIndex = newTurnIndex + + print("\n" + "—" * 13 + "\n") + + printEnemyBoard(boards[1], False) + printPlayerBoard(boards[0]) + + if remainingShips(boards[0]) > 0: + print(f"{bcolors.OKGREEN}You win!{bcolors.ENDC}") + else: + print(f"{bcolors.FAIL}You lose!{bcolors.ENDC}") + + print("\n" + "—" * 13) + + +__main__() diff --git a/print_helper.py b/print_helper.py new file mode 100644 index 0000000..6017e5a --- /dev/null +++ b/print_helper.py @@ -0,0 +1,45 @@ +from constants import BOARD_WIDTH, BOARD_HEIGHT, ROW_NUMBERS, COLUMN_LETTERS + + +class bcolors: + HEADER = '\033[95m' + OKBLUE = '\033[94m' + OKCYAN = '\033[96m' + OKGREEN = '\033[92m' + WARNING = '\033[93m' + FAIL = '\033[91m' + ENDC = '\033[0m' + BOLD = '\033[1m' + UNDERLINE = '\033[4m' + + +characterPrefixes: list[str] = [bcolors.OKBLUE, + bcolors.BOLD, bcolors.FAIL, bcolors.OKBLUE] +characters: list[str] = ['0', '#', 'X', '-'] + + +def getShipCharacter(ship: int): + return characters[ship] + + +def printBoard(board: list[int], hideShips: bool = False): + i = 0 + print(" ", end="") + for n in range(BOARD_WIDTH): + print(f"{bcolors.BOLD}{COLUMN_LETTERS[n]}{bcolors.ENDC} ", end="") + + print() + + for x in range(BOARD_WIDTH): + print(f"{bcolors.BOLD}{ROW_NUMBERS[x]}{bcolors.ENDC} ", end="") + for y in range(BOARD_HEIGHT): + character = getShipCharacter(board[i]) + prefix = characterPrefixes[board[i]] + + if hideShips and board[i] == 1: + character = getShipCharacter(0) + prefix = characterPrefixes[0] + + print(f"{prefix}{character}{bcolors.ENDC} ", end="") + i += 1 + print()