How can I be sure I tested my battleship project properly?

Question

How can I be sure I tested my battleship project properly?

Answer

There are a couple test cases you should run through and if you’re met with any errors, you’ll know where to look in your code based on what you’re trying to test.

  1. Guess a row and/or column value that is 5 or greater, your code should print that it’s not in the ocean and loop again.
  2. Guess an incorrect coordinate that you haven’t guessed before, your code should tell you that you missed.
  3. Guess another incorrect one that you have guessed already, and your code should tell you that.
  4. Guess incorrectly on your 4th turn and you should see game over.
  5. Guess correctly at any time and you should see a congratulations and your code should exit!
3 Likes

Hello! How do i rectify the case where the user does not input any coordinates and presses the ‘enter’ button?

I tried using the below code

  if guess_row == ship_row and guess_col == ship_col:
    print "Congratulations! You sank my battleship!"
    break

  elif guess_row == '' or guess_col == '':
    print "Please enter the coordinates you want to shoot!"

but the system still gives me an error

and what about the user entering letters? The problem occurs when trying to convert anything to integer which can’t be converted to integer, so maybe look into that? you could consider isdigit or catch the exception?

5 Likes

I came here to ask this very question. Thanks for linking this!

Why do we need to indent 4 spaces below the ‘for turn in range(4):’ statement; why not just once?

there is is a difference between need and best practice. 4 spaces is the standard used (see pep8):

https://www.python.org/dev/peps/pep-0008/

using 1 space could make it really hard to see how everything is nested, you would have to stare at the screen really intense.

1 Like

i managed to pull it of by turning the guess_col and guess_row into an integer after running it thru an if else statement that checks if either guess_col or guess_row has any letters in it using isalpha().
if that is true, it counts as a guess and the user will have to try again. if that is false it wil turn guess_col and guess_row into a integer and then run the existing code.

from random import randint

board = []

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

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

print_board(board)

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

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

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


# Everything from here on should be in your for loop
# don't forget to properly indent!
for turn in range(4):
  print "Turn", turn + 1
  guess_row = raw_input("Guess Row: ")
  guess_col = raw_input("Guess Col: ")
	
  if guess_row.isalpha() or guess_col.isalpha():
    print "this is not a number"
  else:
    guess_row = int(guess_row)
    guess_col = int(guess_col)
    if guess_row == ship_row and guess_col == ship_col:
      print "Congratulations! You sank my battleship!" 
      break
    else:
      if guess_row not in range(5) or \
        guess_col not in range(5):
        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"
        if turn == 3:
          print "Game Over"
        else:
          print_board(board)

there are more characters then letters:

image

although less likely the user will enter them, it can still crash your program. The better approach is to verify the input is actually an integer, this eliminates all other possibilities.

2 Likes

stetmin94, i did not think of this. thank you for the tip!

Check my code, you can use .isdigit() function in string data types to check that before doing anything else.

from random import randint

board = []

for x in range(5):
  board.append(["O"] * 5)

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

print_board(board)

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

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

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

# Debbuging code
print ship_row
print ship_col

# Everything from here on should go in your for loop!
# Be sure to indent four spaces!
for turn in range(4):
  print "Turn", turn + 1

  guess_row = raw_input("Guess Row: ")
  guess_col = raw_input("Guess Col: ")
  
  # vefiry that the input is a digit
  if not guess_row.isdigit() and not guess_col.isdigit():
    print "Please enter the coordinates you want to shoot!"
  else:
    guess_row = int(guess_row)
    guess_col = int(guess_col)
    
    if guess_row == ship_row and guess_col == ship_col:
      print "Congratulations! You sunk my battleship!"
      break
    else:
      if (guess_row < 0 or guess_row > 4) or (guess_col < 0 or guess_col > 4):
        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"
        print_board(board)

  if turn == 3:
    print "Game Over"
1 Like

i was very confused with the lesson plan, so i kept using the ‘Solution’ button in most exercise. but even so, at the last exercise, the code doesn’t work properly. when i miss the battleship, it doesn’t prompt me to try again until my turns have used up. is there something wrong?

File “main.py”, line 47, in
board.append[“0” * 10]
TypeError: ‘builtin_function_or_method’ object has no attribute ‘getitem

this is what my code says when I try to run it. What does it mean?

getitem is used when you access something by index, for example:

my_list = ['a', 'b', 'c']
print my_list[0] # accessing list by index, which uses getitem

append is a built-in function which can’t accessed by index, you want to call the append function, how do you do that?

1 Like

Would you be able to paste in your code?
That way we’d have a better idea of where the issue is.

One would think that at this point in time the member is long past this question making it by now meaningless to respond. Please do not resurrect moribund topics.