# Python - 13. Not again - Elif Statement

#1

Hi guys!

That’s the console’s output when I guess a number out of range:

O O O O O
O O O O O
O O O O O
O O O O O
O O O O O
1
2
Guess Row: 8
Guess Col: 5
Traceback (most recent call last):
_ File “python”, line 31, in _
IndexError: list index out of range

That’s the output when the answer is in range:

O O O O O
O O O O O
O O O O O
O O O O O
O O O O O
2
3
Guess Row: 4
Guess Col: 4
You missed my battleship!
O O O O O
O O O O O
O O O O O
O O O O O
O O O O X

This is my 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)
print ship_row
print ship_col
guess_row = int(raw_input("Guess Row: "))
guess_col = int(raw_input("Guess Col: "))

if guess_row == ship_row and guess_col == ship_col:
print "Congratulations! You sank my battleship!"
# Where I think elif would be appropriate, too:
elif (board[guess_row][guess_col] == 'X'):
print "You guessed that one already."
else:
if guess_row not in range(5) or \
guess_col not in range(5):
print "Oops, that's not even in the ocean."
# Where "elif" should be according to the solution:
else:
print "You missed my battleship!"
board[guess_row][guess_col] = "X"
print_board(board)

For me it makes also sense to place “elif” after the first “if” instead of the second. But if I do so there is this error message above. Why doesn’t it work like this ?

Regards
JK

#2

Hi there.

I’ve noticed that you’ve not posted all your code from the exercise. The codeblock in your post is 16 lines long, but in the traceback you’ve posted the error is on (or around) line 24.

Without the full program, we can’t see where the problem is. Nothing that you’ve written in the code you’ve posted looks obviously wrong, and if I run it on repl.it I don’t get an error… but obviously you are, for some reason.

If you post all your code, we might be able to figure out where it’s breaking.

#3

Yeah you’re right. Sry

#4

Looking at your updated post, I believe that you’re getting this error:

and you’re after some help in figuring out why?

Here’s the relevant bit of the code:

if guess_row == ship_row and guess_col == ship_col:
print "Congratulations! You sank my battleship!"
# Where I think elif would be appropriate, too:
elif (board[guess_row][guess_col] == 'X'):
print "You guessed that one already."
else:
if guess_row not in range(5) or \
guess_col not in range(5):
print "Oops, that's not even in the ocean."
# Where "elif" should be according to the solution:
else:
print "You missed my battleship!"
board[guess_row][guess_col] = "X"
print_board(board)

Let’s step through what Python will do when we make a guess. Let’s put the battleship in the centre, and let’s say we guess that it’s in (3,5).

The first if statement, if guess_row == ship_row and guess_col == ship_col:, checks whether we’ve made a correct guess. In this case, we haven’t and we’ve missed.

Python then immediately goes to your elif line elif (board[guess_row][guess_col] == 'X'): to check if we’ve made this guess before.

The problem is, we’re guessing that the battleship is in row 3, column 5. So, Python rightly tries to check whether there’s an X in board[3][5]. However, as we’re working with a 5 x 5 board, the highest index that exists in either list that makes up the board is 4. As we’re asking Python to retrieve an index that’s not within the bounds of the list, you get an IndexError.

This is why the Codecademy solution suggests putting the elif (board[guess_row][guess_col] == 'X'): where it does. The first if statement asks essentially “Did you guess correctly?”, and the second if deals with incorrect guesses. The first thing that the second if does is check whether you guessed within the confines of the board, and prevents you from attempting to check a location on the board that doesn’t exist.

I’m not sure whether the script that checks submissions would reject your code if you organised your ifs in a different way, but the first thing that you should do in an incorrect guess - i.e. one where if guess_row == ship_row and guess_col == ship_col: is not True - is check that the guessed row and/or column is valid. The way that your code runs at the moment means that you’re trying to check for a previous guess before you’ve checked that the guess is actually on the board.

Hope that helps.

#5

There are only 2 options in this game, or you find the battleship, or you dont.

There is only 1 way to find the battleship, that is when you guess it’s position.
Though there are multiple ways to not find the battleship. So you put all those wrong answers into an ‘else’ block.

You have now put a right guess and a wrong guess into 1 block, and then 2 wrong guesses in an other block,
while it would be more logical to only put a right answer in its own block, and all the wrong answers into their
own block.

so: