List Problems in 1 Dimensional Python Battleship - python

I'm just starting to learn python and have come across some trouble when trying to program a simple 1-D version of single player battleship.
2 things I can't seem to make work:
I have a created a 1 dimensional list (which is the gameplay board), but need to display/print the indices of the repeating element of the list. In other words, how can I print a list that only shows the indices of the elements in my board?
I want to replace a that element with a "*" if it was a wrong guess. For example, if I wrongly guess the position as 4 in a board of 5 elements, I want to display:
1 2 3 * 5
Moreover, I want to display the winning hit as an "X":
1 2 X * 5
Here's my current code:
from random import randint
ship=randint(0, 5)
board = ["O","O","O","O","O"]
print ("Let's play Battleship!")
attempts = 1
while attempts < 4:
print (board)
guess = int(input("Guess Where My Ship Is: "))
if guess == ship:
print ("Congratulations Captain, you sunk my battleship!")
break
else:
print ("You missed my battleship!")
if attempts<3:
print("Try again!")
elif attempts==3:
print("Better luck next time, Captain!")
attempts+=1
Thank you and apologies for the lame question.

Good practice: set the board size to a variable so you can reference it regularly. Put this at the top
size = 5 # Can be changed later if you want to make the board bigger
Next, have your ship location be chosen based on that
ship = randint(0, size)
Instead of making a board filled with 0's, Generate the board dynamically so that it's already pre-populated with the possible values.
board = [] # Creating an empty board
for i in range(1, size):
position = str(i) # Converting integers to strings
board.append(position) # Adding those items to the board
Then, inside of the game logic, after the "You missed my battleship" line, change the relevant square on the board
...
print("You missed my battleship!")
number_guess = int(guess) - 1 # Because lists are zero-indexed
board[number_guess] = "*" # Assign "*" to the spot that was guessed
if attempts < 3:
...

To implement your two display functionalities, I would recommend just letting your board list just hold the display values, as you're not using it anywhere else anyway.
from random import randint
ship=randint(1, 5)
board = ['1', '2', '3', '4', '5']
print ("Let's play Battleship!")
attempts = 1
while attempts < 4:
print(' '.join(board))
guess = int(input("Guess Where My Ship Is: "))
if guess == ship:
print ("Congratulations Captain, you sunk my battleship!")
board[guess - 1] = 'X'
break
else:
print ("You missed my battleship!")
board[guess - 1] = '*'
if attempts<3:
print("Try again!")
elif attempts==3:
print("Better luck next time, Captain!")
attempts+=1
print(' '.join(board))
One more thing: You have a bug when you're selecting the index of the ship (should be in range [1, 5]), which I've also corrected.
In case you're expanding on your battleship program and you must have a function that prints out the indices of a list (unless the value is '*' or 'X'), one way is to simply do:
def display(b):
print(' '.join(y if y in 'X*' else str(x + 1) for x, y in enumerate(b)))

Related

creating a lottery that tells you if you've won and how many times(python)

the user must chose one number between 1 and 90, the program creates a 5x5 grid with random numbers in it(from 1 to 90) and tells you if you've won and how many times.
this is what i've come up with:
import random
numeri=range(1, 90)
c=0
while(c<5):
c=1
while(c<=5):
print(random.sample(numeri, k=5),"\t")
c=c+1
c=c+1
print("")
but i can't really wrap my head around on how to make
it check if the input is in the grid...
if you think that the question is out-of-topic, just tell me and i'll take it down.
ty
user_num = input(“Enter your num: “)
# this assumes the input is a valid integer
user_num = int(user_num)
# create grid
count = 0
for row in grid:
for lottery_num in row:
if lottery_num == user_num:
count += 1

Comparing exact values in two arrays

