Why do I get a list index out of range error?

Question

Why do I get a list index out of range error?

Answer

It’s crucial that you get the order of your conditions right, otherwise you might try using invalid user input before checking for it to be invalid. The order, in pseudo code, should be as follows:

if guess is correct:
  print “Congrats! You sunk my ship.”
else, not correct:
  if guess is invalid:
    print “Not in the ocean”
  elif already guessed:
    print “Already guessed!”
  else, just missed:
    print “Missed!”
    update element in board to be “X”
  print the board

Notice the order in which we check things:

  1. If the input is correct, it is valid and we’re done.
  2. OTHERWISE (else), we check everything else. The very first thing we check inside the else is for the input to be invalid (not in the range() of our board list.
  3. The last things we do are use the user-input coordinates to check if they’ve already guessed and to print the board. If we try to print the board or use those invalid inputs in any way, it will cause an error.
1 Like

still in the battleship course I have a question :
Why is differently written the return command in len(board… ???

first is len(board)-1 and then len(board[0] - 1) … shouldn t it be the same ?
more exactly : board vs board[0]

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

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

1 Like

as long as the board is a square its the same, however what if you have a rectangle board? 5 by 8 for example

1 Like

this is my code(i get the out of range error):
what does list index out of range mean? here is my code:
else:
print “You missed my battleship!”
board[guess_row][guess_col]=“X”
print_board(board)
if guess_row not in range(6) or guess_col not in range(6): #i looked at hint for this line
print “Oops, that’s not even in the ocean.”

every element in a list has a position, better know as index/indices

if a list has 5 elements (length of 5), the highest index is 4 (since indices start counting at zero), so are you sure range(6) is good?

oh wow i suck at counting thx xd

yeah, but he has a point, excluding the added range.
Every time i guess a location outside of the range, it reads an indexerror: list index out of range…
if i run the code with numbers within the index range(0-4) there is no error and the gamme runs as it should. When i run the indices outside of it’s range it prints the “oops…” message as it should but follows it up with the indexerror.
It specifically calls the error at the line that reads ’ board[guess_row][guess_col] = “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: "))

# Write your code below!
if guess_row == ship_row and guess_col == ship_col:
  print "Congratulations! You sank my battleship!"   
else:
  if guess_row not in range(0,5) or guess_col not in range(0,5):
    print "Oops, that's not even in the ocean."
  elif guess_row == "X" or guess_col == "X":
    print "You guessed that one already."
  else:
		print "You missed my battleship!"
  board[guess_row][guess_col] = "X"
  print_board(board)

why would you want to update the board (mark an X) when the entered input is invalid (either out of range or already guessed)?

this else:

  else:
		print "You missed my battleship!"

handles a miss but a valid input, that is where you should update the board. Then you can’t get an index error when the input is invalid

it seemed like that’s what the instructions were requiring be done, for if the guess was out of range print that and if the guess was already called, print X.
after advancing to the next step the code was automatically changed to this…

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)
print ship_row
print ship_col

# Everything from here on should go in your for loop!
# Be sure to indent four spaces!
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 sunk my battleship!"
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 (turn + 1) here!
  print_board(board)

it seems the same as what i had written. and i do not understand why the range declaration inside the conditional if statement was change to <,> signs instead of the range(x,x) declaration

both are valid options

the difference you should worry about is here:

  # your code
  else:
		print "You missed my battleship!"
  board[guess_row][guess_col] = "X"
   # next exercise code
  else:
    print "You missed my battleship!"
    board[guess_row][guess_col] = "X"

see how board[guess_row][guess_col] = "X" is nested in the else clause? Now you can’t get an index error, given the program doesn’t get there when input is higher then four (given if clause will run)

2 Likes

O O O O O
2
4
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

My code appears to be placing the X at the wrong position, but I’m not getting any errors and it’s letting me move on?

What’s wrong with the position?

Isn’t it appearing at 5,5 instead of 4,4?

Remember that indexing in Python (and most computer languages) begins with zero.

of course, if you want, you can extend your program to “fix” this. It would improve user experience.

Shouldn’t the elif statement be:
elif guess_row == “X” and guess_col == “X”:
?

no, guess_row and guess_col are the numbers entered by the user. You should use these numbers to check if that location on the board is marked with an X.

Solution to exercise 13/14 of Battleship.
This is very important as not matter what your code is that CC will display the result alright and let you continue with the course, even though your problem might be wrong.

Here’s the solution:

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")
else:
  if guess_row >= len(board) or guess_col >= len(board[0]):
    print "Oops, that's not even in the ocean." 
  elif board[guess_row - 1][guess_col - 1] == "X":
    print "You guessed that one already."
  else:
    print("You missed my battleship!")
    board[guess_row - 1][guess_col - 1] = "X"
    print_board(board)

Don’t foget about that -1 and change the predetermined condition of not blablabla to the one I posted. It’s better and allows the programm to not have errors printing out the coordinates are out of the board when the columns are greater than the rows (as an input from the user). I hope this makes sense.

Happy coding!