I want to create a battleship AI guessing, where the AI takes random shots until a hit is made.
Once a hit is made, the AI will guess the surrounding coordinates until the orientation of the ship is established.
Once the orientation is known, the AI will guess either side of the hits until the ship is sunk. It will then return to random guessing.
This page under 'a better strategy' explains more of what I want to do but improved so the AI will recognise the orientation.
The code below shows the random guessing currently used:
def ai_guessing():
global player_ships_guessed
while True:
guess_x = random_x()
guess_y = random_y()
# if statement ensuring no guesses are repeated
if playerBoard[guess_x][guess_y] == "O" or playerBoard[guess_x][guess_y] == "S":
break
guess = str(guess_x)+str(guess_y)
What is the best approach to this?
Related
I am trying to make a Tic Tac Toe in tkinter however I am running into some problems with the AI system. What I'm trying to do is that if the middle spot isn't taken it will chose it and if it isn't it will pick a random number and map out all the routes it can take to win and all the routes the player will use and for it to block them however I am running into this problem. My code:
def click1():
if isTaken1 == False:
Button1.config(text = "O")
pTurn1 = True
Button1 = Button(root, command = click1)
Button1.config(width = "5", height = "3")
Button1.place(x = 100, y = 30)
#I have nine of these however I can't show them all as it will make this post very long
I am trying to add it when the player takes a turn (The pTurn variable) it will make the AI act however, I have no idea where to put the AI code.
I am trying to do something like:
If isTaken5 == False: #Checking if the middle spot is taken
Button5.config(text = "X") #Player is O and AI is X
else:
AIChoice = random.randint(1,8)
if AIChoice == 1:
Button1.config(text = "X")
So you get the basic idea for it, but I have no idea where to put the cod as if statements put after where you change it don't work.
In a turn-based game, you can call the AI function immediately after the user takes their turn. For example, let's start with a function for the computer's turn. This is where your ai exists:
def computer_turn():
<your logic to pick an empty square>
Ideally you'll also want to check for the case where the computer picked the last place, but I've left that out now to keep the example simple.
Next, we have a function for the player's turn. In this example, it takes a row and column that was clicked on. This will select the button that was clicked, check to see if the game is over, and call computer_turn if the game isn't over yet.
It would look something like this:
def player_turn(row, column):
<your logic to select the given row and column>
if not is_game_over():
computer_turn()
This isn't the only way to handle the game logic. You could create a small state machine, for example. However, for a game as simple as tic-tac-toe, this turn-based system is good enough.
My code is designed to simulate a basketball game, which simulates a 30-second game with 3 points behind.
The player has to choose whether to shoot a 3-pointer, which requires more time to tie the game and regain possession, or quickly shoot a 2-pointer which is faster, and spend the rest of the time to regain possession by fouling (opponent takes 2 free throws and we regain possession) a player who can't shoot free throws. The game is simulated for about 10000 times to see which play has the highest win rate. The problem is my 'have possession' is a True/False (Boolean), but when I run it through functions, it is returned as an int. Also, the 'pointsdifference' is always the same every time I run the code.
Firstly, why is my Boolean Variable returned as an integer?
And secondly, the win rate should vary since this is a random experiment, but there are only 2 results present. How could this code be adjusted so that my simulation produces random results?
import numpy as np
trials=10000
threeptpercentage=34.6
midrangepercentage=49.5
opposingmidrangepercentage=55.4
opponentfreethrowpercentage=60.6
timetoshoot2=4
timetoshoot3=7
timetofoul=2
offensereboundpercent=66.4
ftreboundpercent=64.3
pointsdown=3
timeleft=30
haveposession=True
wins3=0
wins2=0
wintake3=[]
wintake2=[]
def foul(timeleft,pointsdown,haveposession):
#if we don't have the posession, foul to regain posession
timeleft=timeleft-timetofoul
#opponent takes 2 free throw
if np.random.randint(1,101)<=opponentfreethrowpercentage:
pointsdown=pointsdown+1
if np.random.randint(1,101)<=opponentfreethrowpercentage:
pointsdown=pointsdown+1
haveposession=True
#opponent misses the freethrow and we rebound it
else:
if np.random.randint(1,101)<=ftreboundpercent:
haveposession=True
elif np.random.randint(1,101)<=offensereboundpercent:
pointsdown=pointsdown+2
haveposession=True
return haveposession,timeleft,pointsdown
def take3(timeleft,pointsdown,haveposession):
timeleft = timeleft-timetoshoot3
#do we make the shot?
if np.random.randint(1,101)<=threeptpercentage:
pointsdown=pointsdown-3
haveposession=False
#can we rebound?
else:
if np.random.randint(1,101)<=ftreboundpercent:
haveposession=False
pointsdown=pointsdown-2
elif np.random.randint(1,101)<=opposingmidrangepercentage:
pointsdown=pointsdown+2
haveposession=True
return haveposession,timeleft,pointsdown
#attempt to make a 2 and hope for another posession
def take2(timeleft,pointsdown,haveposession):
#if we are down by 3 or more, take the 2 quickly. if we are down by 2 or less, we tun down the clock
timeleft = timeleft-timetoshoot2
#do we make the shot?
if np.random.randint(1,101)<=midrangepercentage:
pointsdown=pointsdown-2
haveposession=False
#can the opponent rebound?
else:
if np.random.randint(1,101)<=ftreboundpercent:
haveposession=False
pointsdown=pointsdown-2
return haveposession,timeleft,pointsdown
for i in range(1,trials+1):
while timeleft>0:
if haveposession==True:
timeleft,pointsdown,haveposession=take3(timeleft,pointsdown,haveposession)
else:
timeleft,pointsdown,haveposession=foul(timeleft,pointsdown,haveposession)
if pointsdown<0:
wintake3.append(wins3)
while timeleft>0:
if haveposession==True:
timeleft,pointsdown,haveposession=take2(timeleft,pointsdown,haveposession)
else:
timeleft,pointsdown,haveposession=foul(timeleft,pointsdown,haveposession)
if pointsdown<0:
wintake2.append(wins2)
winrate3=len(wintake3)*100/trials
winrate2=len(wintake2)*100/trials
print('Winrate if shoot a 3-pointer =',winrate3,'%')
print('Winrate if shoot a 2-pointer =',winrate2,'%')
I've been trying to make a basic text game in Python, and I'm using dictionaries to contain the player's information. I want to make it so that when a player's health reaches 0, the code will stop running. I've had trouble making that happen. My dictionary, which is at the beginning of my code, looks like this:
playerAtt = {}
playerAtt["Weapon"] = "Baseball bat"
playerAtt["Party"] = "Empty"
playerAtt["Health"] = 15
playerAtt["Cash"] = "$100"
print(playerAtt)
if playerAtt['Health'] <= 0:
exit()
The bottom section is what I wrote to try and make the code stop running when the player's health reached zero, but it doesn't seem to work. In one path of my game, your health gets set to zero and the game is supposed to end, but the program continues to run:
townChoice = raw_input("You met a traveler in the town. 'Yo. I'm Bob. Let's be friends.' Will you invite him to your party? Y/N\n")
if townChoice == 'y' or townChoice == 'Y':
print("That kind traveler was not such a kind traveler. He stabbed you with a machete. RIP " + Name + '.')
playerAtt['Health'] == 0
When you reach this part of the game, all it does is print the message, and moves on to the next decision. In this situation, I could just manually end the program by doing exit() under the print command, but there are circumstances where the player only loses a fraction of their health, and they would eventually reach zero. Sorry if this is a stupid question, I've only been working on Python for a few days.
You have two "=" when you set the player's health to 0
I had put 2 == instead of 1 = when defining
playerAtt["Health"].
Also, I needed to make sure it was constantly checking if the player's health was zero, so I used a while loop. I used
while playerAtt["Health"] = 0:
deathmsg()
exit()
to fix it. deathMsg was a function I made to display a random death message, for more information.
I'm creating a Memory Matching game for a final project for my compsci class.
As of now, I have the cards all appear on the GUI window once you hit start game.
Once start game is hit, all the cards with their face value shows with the back of the card immediately. (So you never actually see the card fronts)
My reasoning for doing this is so that when you click on a card, I'll simply undraw the back card image instead of "Flipping" anything.
However, I keep getting errors, and when I don't get errors, it simply results in my program saying "Not Responding" and makes me have to restart the Shell.
Here are some little bits and pieces of my code which I think pertain to my issue:
for firstcard in range(6):
firstrow = self.deck.dealCard()
randomsuite = firstrow.getSuite()
randomrank = firstrow.getRank()
#Real image with face value of card
realCard = Image(Point(xpos,ypos),"playingcards/"+ (randomsuite) + str(randomrank) +".gif")
realCard.draw(win)
#Red Back of card to cover image
firstcard = Image(Point(xpos,ypos),"playingcards/b1fv.gif")
firstcard.draw(win)
#pushes the card to the right a bit
xpos += 100
while not Quitbutton.isClicked(p):
#Start Game
if StartGameButton.isClicked(p) and player == True:
if first == True:
Game.gameboard(win,150,125)
firstcard = Image(Point(xpos,ypos),"playingcards/b1fv.gif")
first = False
if StartGameButton.isClicked(p):
p = win.getMouse()
if firstcard.isClicked(p):
firstcard.undraw()
p = win.getMouse()
As of now you can see I have in my code if firstcard.isClicked(p):. However, this doesn't actually work because my isClicked function is a part of a Button Class and therefore, only works when dealing with Buttons and not images. So I'm not entirely sure what to do to select a single card and how to show that that card has been clicked and therefore should be undrawn
Below is the troubling code with a quick breakdown.
if player.attacked == True and delay >= 60: #if it's monster's turn plus a built in delay so everything isn't instant
for enemy in enemies_list: #iterating the all the enemies in the sprite group
if enemy.attack_rdy == True and enemy.health >0 and delay ==60: #if THAT particular monster hasn't attacked, isn't dead, and the delay has been long enough.
player.hit.play() #play the player's damaged sound
damage = random.randrange(each.attack[0],each.attack[1]+1)-player.armor #random attack roll of a tuple assigned to the enemy class
player.health -= damage
enemy.attack_rdy = False #Sets THIS particular enemy so that he may not attack until it's his turn again
player.damaged = True #Just triggers an animation on the player
each.attack_anim = 1 #triggers an animation on the enemy
break #stops the for loop so that everything doesn't happen at once and relies on the delay int.
Problem:
This iteration works properly in that the player is accurately attacked the correct number of times in accordance to the number of enemies attacking him. For some weird reason the same enemy will be attacking all those times however. When the attacking enemy dies, another one simply takes over his task of being the one who attacks. I can make no sense of it.
In true bonehead fashion, after staring at and editing my code for hours I find my blunder mere moments after posting. It's really just a stupid error.
each.attack_anim = 1
SHOULD read
enemy.attack_anim = 1
With blunder corrected, code runs as designed.