So this is a bit confusing. I am currently making a Top-Trumps game. Right now I have two arrays, a player deck and a computer deck. The way it works is that it creates an array from a text file of dog names, then assigns 4 values to it (Exercise, Intelligence, Friendliness and Drool). This all works. Then it splits up the deck and gives half to each array (player and computer). The user gets the first pick and I have managed to get it to allow the user to pick a category. What I don't know how to do is compare exact values in the two arrays. The arrays are listed as follows (example):
[['Fern-the-Fox-Terrier'], 'Exercise: ', 3, 'Intelligence: ', 67, 'Friendliness: ', 10, 'Drool: ', 4]
Here is the code if you need it: (I'm not sure how to attach a text file)
import random
import shutil
import os #here I have imported all necessary functions for the following code to work
import array
import time
allowedresponses = ["Exercise","Intelligence","Friendliness","Drool"] #this allows me to make sure both the user and the computer select only the values available
cardcount = 0
usercards = 0 #the following variables are used for later
computercards = 0
x = 1
y = 0
play = input("Welcome to Celebrity Dogs Top Trumps! Press S to start, or Q to quit: ")
play = play.upper()
while x==1:
if play == "S" or play == "s":
print("Great! Lets play!")
x+=1 #here the user is given the option to play the game or quit. Pressing Q will immediatley end the the program, whilst pressing S will start it.
elif play == "Q" or play == "q": #x = 1 variable is used to end the while loop, permitted the user enters an appropriate answer
print("OK, bye")
quit
x+=1
else:
print("That's not a valid answer. Please try again")
play = input("Welcome to Celebrity Dogs Top Trumps! Press S to start, or Q to quit: ")
cardcount = int(input("How many cards in this game? Please pick an even number between 4 and 30: ")) #the following section of code asks the to select the number of cards they want played
while x==2:
if cardcount < 4:
print("Thats too small! Please try again!") #the programs tells the user to select again if they have picked a number smaller than 4
cardcount = int(input("How many cards in this game? Please pick an even number between 4 and 30: "))
elif cardcount > 30:
print("Thats too big! Please try again!") #the programs tells the user to select again if they have picked a number larger than 30
cardcount = int(input("How many cards in this game? Please pick an even number between 4 and 30: "))
if cardcount % 2 != 0:
print("Thats an odd number! Please try again!")#the programs tells the user to select again if they have picked a number that can't be divided by 2 with no remainders, essentially forcing only even numbers
cardcount = int(input("How many cards in this game? Please pick an even number between 4 and 30: "))
else:
print("Perfect! Onwards!")
x+=1 #once again I have used the x variable to allow the user to continue if they have selected a number that fits the requirements
time.sleep(1)
print("----------------------------------------------------------------------")
print("Rules: 1) For exercise, intelligence and friendliness, the highest value wins. For drool, lowest wins")
print(" 2) If there is a draw, the player that picked the value wins and gets the cards")
shutil.copyfile('dogs.txt','celebdogs.txt') #this creates a copy of the dogs text file. It is mainly for if I ever need to edit a file with the dogs in,, the origin file is never changed.
topdogs = [] #here I have created an array for the dogs
inp = open('celebdogs.txt','r') #I have used python's text file edits to import everything in the newly made celebdogs text file into an array, in order to import it later
for line in inp.readlines():
topdogs.append([])
for i in line.split():
topdogs[-1].append(i)
inp.close()
deck = [] #here I have created an array for the deck of cards that will be used in the game
print("----------------------------------------------------------------------")
for index in range(0,cardcount): #this part of the code tells the program to repeat the following until the number of cards selected by the user is in the deck
deck.insert([index][0], [(random.choice(topdogs))])#h
deck[index].append("Exercise: ")
deck[index].append(random.randint(0,5))
deck[index].append("Intelligence: ")
deck[index].append(random.randint(0,100))
deck[index].append("Friendliness: ")
deck[index].append(random.randint(0,10))
deck[index].append("Drool: ")
deck[index].append(random.randint(0,10))
time.sleep(1)
playerDeck=[]
computerDeck=[]
while len(deck)>0:
playerDeck.append(deck.pop(0))
computerDeck.append(deck.pop(0))
time.sleep(1)
print("This is your deck: ")
print(playerDeck)
playerTurn = True
print("----------------------------------------------------------------------")
time.sleep(1)
print("This is your first card: ")
print(playerDeck[0])
if playerTurn == True:
answer = input("Please select an attack (Exercise, Intelligence, Friendliness and Drool): ")
while allowedresponses.count(answer) == 0:
answer = input("That isn't a valid choice, please try again: ")
else:
answer = random.choice(allowedresponses)
print("Computer chooses", answer)
print("Computer Card: ")
print(computerDeck[0])
if playerDeck == cardcount:
print("You win!!!!")
if computerDeck == cardcount:
print("Computer wins!!!!")
os.remove('celebdogs.txt')
Just in case I haven't explained this well, I need help knowing how to compare precise values in two arrays, so if I want to compare the values of Exercise in both decks for the single cards. Both arrays have the exact same format (name, exercise, value, intelligence, value, friendliness, value, drool, value) so I need to be able to compare specific values.
Thanks!
Try use python's zip function:
computerDeck = [1, 2, 3]
playerDeck = [1, 3, 3]
for computer_card, player_card in zip(computerDeck, playerDeck):
if computer_card == player_card:
print('valid')
else:
print('invalid')

Python battleships: getting a user input for how many ships they want

I am trying to get the game to take an input for how many ships the user would like, and to place that many ships. I have put the coordinates into a list and that is how I am storing them, and checking if it is a hit. But the ships get placed over each other, and with this list method, I don't know how to first of all, check they are not overlapping, and second of all, change it so they aren't.
from random import randint
print('Welcome to Battleships for 1 player! Please be careful with entries, as if you get it wrong, you will still lose a go!')
print('Good luck!')
print('')
no_of_goes = int(input("How many goes would you like: "))
size_of_board = int(input("And how big would you like the board to be: "))
if size_of_board > 56:
print("That board will be too big to fit on the screen (max 56)")
size_of_board = int(input("And choose a more sensible number: "))
no_of_ships = int(input("And finally, how many ships would you like?: "))
board = []
# printing out the board
for x in range(size_of_board):
board.append(["O"] * size_of_board)
def print_board(board):
for row in board:
print (" ".join(row))
print_board(board)
# the lists that will become the locations
ship_rows = []
ship_cols = []
# generating random locations
def random_row(board):
return randint(0, len(board) - 1)
def random_col(board):
return randint(0, len(board) - 1)
# adding locations to lists
ships = list(range(no_of_ships))
for i in ships:
row = random_row(board)
col = random_col(board)
ship_rows.append(row)
ship_cols.append(col)
##
## And this is my attempt (didn't work)
##
for row in ship_cols:
if row == ship_cols and col == ship_cols:
ship_rows[-1] = random_row(board)
ship_cols[-1] = random_col(board)
# allowing to see where ships are and logging how many ships have been hit
print(ship_rows)
print(ship_cols)
ship_count = [1]
## I couldn't find a way of ending the game once the ships were sunk, so I stuck in a recursive function (sorry)
def printing_stars():
print('You have won!! ' +'*' * 56)
printing_stars()
for turn in range(no_of_goes):
# asking for their guesses
print('Turn ' + str(turn + 1) + ' out of ' + str(no_of_goes))
guess_col = int(input("Guess Col:")) - 1
guess_row = int(input("Guess Row:")) - 1
for item in ship_rows:
# If they hit, it gives a '!'
if len(ship_count) == no_of_ships and guess_row == item and guess_col == ship_cols[ship_rows.index(item)]:
print("You have won!!!! Congratulations")
board [guess_row][guess_col] = '!'
print_board(board)
printing_stars()
elif guess_row == item and guess_col == ship_cols[ship_rows.index(item)]:
print ("Congratulations! You sunk one of my battleships")
board [guess_row][guess_col] = '!'
print_board(board)
ship_count.append(1)
break
else:
# all misses
if (guess_row < 0 or guess_row > size_of_board - 1) or (guess_col < 0 or guess_col > size_of_board - 1):
print ("Oops, that's not even in the ocean.")
elif board[guess_row][guess_col] == "X" or board[guess_row][guess_col] == "!":
print ("You guessed that one already.")
turn -= 1
else:
print ("You missed my battleship!")
board[guess_row][guess_col] = "X"
print_board(board)
if turn == (no_of_goes - 1):
print('Game Over')
break
Any ideas? Would be very grateful :)
Some suggestion for your code :
You could model the player board with a numpy array like this :
Size : i lines and j colums => (i, j)
0 if water
1 if water that was shot by the palyer
2 if ship unharm
3 if ship case is hit
Once they are no more 2, it means there is a winner.
With this system, you can tell a player if he is shooting twice the same spot and you could also generate a display.
Moreover, to randomly position the ship, you could use this procedure :
Set ship size : let's say 4 spots.
Choose randomly 0 or 1 : 0 to place the ship horizontaly, and 1 to place the ship verticaly
Now we have to look if it is placed horizontaly or verticaly.
If it's horizontaly placed :
Choose 2 random number between 0 and j-4 and 0 and i. That will be your ship first spot coordinate, it means, this spot turn to 2, and the 3 spot on after it also.
Example with a 5*5 board, and a position pick of (1,0) for an horizontal ship
00000
22220
00000
00000
00000
I let you take care of the case verticaly, just have to change the random number generation indices.
Then that solution doesn't prevent from getting a ship on an other one. One simple solution, is with this loop :
while True:
if all ship placed:
break
pick number
Try to place the ship. (with an if statement, check if one of the spot your gonna change is already a 2.)
That solution should work as long as it is possible to place all the ship on the board. If it's impossible, you'll the loop won't end. Moreover if the number of ship is not limited in regard of the board size, it could be long to place them.
You can then keep improving the method with more complicated scenario. One other solution would be to check after each ship positioning where you still have place to put one.

