1

I have this problem while making a simple battleship game. Here is my code:

board = []
row = ['O'] * 5 #<<<<determine the board size here 
joined_O = '  '.join(row)


for i in range(5): #<<<<determine the board size here
    board.append(joined_O)
    print(joined_O)

from random import randint #<<<< this code is to determine where the ship is. It is placed randomly.
ship_row = randint(1,len(board))
ship_col = randint(1,len(board))

print(ship_row,', ',ship_col,'\n')

print('Shoot missile to the ship')
missile_row = int(input('row   : '))
missile_col = int(input('column: '))

#I really don't know where you're supposed to put the int() thingy so i put it everywhere
if int(missile_row) == int(ship_row) and int(missile_col) == int(ship_col):
    print("Congratulation! You've hit the ship.")
    break
elif int(missile_row) >= len(board) or int(missile_col) >= len(board):
    print('Sorry! Area is out of range.')
    break
else:
    print('Missile missed the target')
    board[int(missile_row)][int(missile_col)] = 'X'
    print(board)

I tried to reassign the 'O's where the missile hit with an 'X' but then it says

TypeError: 'str' object does not support item assignment.

0

2 Answers 2

3
for i in range(5): #<<<<determine the board size here
    board.append(joined_O)

This doesn't look right to me. You should be appending lists to board, not strings. I'm guessing that you previously had something like:

for i in range(5):
    board.append(row)

Which would at least be the right type. But then you'd have weird bugs where five Xes appear instead of one whenever you miss a ship. This is because each row is the same row; making a change to one makes a change to all of them. You can avoid this by making a copy of the row each time using the slicing trick.

for i in range(5): #<<<<determine the board size here
    board.append(row[:])

Now your Xes should assign properly. But print(board) in your else block will be a bit ugly. You can format it nicely without brackets and quote marks using a couple quick joins:

else:
    print('Missile missed the target')
    board[int(missile_row)][int(missile_col)] = 'X'
    print("\n".join("  ".join(row) for row in board))

Now you've got some pretty nice output.

Shoot missile to the ship
row   : 1
column: 1
Missile missed the target
O  O  O  O  O
O  X  O  O  O
O  O  O  O  O
O  O  O  O  O
O  O  O  O  O
Sign up to request clarification or add additional context in comments.

6 Comments

Brother, you just fixed all the bugs in his code, and lost him the opportunity to learn python.
Perhaps... But the great thing about programming is there's always more bugs / learning opportunities in the future :-)
@Wajahat He did do some good teaching moments in here though- and at least broke up code to remove the chance to copy-paste the whole program.
Hi! Thank you for putting your time to answer this. I have a few questions though because I still don't understand some of it. 1. If I don’t use the slicing trick, why is each row is still the same row if I append it five times to the board list? Doesn't it mean I add 5 different lists to the empty list? I've tried using the slicing trick and it worked I'm just still confused as to what made it different.
2. The reason why I used the joined_o variable is to make the board without quotation marks since the beginning and not just the last bit. Did you join the rows at the end so that they don’t become a string? I intend to repeat using the input function so if board becomes a list of strings it's not possible for me to put another 'X' into the board right? If you don't understand what I mean please tell me so I can elaborate. Thank you so much!
|
1

Look at:

board = []
row = ['O'] * 5 #<<<<determine the board size here 
joined_O = '  '.join(row)
  • board is a list.
  • row is a list.
  • joined_O is a string formed by concatenating the elements of row.

AND:

for i in range(5):  #<<<<determine the board size here
    board.append(joined_O)
    print(joined_O)

board is now a list of strings

So

board[int(missile_row)][int(missile_col)] = 'X'

is not a valid command because it is trying to modify the string in board list instead of an element in a 2D list. In Python, strings are immutable, so you can't change their characters in-place.

In short, board is not a 2D list in your code, but a list of strings.

1 Comment

Thank you very much for answering! I didn't know that joining them will make them into a string. I understand now why it is not possible for me to replace the O with an X so thank you for that!

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.