35

I'm trying to improve a game of battleships. The original version works fine with no errors. I have written code to help overcome the fact that the first version places the ships in the same place every time so I have started with one ship (made of two squares). I have done this by creating two functions: the first generates a random coordinate...

# Destroyer (2 squares)
def Deploy_Destroyer_1(Player):
    rand_col_1 = randint(0,11)
    if rand_col_1 <= 5:
        rand_row_1 = randint(0,11)
    else:
        rand_row_1 = randint(6,11)
    return rand_col_1
    return rand_row_1
    if Player[rand_row_1][rand_col_1] == 'X':
        Deploy_Destroyer_1(Player)
    else:
        Deploy_Destroyer_2(Player)

and the second trials this co-ordinate against the conditions (if it will fit on the board and which rotation it can be placed).

def Deploy_Destroyer_2(Player):
    if rand_col_1 == 5 and rand_row_1 == 6:
        #can be 1, 2, 3 or 4... in that order below
        rand_position_1 = randint(1,4)
        if rand_position_1 == 1:
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1 + 1][rand_col_1] = 2
        if rand_position_1 == 2:
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1 - 1][rand_col_1] = 2
        if rand_position_1 == 3:
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1][rand_col_1 + 1] = 2
        if rand_position_1 == 4:
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1][rand_col_1 - 1] = 2
    elif rand_col_1 in range(1,4) and rand_row_1 in range(1,10):
        #can be any 1, 2, 3 or 4... in that order below
        rand_position_1 = randint(1,4)
        if rand_position_1 == 1:
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1 + 1][rand_col_1] = 2
        if rand_position_1 == 2:
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1 - 1][rand_col_1] = 2
        if rand_position_1 == 3:
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1][rand_col_1 + 1] = 2
        if rand_position_1 == 4:
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1][rand_col_1 - 1] = 2
    elif rand_col_1 in range(5,10) and rand_row_1 in range(7,10):
        #can be any 1, 2, 3 or 4... in that order below
        rand_position_1 = randint(1,4)
        if rand_position_1 == 1:
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1 + 1][rand_col_1] = 2
        if rand_position_1 == 2:
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1 - 1][rand_col_1] = 2
        if rand_position_1 == 3:
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1][rand_col_1 + 1] = 2
        if rand_position_1 == 4:
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1][rand_col_1 - 1] = 2
    elif rand_col_1 == 0 and rand_row_1 == 0:
        #can be any 1, 2, 3 or 4... in that order below
        rand_position_1 = randint(1,4)
        if rand_position_1 == 1:
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1 + 1][rand_col_1] = 2
        if rand_position_1 == 2:
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1 - 1][rand_col_1] = 2
        if rand_position_1 == 3:
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1][rand_col_1 + 1] = 2
        if rand_position_1 == 4:
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1][rand_col_1 - 1] = 2
    elif (rand_col_1 == 5 and rand_row_1 == 0) or (rand_col_1 == 11 and rand_row_1 ==6):
        #can be one or four
        #check brackets and booleans here
        rand_position_1 = randint(1,2)
        if rand_position_1 == 1: #position 1
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1 + 1][rand_col_1] = 2
        if rand_position_1 == 2: #position 4
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1][rand_col_1 - 1] = 2
    elif rand_col_1 == 0 and rand_row_1 == 11:
        #can be 2 or 3
        rand_position_1 = randint(2,3)
        if rand_position_1 == 2: #position 2
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1 - 1][rand_col_1] = 2
        if rand_position_1 == 3: #position 3
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1][rand_col_1 + 1] = 2
    elif rand_col_1 == 11 and rand_row_1 == 11:
        #can be 2 or 4
        rand_position_1 = randint(1,2)
        if rand_position_1 == 1: #position 2
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1 - 1][rand_col_1] = 2
        if rand_position_1 == 2: #position 4
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1][rand_col_1 - 1] = 2
    elif (rand_row_1 == 0 and rand_col_1 in range(1,4)) or (rand_row_1 == 6 and rand_col_1 in range(6,10)):
        #can be 1, 3 or 4
        #check brackets and booleans here
        rand_position_1 = randint(1,3)
        if rand_position_1 == 1: #position 1
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1 + 1][rand_col_1] = 2
        if rand_position_1 == 2: #position 3
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1][rand_col_1 + 1] = 2
        if rand_position_1 == 3: #position 4
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1][rand_col_1 - 1] = 2
    elif (rand_col_1 == 5 and rand_row_1 in range(1,5)) or (rand_col_1 == 11 and rand_row_1 in range(7,10)):
        #can be 1, 2 or 4
        #check brackets and booleans here
        rand_position_1 = randint(1,3)
        if rand_position_1 == 1: #position 1
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1 + 1][rand_col_1] = 2
        if rand_position_1 == 2: #position 2
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1 - 1][rand_col_1] = 2
        if rand_position_1 == 3: #position 4
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1][rand_col_1 - 1] = 2
    elif rand_col_1 == 0 and rand_row_1 in range(1,10):
        #can be 1, 2 or 3... in that order below
        rand_position_1 = randint(1,3)
        if rand_position_1 == 1:
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1 + 1][rand_col_1] = 2
        if rand_position_1 == 2:
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1 - 1][rand_col_1] = 2
        if rand_position_1 == 3:
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1][rand_col_1 + 1] = 2
    elif rand_col_1 in range(1,10) and rand_row_1 == 11:
        #can be 2, 3 or 4
        rand_position_1 = randint(1,3)
        if rand_position_1 == 2: #position 2
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1 - 1][rand_col_1] = 2
        if rand_position_1 == 3: #position 3
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1][rand_col_1 + 1] = 2
        if rand_position_1 == 4: #position 4
            Player[rand_row_1][rand_col_1] = 2
            Player[rand_row_1][rand_col_1 - 1] = 2