Game of Pig - can't figure out how to loop through all the players

I have figured out most of the problem but can't seem to figure out how to loop through each of the players to let them play the game. This is the code I have so far. I think that my while loop in the main() function is wrong but I don't know what to do to fix it. Let me know if you can point me in the right direction. I also need to figure out how to end the turn if you roll a 1.
import random
def instructions():
print ("==================================================")
print ("\nWelcome to the Game of Pig. To win, be the")
print ("player with the most points at the end of the")
print ("game. The game ends at the end of a round where")
print ("at least one player has 100 or more points.\n")
print ("On each turn, you may roll the die as many times")
print ("as you like to obtain more points. However, if")
print ("you roll a 1, your turn is over, and you do not")
print ("obtain any points that turn.\n")
def num_players():
while True:
players = raw_input("How many players will be playing? ")
if players.isdigit():
return int(players)
else:
print "\nPlease enter a valid number of players.\n"
def name_players(players):
count = 1
list_of_players = []
for i in range(players):
name = raw_input("Enter the name for Player {}: ".format(count))
list_of_players.append(name)
count += 1
print ""
return list_of_players
def start_game(list_of_players):
points = 0
for player in list_of_players:
print "{0} has {1} points.".format(player, points)
print ("==================================================\n")
s = input("How many sides of the dice do you want? ")
for player in list_of_players:
print ("\n{0}'s turn:").format(player)
answer = raw_input("Press y to roll the dice?")
while answer == 'y' and points <= 100:
roll = random.randrange(1, s)
if roll > 1:
points += roll
print "{0} has {1} points.".format(player, points)
answer = raw_input("Press y to roll the dice?")
def main():
instructions()
players = num_players()
list_of_players = name_players(players)
start_game(list_of_players)
if __name__ == "__main__":
main()
The problem you encountered is due to the local variable, points, in function start_game. All your players are sharing the same variable to keep tracking their score. Therefore, once, your first player reaches/passes 100 points, the game logic will move to the second player. However, the points variable is still keeping the score from the previous player (which is more than or equal to 100). Because of that, the following players will never get chance to get into while loop.
You should declare points vriable for each players OR reset points variable every time when points variable holds value is greater than or equal to 100.
def start_game(list_of_players):
points = 0 #<----------------- points is local variable to the function
for player in list_of_players:
print("{0} has {1} points.".format(player, points))
print ("==================================================\n")
s = int(input("How many sides of the dice do you want? ")) ###
# validate value of s?
for player in list_of_players:
### the variables declared in for loop is unique to each player
print ("\n{0}'s turn:".format(player))
answer = input("Press y to roll the dice?")
while answer == 'y' and points <= 100:
roll = random.randrange(1, s + 1, 1) ### randrange
if roll > 1:
points += roll
print("{0} has {1} points.".format(player, points))
answer = input("Press y to roll the dice?")
PS. I'm running your code with Python 3.6.1.
Furthermore, one more thing you need to take care of is that for random.randrange(start, stop, step). The output will not include the value of stop. e.g. random.randrange(0, 10, 1) will generate integers from 0 to 9 inclusive. Therefore, if a player chose 6 sides of dice, that means the random number range should be from 1 to 6. In this way, you need to increment whatever number player entered.
e.g. 6 sides of dice
either random.randrange(0, 6+1, 1) or random.randrange(6+1) should work.

