Correcting Floats in Battleship

Link to exercise in question: https://www.codecademy.com/courses/learn-python/lessons/battleship/exercises/test-run

The exercise asks to “Thoroughly test your game. Make sure you try a variety of different guesses and look for any errors in the syntax or logic of your program.”

Everything else works great, except for one bug: entering a float value (1.5) as a guess. It broke the game even though my guess_row and guess_col variables were set to “intergerize” their inputs:

guess_row = int(raw_input("Guess Row: "))

I tried defining them as functions that would fail an if statement if the value entered wasn’t an integer, but I can’t get it to work. Here’s what I’ve got for that:

def guess_row(r):
  int(raw_input("Guess Row: "))
  if x is int:
    pass
  else:
    print "Not a whole number!"
    int(raw_input("Guess Row: "))

Even if this worked (it doesn’t) like it does in my head, it would still dead-end if a user entered a float value a second time. I saw on another site a recommendation to do it as a while loop. Something like this:

def guess_row(r):
  int(raw_input("Guess Row: "))
  i = 0
  while i = 0:
    if x is int:
      i += 1
  else:
    print "Not a whole number!"
    int(raw_input("Guess Row: "))

I know that has problems of its own but I can’t even get to a point of testing it because I’m stuck on defining the function. My ultimate goal here is to have the user be re-prompted to guess a row/column if they enter a non-integer value that is within the range (e.g., 1.5). Help, please!

@gryfer

Recursion can probably help you out of this mess. Try this

def guess_row(r):
    try:
        n = int(input("Guess Row: "))
        print("You entered the whole integer: ", n)
    except ValueError:
        print("Not a whole number!")
        return guess_row(r)

It looks like you might be using an old version of Python, so just replace input with raw_input and take the parentheses off of the print statements.

Basically, this will continue to call guess_row until a successful conversion is completed. If you enter a float or a str it will except the ValueError produced by the call to int(n), inform the user, and try again.

1 Like

Thank you so much! This worked. I called a friend who does this for a living primarily in C# and we had previously worked out the following:

def guess_row():
  r = raw_input("Guess Row: ")
  while not r.isdigit():
      print "Not a whole number!"
      r = raw_input("Guess Row: ")
  return int(r)

This worked well enough but then I tried to modify it further so that inputting a number outside of the range 1 - 5 would return an error immediately and not wait until both inputs (row and column) had been provided. I wasn’t able to do it with the code we had put together.

However, I was able to do it almost immediately using this version. Here’s what I ended up putting together:

def guess_row():
  try:
    r = int(raw_input("Guess Row: "))
    if r > 5 or r < 1:
      print "Oops, that's not even in the ocean."
      return guess_row()
    else:
      return r
  except ValueError:
    print "Not a whole number!"
    return guess_row()

Works like a charm. Now I can’t find a way to break the system.

Thank you again. So much more left to learn.

For anyone curious, here’s my final code for Battleship:

from random import randint

board = []
board_size = 5

for x in range(0, board_size):
  board.append(["O"] * board_size)

def print_board(board):
  for row in board:
    print "  ".join(row)
  print

print_board(board)

def random_row(board):
  return randint(1, len(board) - 1)

def random_col(board):
  return randint(1, len(board[0]) - 1)

ship_row = random_row(board)
ship_col = random_col(board)

def try_row():
  try:
    r = int(raw_input("Guess Row: "))
    if r > 5 or r < 1:
      print "-- Oops, that's not even in the ocean. Try again! --"
      return try_row()
    else:
      return r
  except ValueError:
    print "-- Not a whole number! --"
    return try_row()

def try_col():
  try:
    c = int(raw_input("Guess Col: "))
    if c > 5 or c < 1:
      print "-- Oops, that's not even in the ocean. Try again! --"
      return try_col()
    else:
      return c
  except ValueError:
    print "-- Not a whole number! --"
    return try_col()

turns = 3

for turn in range(turns):
  print "Turn %s of " % (turn + 1) + str(turns) + "."
  print
  guess_row = try_row()
  guess_col = try_col()
  if guess_row == ship_row and guess_col == ship_col:
    board[guess_row - 1][guess_col - 1] = "X"
    print
    print "Congratulations! You sank my battleship!"
    print
    print_board(board) 
    break
  else:
    while board[guess_row - 1][guess_col - 1] == "-":
      print
      print "You guessed that one already."
      print
      print_board(board)
      print "Turn %s of " % (turn + 1) + str(turns) + "."
      print
      guess_row = try_row()
      guess_col = try_col()
    if turn + 1 == turns:
      print
      board[guess_row - 1][guess_col - 1] = "-"
      board[ship_row - 1][ship_col - 1] = "?"
      print_board(board)
      print "GAME OVER!"
      break
    else:
      board[guess_row - 1][guess_col - 1] = "-"
      print
      print "You missed my battleship!"
      print
  print_board(board)

It’s a little more complicated than the exercise asked for but I wanted to get it just right. If anyone wants to playtest it for me, I’d be grateful! As it stands, it won’t let you submit a float or a non-integer before proceeding. I also slightly improved the visuals, and added a reveal at the end if you didn’t guess the answer correctly.

1 Like

I will be sure to try this out later. Great job, and I’m glad I was able to help.

1 Like