After applying my code I get this error.

    Traceback (most recent call last):
  File "<stdin>", line 310, in <module>
  File "<stdin>", line 15, in PrintBoards
TypeError: sequence item 0: expected string, NoneType found

and here is the PrintBoards function

def PrintBoards(Player,Opponent):
    print ' '*10, 'PLAYER', ' '*30, 'OPPONENT'
    letters = ['A','B','C','D','E','F','G','H','I','J','K','L']
    for x in range(6):
        print letters[x],"  ".join(map(DisplayChar,Player[x]))," "*18,"| ","  ".join(map(DisplayChar,Opponent[x]))
    for x in range(6,12):
        print letters[x],"  ".join(map(DisplayChar,Player[x]))," | ","  ".join(map(DisplayChar,Opponent[x]))
    print " ","  ".join(map(str,range(1,10)))," 10 11 12","  ","  ".join(map(str,range(1,10)))," 10 11 12"

and here is the DisplayChar function

def DisplayChar(x):
    if x==0: 
        return '?'
    elif x==1:
        return ' '
    elif x==2:
        return 'X'
    elif x==3:
        return ' '
    elif x==4:
        return '*'

I tried editing the above function to this...

def DisplayChar(x):
        if x==0: 
            return '?'
        elif x==2:
            return 'X'
        elif x==4:
            return '*'
        else:
            return ' '

However it gave me this error instead

Traceback (most recent call last):
  File "<stdin>", line 309, in <module>
  File "<stdin>", line 15, in PrintBoards
TypeError: argument 2 to map() must support iteration

I also tried printing the lists Player and Opponent after the PrintBoards function to ensure that they contain 0s and 1s (referring to the DisplayChar function) which they do (when inserted into the original, not when I put my new and very long code in)

This next bit is in response to Michael

