12. Bad Aim


#1

    if guess_row not in range(0, len(board) - 1) or \
    guess_col not in range(0, len(board) - 1):

Nothing wrong with the code, I managed to get the all green pass. I'm just wondering if anyone knows where the 'in' came from and what its purpose is? Has it been in any of the previous lessons?

I'm basically wondering why we can't just write not range... instead of not in range...?


#2

Hi @digitalninja65206 ,

Does this actually work correctly? It should accept all valid locations and reject any that are not valid.

Row 4, column 4 is a board location that your code should accept as valid. Try it out to see what happens.


#3

Yeah it actually does work perfectly. I'm just more curious as to the meaning of the in operator .

The full if code is:

    if guess_row not in range(0, len(board) - 1) or \
    guess_col not in range(0, len(board) - 1):
        print "Oops, that's not even in the ocean."

#4

The in operator determines whether a specified value is included in a sequence or string. For example, if we have this ...

my_list = [7, 3, 9, 4, 1]
print 3 in my_list

... then True is displayed.

However, if we have ...

my_list = [7, 3, 9, 4, 1]
print 6 in my_list

... False is displayed.

In the Battleship! game we use range to test whether a user's row and column guess is within the valid indexes of board. Valid indexes are 0, 1, 2, 3, or 4, and any of those should be accepted.

Considering the above, there is another interesting issue here. Your code passed when you submitted it, and when I submitted it. Codecademy's submission correctness test (SCT) should have given it an "Oops" message because it rejects some valid locations.


#5

Thx man, I understand it better now. Also found some good info about the operator here: https://www.tutorialspoint.com/python/membership_operators_example.htm

About the code, here is the full 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, len(board) - 1) or \
    guess_col not in range(0, len(board) - 1):
        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)

Do you get any errors now?


#6

Codecademy accepts your code without issuing any error messages. However, here's some example input and output from my testing it ...

Guess Row: 4
Guess Col: 4
Oops, that's not even in the ocean.

Note that the input represents a valid board location, but the output claims that it is "... not even in the ocean ...".

This reveals a bug in Codecademy's submission correctness test (SCT), which should have noticed the problem.

The problem is this, which does not accept row 4 or column 4 as valid ...

if guess_row not in range(0, len(board) - 1) or \
    guess_col not in range(0, len(board) - 1):

This revision would correctly determine whether a location is valid ...

if guess_row not in range(0, len(board)) or \
    guess_col not in range(0, len(board)):

You could shorten it to this ...

if guess_row not in range(len(board)) or guess_col not in range(len(board)):

Congratulations on revealing the SCT bug. :sunglasses:


#7

I'm not sure that I understand. In codecademys interpreter, when I type row 4 and column 4, I get the message that I've missed and an X in the right position of the board. Do you mean that this is an error?

And also, in my case, isn't range(0, len(board) - 1) the same as range(0,4)?
Oh okay, I think you mean that range(0,4) only applies to range 0, 1, 2, 3 but not 4. Thus 4 should not be accepted, right?

By the way, do you know why this is:

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

instead of:

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

The program works with both...


#8

Yes, you are correct that is does not include 4. However, 4 is a valid row or column.

The randint function differs from the range function in that the upper bound for range is exclusive while the upper bound for randint is inclusive.

The reason that both versions of the random_col function presented above do work correctly is that board is a square with both dimensions being the same. The first of the two is better, though, because it would still work if you changed the board object to a rectangle that is not a square. The expression, len(board[0]), measures the number of columns in a row, specifically row 0, directly.


#9

Cool, thanks! You've been very helpful :smiley:


#10

No problem; enjoy the game. :smile:


#11