4
\$\begingroup\$

I'm working on a 2-player battleships game in python, although the game is slightly buggy. It sometimes does not allow me to play another game once the first game has finished, and it does not change the location of the ship once the game has moved onto game 2. I'm not entirely sure how these problems arise only that they only seem to occur sporadically. I've been told to include a main() function and pass all my functions through there but I'm not sure how to get started on that.

I've also been told that manipulating global variables are a problem in this game but I'm not sure why, perhaps you could tell me where I'm going wrong and how to improve the functionality of the game?

from random import randint

game_board = []
player_one = {
    "name": "Player 1",
    "wins": 0,
    "lose": 0
}
player_two = {
    "name": "Player 2",
    "wins": 0,
    "lose": 0
}
total_turns = 0

# Building our 5 x 5 board


def build_game_board(board):
    for item in range(5):
        board.append(["O"] * 5)


def show_board(board):
    print("Find and sink the ship!")
    for row in board:
        print(" ".join(row))

# Defining ships locations


def load_game(board):
    print("WELCOME TO BATTLESHIP!")
    print("START")
    del board[:]
    build_game_board(board)
    show_board(board)
    ship_col = randint(1, len(board))
    ship_row = randint(1, len(board[0]))
    return {
        'ship_col': ship_col,
        'ship_row': ship_row,
    }

ship_points = load_game(game_board)

# Players will alternate turns.


def player_turns():
    if total_turns % 2 == 0:
        return player_two
    else:
        return player_one

# Allows new game to start


def play_again():
    answer = str(input("Would you like to play again?"))
    if answer == "yes" or answer == "y":
        total_turns = 0
        ship_points = load_game(game_board)
    else:
        print("Thanks for playing!")
        exit()

# What will be done with players guesses


def input_check(ship_row, ship_col, player, board):
    guess_col = 0
    guess_row = 0
    while True:
        try:
            guess_row = int(input("Guess Row:")) - 1
            guess_col = int(input("Guess Col:")) - 1
        except ValueError:
            print("Enter a number only.")
            continue
        else:
            break
    match = guess_row == ship_row - 1 and guess_col == ship_col - 1
    not_on_game_board = (guess_row < 0 or guess_row > 4) or (guess_col < 0 or guess_col > 4)

    if match:
        player["wins"] += 1
        print("Congratulations! You sunk my battleship!")
        print("Thanks for playing!")
        play_again()
    elif not match:
        if not_on_game_board:
            print("Oops, that's not even in the ocean.")
        elif board[guess_row][guess_col] == "X":
            print("You guessed that one already.")
        else:
            print("You missed my battleship!")
            board[guess_row][guess_col] = "X"
        show_board(game_board)
    else:
        return 0

# GAME - 3 games in total

for games in range(3):
    games += 1
    for turns in range(6):
        total_turns += 1
        if player_turns() == player_one:
            print("Player One")
            input_check(
                ship_points['ship_row'],
                ship_points['ship_col'],
                player_one, game_board
            )
        elif player_turns() == player_two:
            print("Player Two")
            input_check(
                ship_points['ship_row'],
                ship_points['ship_col'],
                player_two, game_board
            )
        else:
            continue
        if total_turns == 6 and player_turns() == player_one:
            print("The game is a draw")
            play_again()
        elif total_turns == 6 and player_turns() == player_two:
            print("The game is a draw")
            play_again()
        else:
            continue
\$\endgroup\$
2
\$\begingroup\$

This is a bug, a for-loop automatically increments "games" by one:

for games in range(3):
    games += 1

In play_again(); input is automatically of type string, so no need for:

answer = str(input())

Rather:

answer = input()

You should also split logical parts of the code like if-else statements with newline. This makes the code much easier to read. Finally, you can avoid three lines at the end by doing this:

if total_turns == 6:
    print("The game is a draw")
    play_again()

Instead of using if-elif. I tried playing and I didn't come across the bugs you mentioned. About using main(); the idea is to build a main() function and make it run as such:

class AClass:
    def AFunction():
        # do something

def main():
    input("Enter 'start' to start game: ")
    Aclass.AFunction()

if __name__ == "main":
    main()
\$\endgroup\$
1
\$\begingroup\$

Little improvement:

In play_again() function, if the user types "Y" to mean "yes", the game will exit. So it is better to change:

answer = str(input("Would you like to play again?"))

to:

answer = input("Would you like to play again?").lower()

P.S. str() is unnecessary here as answer is a string by default:

>>> answer = input("Would you like to play again?")
Would you like to play again?
>>> type(answer)
<class 'str'>
>>> 
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.