PLAYER                                OPPONENT
[[1, 1, 1, 1, 1, 1], [1, 2, 2, 2, 1, 1], [1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1], [1, 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1], [1, 2, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
[0, 0, 0, 0, 0, 0]
A                                                       |  ?  ?  ?  ?  ?  ?
<function Deploy_Destroyer_1 at 0x1c2634>
[0, 0, 0, 0, 0, 0]
B
Traceback (most recent call last):
  File "<stdin>", line 314, in <module>
  File "<stdin>", line 17, in PrintBoards
TypeError: argument 2 to map() must support iteration

After someone kindly pointed out I had assigned the function instead of called it, I've found that another error occurred (I don't think Python likes me)

Traceback (most recent call last):
  File "<stdin>", line 313, in <module>
  File "<stdin>", line 17, in PrintBoards
TypeError: argument 2 to map() must support iteration

Below I've also included where I called the function in case I've done something silly

Player, Opponent = InitBoards()
Player = DeployFleet(Player), Deploy_Destroyer_1(Player)
PrintBoards(Player,Opponent)

I changed it to what Micheal0x2a said and it ran with no errors however the ship that the code is placing disappeared

From what I understand, the PrintBoards function prints the board for the Player by mapping the items in the list to the DisplayChar function (if 2 is an item in the list, it prints X etc). So my novice knowledge tells me that the Deploy_Destroyer_1 function should be called in Player = in the Main function (included above) to ensure that the item in the list is changed, therefore the character printed should change.

I’m guessing that there is something wrong with my new code (Deploy_Destroyer_1) which doesn’t do this correctly (either doesn’t change the item in the list therefore doesn’t print the correct character, or something else which I can’t think of).

However there is also a big chance that I have confused myself

I have only been learning Python for a couple of weeks so if anyone needs more detail in order to help me please ask

10
  • 1
    You need to show the full traceback, so we can see where the error is being raised. Commented Sep 17, 2013 at 14:15
  • does that help at all? you might need the whole program? argh Commented Sep 17, 2013 at 14:18
  • 1
    Your problem is definitely not the TypeError. Commented Sep 17, 2013 at 14:21
  • got any suggestions @septi? Commented Sep 17, 2013 at 14:22
  • 1
    We don't know about the PrintBoards function, but I guess there's a join inside it that joins together all cell contents. This does not work with Nones. Commented Sep 17, 2013 at 14:26

4 Answers 4

163

If you've arrived here because you were looking for the root cause of "TypeError: sequence item 0: expected string, NoneType found", it can come from doing something along these lines...

','.join([None])
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks, that's exactly what I needed to know. This can also happen if your list has other stuff in it, but stil contains a None. [None, 'foo', 'bar'] Now I have to find the method to clear 'None's from the array
This is a nice way to do it: >>> filter(None, ['a', None, 'c'])
@NoelEvans: +1, but you need to point out that this will not filter None from the list, but also any other falsey values.
As inspired by @NoelEvans I found this to be useful: ','.join(map(str,[None]))
You, sir, just saved me from spending countless hours looking desperately at Google Cloud logs, which are all but self-explanatory.
1

Your DisplayChar function does not have a default value. This would do no harm if you'd be handling all possible cases for x, but apparently you're not. Try

def DisplayChar(x):
    if x == 0: 
        return '?'
    elif x == 2:
        return 'X'
    elif x == 4:
        return '*'
    else:
        return ' '

but this will probably yield blank strings where you don't expect them.

Generally, I'd recommend going through a good Python tutorial first. All of your above code can be greatly simplified.

2 Comments

changed it to that... it did print another line of the boards but got this error instead :S Traceback (most recent call last): File "<stdin>", line 308, in <module> File "<stdin>", line 15, in PrintBoards TypeError: argument 2 to map() must support iteration
Right. You probably meant DisplayChar(Player[x]) instead of map(DisplayChar,Player[x])
1

The problem is most likely somewhere within these 4 lines:

for x in range(6):
    print letters[x],"  ".join(map(DisplayChar,Player[x]))," "*18,"| ","  ".join(map(DisplayChar,Opponent[x]))
for x in range(6,12):
    print letters[x],"  ".join(map(DisplayChar,Player[x]))," | ","  ".join(map(DisplayChar,Opponent[x]))

Within these lines, you've used a join statement multiple times. The join statement requires a list of strings in order to work. However, when you're mapping DisplayChar to Player[x], the DisplayChar function is returning the value None instead of a string of some sort.

If you look at the DisplayChar function, it handles values only from 0 to 4. The lists you use probably include additional numbers or characters. If x happened to be something like 5, DisplayChar will terminate and simply return the value None. Remember, functions return the value None by default.

You either need to handle these additional numbers within DisplayChar, or modify DisplayChar to contain an else statement to return an empty string, like so:

def DisplayChar(x):
    if x==0: 
        return '?'
    elif x==1:
        return ' '
    elif x==2:
        return 'X'
    elif x==3:
        return ' '
    elif x==4:
        return '*'
    else:
        return ' '

Edit:

Ok, I think I might know what's going on, given the new edits.

Notice when you were printing out Player[x], it printed <function Deploy_Destroyer_1 at 0x1c2634> the second time around?

That means somewhere, buried deep inside your code, you've done something to the effect of Player[row] = Deploy_Destroyer_1 (notice the missing parenthesis!). Instead of calling the function, you've assigned the function.

Hunting for, and adding the missing parenthesis should most likely solve the problem.

Edit 2:

I think your problem is with this line: Player = DeployFleet(Player), Deploy_Destroyer_1(Player)

If you try doing a print Player immediately after, I think you'll most likely see a large list of numbers, followed by None.

This is because the DeployFleet function is returning the table (I think?) whereas the Deploy_Destroyer_1 function returns nothing. Instead, it just mutates the Player table.

To fix this, try doing either this:

Player = DeployFleet(Player)
Deploy_Destroyer_1(Player)

...or modify Deployer_Destroyer_1 so that it returns Player when it's finished, so you can do this:

Player = DeployFleet(Player)
Deploy_Destroyer_1(Player)

10 Comments

Player is a define list in a different function def InitBoards(): #The following convention is used for storing the state of a square: #0=Unknown #1= Empty #2= Occupied #3= Missed #4= Hit (player or opponent) # Initially, the player's board is all empty, the opponent's is all unknown Player = [[1]*(6 if x<6 else 12) for x in range(12)] Opponent = [[0]*(6 if x<6 else 12) for x in range(12)] return Player,Opponent Here's what I thought: map() checks state of square/cell and prints the correct string using DisplayChar function. I tried changing Display
@BLeeM - just right after the for loops, could you try writing print Player[x], Opponent[x] so that we can check what's actually contained within those lists? Right now, we're just making guesses as to what's inside those values, and I'd like to know for certain.
It's defined in the InitBoards function (where the 1 and 0 refer to DisplayChar) def InitBoards(): # Initially, the player's board is all empty, the opponent's is all unknown Player = [[1]*(6 if x<6 else 12) for x in range(12)] Opponent = [[0]*(6 if x<6 else 12) for x in range(12)] return Player,Opponent So it just prints all the 1s and 0s because we don't know anything about the opponents and I haven't deployed my fleet yet
@BleeM -- Regardless, could you still print them out? Something could be modifying them in unexpected ways. Besides, when debugging, it's always good to be paranoid and test your assumptions -- if your assumptions were correct, there wouldn't be a bug :)
It doesn't reach the print it stops just as before and gives me the traceback error :( and thanks for the advice!
|
1

use this if any this type error came: for example ','.join((map(str,video_url)) map function help your to change tuble to str

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.