Multiple Same Numbers Entered in Guessing Game; Loop Stops Working?

I've been making a 4 number guessing game to learn python that meets three criteria:
replayable
tells player how many tries it took to guess correct answer
tells player how many numbers are correct to steer player to right answer
I thought I met the criteria but there is this really weird bug that happens in the game. If you try to guess the number using trial and error; the game breaks and doesn't detect that your answer is right. If the answer is '[1, 2, 3, 4]' and you try to get the answer by doing '[1, 1, 1, 1]' then '[1, 2, 2, 2,]' and eventually get '[1, 2, 3, 4]'; the program will say that the 4 numbers match but it won't let you win the game and just asks you to play again. This bug has been really killing me and I hope the person reading understands what I'm trying to say.
Sorry about the big long block of code but, the problem could be anywhere here but I honestly cannot see it; I will annotate as best as I can to make it look less confusing. I just... why is this happening!?
def compareLists(a, b): # to compare the guessed numbers and random numbers
return list(set(a) & set(b))
rNums = random.sample(range(10), 4) # random list of numbers
def start():
count = 0 # count for number of tries
global rNums
gNums = [] # guessed numbers
print(rNums) # cheating to save time
flag = True # to stop the guessing loop
while flag:
print("Get ready to guess 4 numbers!")
for i in range(0, 4): # asks the player 4 times to input a number
x = int(input("Guess: "))
gNums.append(x) # puts numbers in guessed numbers
comparison = len(compareLists(rNums, gNums)) # storing the length of the list of similar numbers
isCorrect = gNums == rNums # to check if lists are the same
print("You guessed: ", gNums) # telling player what they have guessed
if isCorrect: # if the lists are the same
if count > 1:
print("You win!! It only took you %d tries!" %count) # telling the player how many tries it took
else: #congratulating the player on a flawless guess
print("I CAN'T BELIEVE WHAT I'M SEEING!!!")
print("YOU GOT IT IN ONE GO!!")
count += 1 # increment count
rNums = random.sample(range(10), 4) # generate new numbers
gNums.clear()
pAgain = input("Play again?")
if pAgain.lower() in ('y', 'yes'): # replaying the game
continue
elif pAgain.lower() in ('n', 'no'):
flag = False
else:
print("Incorrect syntax!")
else:
print("You guessed " + str(comparison) + " numbers right, keep guessing!") # tells the player how many numbers are similar so the player can get a more educated guess
gNums.clear() # empties guessed numbers
count += 1 # increment count
print("Number of tries so far: %d" %count) # showing player number of tries so far
Your comparison for checking if the two lists are the same isn't working:
isCorrect = gNums == rNums # to check if lists are the same
The above code is checking if the two lists are identical, but the elements have to be in the same order.
For your test, you can just check if the number that match (ignoring order) is equal to the length of the list of numbers:
isCorrect = comparison == len(gNums) # to check if lists are the same
For more information on comparing lists regardless of order, see this answer.
Also, you should increment your count before you do your comparison with 1, or else your program will say you only took one go when you actually took two.

Categories