This question already has answers here:
How can I read inputs as numbers?
(10 answers)
Closed 7 years ago.
I'm having issues with this code, when i run the code, it always prints "Oops, that's not even in the ocean." no matter what i type. Also if i write letters the code crashes. How can i add a typo check fonction that could solve the crash and make the code resistant from typos from the user. Thank you in advance !
from random import randint
#initializing board + this is my list
board = []
for x in range(5):
board.append(["O"] * 5)
def print_board(board):
for row in board:
print " ".join(row)
#starting the game and printing the board
print "Let's play Battleship!"
print_board(board)
#defining where the ship is
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)
#asking the user for a guess
for turn in range(4):
guess_row = raw_input("Guess Row:")
guess_col = raw_input("Guess Col:")
# if the user's right, the game ends
if guess_row == ship_row and guess_col == ship_col:
print "Congratulations! You sunk my battleship!"
break
else:
#warning if the guess is out of the board
if (guess_row < 0 or guess_row > 5) or (guess_col < 0 or guess_col > 5):
print "Oops, that's not even in the ocean."
#warning if the guess was already made
elif(board[guess_row][guess_col] == "X"):
print "You guessed that one already."
#if the guess is wrong, mark the point with an X and start again
else:
print "You missed my battleship!"
board[guess_row][guess_col] = "X"
# Print turn and board again here
print "Turn " + str(turn+1) + " out of 4."
print_board(board)
#if the user have made 4 tries, it's game over
if turn >= 3:
print "Game Over"
Your problem lies in the fact that raw_input returns a string, you need to cast it to an integer like this:
guess_row = int(raw_input("Guess Row:"))
guess_col = int(raw_input("Guess Col:"))
Related
I'm nearing the end of a lesson on creating a very simple battleship game. Basically you get 4 chances to guess the location of the ship. if you lose: game over. If you win before all 4 chances you're supposed to end the game using a "break" function.
Problem is: After inserting "break", I get an error msg reading:
File "python", line 33
SyntaxError: 'break' outside loop
Here is my code, please and thank you for any help it is much appreciated:
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 "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[0]) - 1)
ship_row = random_row(board)
ship_col = random_col(board)
print ship_row
print ship_col
turn = 1
for turn in range(4):
print turn
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
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
print_board(board)
if turn == 3:
print "Game Over"
Your break is outside the loop indeed. Try to fix indentation in if-else statement on line 31 like this:
for turn in range(4):
...
if guess_row == ship_row and guess_col == ship_col:
print "Congratulations! You sunk my battleship!"
break
else:
...
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I'm trying to learn Python and Codecademy has been great help. In one of their lessons I made a simplified Battleship game. Now I'm trying to expand on it with adding a second boat, but it gives me a "invalid syntax" error around the "else" of the "while" function. The whole meaning of the "while" function is to find a location on the board for the 2nd boat that isn't already taken by the original boat. All help is appreciated!
from random import randint
#Defines the board
board = []
for x in range(5):
board.append(["O"] * 5)
#How it should print the board
def print_board(board):
for row in board:
print (" ".join(row))
print ("Let's play Battleship!")
for turn in range(1):
print ("TURN ", turn + 1)
break
print_board(board)
#Spawns the boat on a random location on the board
def random_row1(board):
return randint(0, len(board) - 1)
def random_col1(board):
return randint(0, len(board[0]) - 1)
ship1_row = random_row1(board)
ship1_col = random_col1(board)
#Spawns the 2nd boat
def random_row2(board):
return randint(0, len(board) - 1)
def random_col2(board):
return randint(0, len(board[0]) - 1)
ship2_row = random_row2(board)
ship2_col = random_col2(board)
#Finds a new location for the 2nd boat if it is already taken by the 1st
#boat. It procceds with the game when an untapped location has been found.
while ship1_row == ship2_row and ship1_col == ship2_col:
ship2_row = randint(0, len(board) - 1)
ship2_col = randint(0, len(board[0] - 1)
else:
#Debugging
print ("Ship 1 row: ", ship1_row)
print ("Ship 1 col: ", ship1_col)
print (" ")
print ("Ship 2 row: ", ship2_row)
print ("Ship 2 col: ", ship2_col)
for turn in range(4):
realturn = turn + 1
guess_row = int(input("Guess row: "))
guess_col = int(input("Guess colum: "))
if guess_row == ship_row and guess_col == ship_col:
print ("CONGRATULATIONS! You sunk the battleship!")
break
else:
if (guess_row < 0 or guess_row > 4) or (guess_col < 0 or guess_col > 4):
print ("Oops, that location isn't even in the ocean!")
elif(board[guess_row][guess_col] == "X"):
print ("You guessed that location already!")
else:
print ("You missed the battleship!")
board[guess_row][guess_col] = "X"
if turn == 3:
print ("GAME OVER!")
break
print (" ")
print ("TURN ", realturn + 1)
print_board(board)
You have unbalanced parentheses on the preceding line:
ship2_col = randint(0, len(board[0] - 1)
^open ^open ^close
(two opening and one closing.)
So I've been going through Codecademy's Python lessons. I enjoyed the Battleship game I created in one of the lessons, but one thing annoyed me. The player has to constantly keep in mind that the rows and columns count 0-4 rather than 1-5. I've already made an attempt to fix this, but I'm not sure if it's messing with my ship placement.
Here's my original code:
from random import randint
#Create 5x5 game board
board = []
for x in range(5):
board.append(["O"] * 5)
def print_board(board):
for row in board:
print " ".join(row)
#Start game
print "Let's play Battleship!"
print_board(board)
#Randomly place ship
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)
#Process player guesses max 4 turns
for turn in range(4):
print "Turn: %d" % (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
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."
print_board(board)
elif(board[guess_row][guess_col] == "X"):
print "You guessed that one already."
print_board(board)
else:
print "You missed my battleship!"
board[guess_row][guess_col] = "X"
print_board(board)
if turn > 2:
print "Game Over"
Here's my attempt to change the board count:
from random import randint
#Create 5x5 game board
board = ['dummy']
for x in range(5):
board.append(["O"] * 6)
def print_board(board):
for row in board:
print " ".join(row[1:])
#Start game
print "Let's play Battleship!"
print_board(board[1:])
#Randomly place ship
def random_row(board):
return randint(1, len(board[1:]) - 1)
def random_col(board):
return randint(1, len(board[1:]) - 1)
ship_row = random_row(board[1:])
ship_col = random_col(board[1:])
print "%d,%d" % (ship_row, ship_col)
#Process player guesses max 4 turns
for turn in range(4):
print "Turn: %d" % (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
else:
if (guess_row < 1 or guess_row > 5) or (guess_col < 1 or guess_col > 5):
print "Oops, that's not even in the ocean."
print_board(board[1:])
elif(board[guess_row][guess_col] == "X"):
print "You guessed that one already."
print_board(board[1:])
else:
print "You missed my battleship!"
board[guess_row][guess_col] = "X"
print_board(board[1:])
if turn > 2:
print "Game Over"
The print "%d,%d" % (ship_row, ship_col) is only in there so I can test the ship placement. I haven't seen a ship placed in a position higher than 3 on rows or columns. Not sure if I screwed the code or if it's just dumb luck. Any insight is appreciated and if you know an easier to accomplish this please let me know. I've been thinking guess_row = int(raw_input("Guess Row:")) - 1 but haven't tested it yet.
Well sometimes the obvious answer is the right one.
I changed:
for turn in range(4):
print "Turn: %d" % (turn + 1)
guess_row = int(raw_input("Guess Row:"))
guess_col = int(raw_input("Guess Col:"))
To:
for turn in range(4):
print "Turn: %d" % (turn + 1)
guess_row = int(raw_input("Guess Row:")) - 1
guess_col = int(raw_input("Guess Col:")) - 1
This allows the player to enter a choice of 1-5 rather than 0-4
This is the "Battleship!" problem that is covered in Codecademy (Python) I want to put a condition wherein the number of turns does not get incremented in the case that the user enterers a value of row/column that is repeated or outside limits. I can't figure out what the problem is in this code:
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 "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[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!
for turn in range(4):
# Be sure to indent four spaces!
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
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."
print "Please try again."
# turn -= 1 Why doesn't this work? The "Game Over" message does not get displayed at the end of the game if such a case arises (but the game still ends!), which means the value of turn does not reach 3. But still when 'turn + 1' is printed, the value gets incremented even if such a condition is encountered.
elif(board[guess_row][guess_col] == "X"):
print "You guessed that one already."
print "Please try again."
# turn -= 1 Same as last message.
else:
print "You missed my battleship!"
board[guess_row][guess_col] = "X"
if turn == 3:
print "Game Over"
# Print (turn + 1) here!
print_board(board)
There is only a very small error in your code, from what I can see. The last if statement, which includes your "Game Over" string, is indented incorrectly. Move it left one block:
else:
print "You missed my battleship!"
board[guess_row][guess_col] = "X"
if turn == 3:
print "Game Over"
# Print (turn + 1) here!
print_board(board)
Here is my complete code from that exercise:
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 "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[0]) - 1)
ship_row = random_row(board)
ship_col = random_col(board)
print ship_row
print ship_col
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!"
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_board(board)
if turn == 3:
print "Game Over"
A for turn in range(4): loop doesn't work the way you think it does.
It's equivalent to this:
_range = [0, 1, 2, 3]
_it = iter(_range)
while True:
try:
turn = next(_it)
except StopIteration:
break
# your code here
You don't have to understand all of the details there, but they key point is that, each time through the loop, it's assigning a new value to turn, which comes straight out of the iterator, and has nothing to do with the old value of turn. So, your changes to turn are irrelevant.
So, how do you fix it?
One way is to replace the for loop with a while loop that explicitly maintains turn, so you can explicitly decrement it—or, better, just not increment it. For example:
turn = 0
while turn < 4:
# your code, slightly modified
# do turn += 1 only when the turn is valid
# don't do turn += 1 when the turn is invalid
The other way is to put another loop inside this for loop that just repeats until the player makes a valid turn:
for turn in range(4):
while True:
# your code, slightly modified
# do break only when the turn is valid
# do nothing, or continue, when the turn is invalid
While I'm at it, there's another problem in your code.
That if turn == 3 part is either wrong, or unnecessary. The game is over when the player is out of turns. You know the player is out of turns when you finish the loop. You don't need any extra test for it. So:
for or while or whatever:
# stuff
print "Game Over"
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Bear with me, I'm new to programming and I know for a fact this contains a lot of unnecessary code.
Is there a way to add more ships without the code extending forever?
Also a better way to code the comparisons under my while loop. Thanks for taking the time to read and comment.
from random import randint
board = []
for x in range(10):
board.append(["O"] * 10)
# creating the "map" of "O"'s for an ocean - 10x10
def print_board(board):
for row in board:
print " ".join(row)
print "Let's play Battleship!"
print_board(board)
# random number for row from 0 to length of board (9) in this case
def random_row(board):
return randint(0, len(board) - 1)
# random number for column from 0 to length of board (9) in this case
def random_col(board):
return randint(0, len(board[0]) - 1)
# 1st ship, size = 1x1
ship_row = random_row(board)
ship_col = random_col(board)
# 2nd ship, size = 1x2
ship_row2 = random_row(board)
if ship_row2 == ship_row: #Did not want a ship coordinate to fall onto a previous ship
ship_row2 = random_row(board) #so I set it to generate a new number if it did
ship_row2_1 = ship_row2 - 1 #2nd part of this ship, needs to be adjacent so I set - 1 (could be +1)
if not ship_row2_1 >= 0: # if first part is 0, then ship_row2_1 would be off the "map",
ship_row2_1 += 2 #so I added 2 to bring it to a positive number
ship_col2 = random_col(board)#same things as above for the column code
if ship_col2 == ship_col:
ship_col2 = random_col(board)
ship_col2_1 = ship_col2
turn = 0
ships_sunk = 0
while True:
try:
guess_row = int(raw_input("Guess Row:"))
guess_col = int(raw_input("Guess Col:"))
# so my code here basically says if you hit the 1x1 ship it should turn it to an X,
#and not be able to hit it again.
if (guess_row == ship_row and guess_col == ship_col) and (board[guess_row][guess_col] != "X"):
print "\nCongratulations! You sunk a battleship!"
print "One more to go!\n"
board[guess_row][guess_col] = "X"
print_board(board)
ships_sunk += 1
if ships_sunk == 2:
print "\n You got them all! Pokemon!"
break
# here is the same but for the 1x2 ship, I had to turn them all to X to prevent user,
# from hitting the same part of the "ship".
elif ((guess_row == ship_row2 and guess_col == ship_col2) or \
(guess_row == ship_row2_1 and guess_col == ship_col2_1)) and (board[guess_row][guess_col] != "X"):
print "\nCongratulations! You sunk a battleship!"
print "One more to go!\n"
board[guess_row][guess_col] = "X"
board[ship_row2][ship_col2] = "X"
board[ship_row2_1][ship_col2_1] = "X"
print_board(board)
ships_sunk += 1
if ships_sunk == 2:
print "\n You got them all! Pokemon!"
break
else:
if (guess_row < 0 or guess_row > (len(board) -1 )) or (guess_col < 0 or guess_col > (len(board[0]) - 1)):
print "\nOops, that's not even in the ocean."
elif(board[guess_row][guess_col] == "X"):
print "\nYou guessed that one already."
elif type(guess_row) is not int or type(guess_col) is not int:
print "Type a number!"
else:
print "\nYou missed my battleship!"
board[guess_row][guess_col] = "X"
turn += 1
print_board(board)
if turn == 4:
print "Game Over"
break
except ValueError:
print "Please type a number!"
You need to store the "game state" in a more flexible way. The same thing goes for the logic that determines when a player has won. One way of doing this would be to break down your application into classes, maybe something like:
Battle class: contains ships for each side, scoring methods, dimensions for the battle area
Ship class: size of the ship, amount of damage ship has sustained, ship's location
Whenever making a new Battle class, you could pass it an initial list of Ships for each side. These lists could be as long as you want (provided the ships can fit into the battle area without overlapping).