161 lines
3.8 KiB
Python
161 lines
3.8 KiB
Python
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__()
|