Battleship Row/Col Concept - Curious


#1

My question is why/how python recognizes the rows and columns we establish in the 'board' list-of-lists.

I understand that the board list is a list of 5 lists, and that this is accounted for/established in how we create the list (appending 5 lists of 5). However, when we create the random integers for the row and column with the randint command, how does this translate to a location on the matrix, rather than two different random integers placed accordingly at two places in the list?

So, the randint command, used in the code as such......

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

......simply returns a random integer between 0 and 24 (out of a list 25 items long). Then, you do the same for a random_column function, and you have two coordinates that determine the location of an X. My failure to understand is as follows: I understand how Python could place this X in the proper place, if you just pulled ONE random integer - say you got '21' for the random integer, then OK, it puts the X in the 21st overall place in the list of lists, which would be the second one in the bottom row when you print it all out. But this is obviously NOT how it works, because you pull two integers, and together they define the location. I just don't see where in the code accounts for what a row and what a column are in the first place.

My assumption is that, in the process of making and defining a list of lists, there is some abstraction that Python is doing, that isn't really spelled out in the Battleship lesson because it's not teaching at this depth and really just wants you to be able to make a decent REPL.

For reference, here's the code, with annotations for a reminder (the code works properly to run the game, I passed the lesson with it and it works in Powershell as well)

from random import randint

board = []

#sets up board, function to lay out/print board

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

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

#initial printout, creates random row/col and establishes location of ships
print "Let's play Battleship!"
print_board(board)

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

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

ship_row = random_row(board)
ship_col = random_col(board)
print ship_row # gives away answer - for debugging
print ship_col # gives away answer - for debugging

# Everything from here on should go in your for loop!
# Be sure to indent four spaces!
print_board(board)
turn = 0
for turn in range(4):
    print "Turn", turn + 1
    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!"
        break
    
    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"
    if turn == 3:
        print "Game Over"
    turn += 1
        # Print (turn + 1) here!
print_board(board)

I feel like understanding this properly will be good for my overall conceptual understanding of how Python (and programming languages in general, possibly) handles data.

Much appreciated,

A


#2

no? the outer list contains 5 list, so the random number generated can be: 0, 1, 2, 3 or 4

once we have two random integers, the first integer selects the random row and the second integer the random column


#3

Thanks for taking the time -

Yeah, I considered that, and wound up asking the question as is because it's kind of incidental - even if I was sure it was selecting from a list of 5 lists rather than the full list-list of 25, the question still remains, how does it know what a row and what a column are? I can understand if it's selecting the first list item (row), and then in turn selecting the next list item (column) from within THAT list - which gives you all the data you need, but since the random integers are pulled separately and independently, this would have to be finagled in the code that assigns the 'X' - and I don't really see how that works in that line of code. Do two lists written consecutively like board[][] automatically pull the second list from the first? Intuitively I would think it needs double parentheses for this.

I know I'm 99% for sure overthinking it.


#4

we can access lists by index:

example = ["O","O","O","O","O"]
print example[2]

it doesn't matter if index you use is randomly generated, as long as you have a variable (ship_row and ship_col) which will keep the same value during a game, so the ship stays in the same spot

you are overthinking this, here:

you use double square brackets:

board[guess_row][guess_col] = "X"

#5

Ok so that's the ultimate answer to my question, the double brackets. I hadn't been clear on the fact that the second of the double brackets pulls from the first, and therefore the expression only points to one location at [list (row)][item in that list (col within that row)]. Without knowing that, it appears that it's pulling two separate numbers, which wouldn't make sense.

And yes I was indeed overthinking it - I already had deduced where in the code the row col definition had to happen in my last comment, I could have told myself "it just works like that, chill".

Thanks!


#6

i see where you went wrong now, i hadn't gotten to grips with what you didn't understand

now it makes sense, hopefully it make sense for you as well now :slight_smile:


#7

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.