问题
I have created a dice betting game. When my code is run, there is a "CLICK TO ROLL" button. Currently, if you click anywhere on the screen, the dice will roll. How can I make it so the program closes if you click anywhere outside the box, and only if you click inside the box the dice rolls?
import graphics
from graphics import *
from random import randrange
max_x = 500
max_y = 300
win = GraphWin("Dice Rolls", max_x,max_y)
#drives the program
def main():
class dots():
#Drawn dots
def __init__(self,p_x=0,p_y=0,p_s=50):
self.m_x = p_x
self.m_y = p_y
self.m_dice_size = p_s
self.m_items = []
dot_size = 4
x = self.m_x
y = self.m_y
s = self.m_dice_size
d = s/4
self.m_items.append(Circle(Point(x+2*d, y+2*d), dot_size))
self.m_items.append(Circle(Point(x+1*d, y+1*d), dot_size))
self.m_items.append(Circle(Point(x+1*d, y+2*d), dot_size))
self.m_items.append(Circle(Point(x+1*d, y+3*d), dot_size))
self.m_items.append(Circle(Point(x+3*d, y+1*d), dot_size))
self.m_items.append(Circle(Point(x+3*d, y+2*d), dot_size))
self.m_items.append(Circle(Point(x+3*d, y+3*d), dot_size))
for dot in self.m_items:
dot.setFill('black')
#Displays three dice images based on the random value
def display_dice(self):
return (self.m_x,self.m_y,self.m_s)
def undraw(self):
for dot in self.m_items:
dot.undraw()
#Drawn Dice
def draw(self, p_win, p_num):
for dot in self.m_items:
dot.undraw()
if (p_num==1):
self.m_items[0].draw(p_win)
elif (p_num==2):
self.m_items[3].draw(p_win)
self.m_items[4].draw(p_win)
elif (p_num==3):
self.m_items[0].draw(p_win)
self.m_items[3].draw(p_win)
self.m_items[4].draw(p_win)
elif (p_num==4):
self.m_items[1].draw(p_win)
self.m_items[3].draw(p_win)
self.m_items[4].draw(p_win)
self.m_items[6].draw(p_win)
elif (p_num==5):
self.m_items[0].draw(p_win)
self.m_items[1].draw(p_win)
self.m_items[3].draw(p_win)
self.m_items[4].draw(p_win)
self.m_items[6].draw(p_win)
elif (p_num==6):
self.m_items[1].draw(p_win)
self.m_items[2].draw(p_win)
self.m_items[3].draw(p_win)
self.m_items[4].draw(p_win)
self.m_items[5].draw(p_win)
self.m_items[6].draw(p_win)
#Prepares for next roll
class dice_t:
def __init__(self,x=0,y=0):
self.m_x = x
self.m_y = y
self.m_s = 50
self.m_item = Rectangle(Point(self.m_x,self.m_y),Point(self.m_x+self.m_s,self.m_y+self.m_s))
self.m_item.setFill('white')
self.m_dots = dots(self.m_x,self.m_y,self.m_s)
def display_dice(self):
return (self.m_x,self.m_y,self.m_s)
def draw_die(self, p_win):
self.m_item.undraw()
self.m_item.draw(p_win)
def draw(self, p_win, p_num):
self.draw_die(p_win)
self.m_dots.draw(p_win,p_num)
def undraw(self):
self.m_item.undraw()
self.m_dots.undraw()
#Winnings and losing calculation
def check_winner(p_rolls=[]):
last = None
total = 0
triple = True
for r in p_rolls:
if (last!=None) and (last!=r):
triple = False
last = r
total += r
if (total==3) or (total==18):
return 10
elif (total==4) or (total==17):
return 5
elif (triple ==True):
return 2
return -1
#Text and instructions/rules
def get_bet(p_win,p_balance,p_def_bet):
inst = []
inst.append(Text(Point(max_x/2,20), "MAKE YOUR BET: "))
inst.append(Text(Point(max_x/2,40), "BALANCE:"+str(p_balance)))
inst.append(Text(Point(max_x/2,70), "Rules: "))
inst.append(Text(Point(max_x/2,90), "If you roll a 3 or 18 in total your bet winnings will be 10x your bet."))
inst.append(Text(Point(max_x/2,110), "If you roll a 4 or 17 in total your bet winnings will be 5x your bet."))
inst.append(Text(Point(max_x/2,130), "If you roll triples besides a 3 and 18 your bet winnings will be 2x your bet."))
inst.append(Text(Point(max_x/2,150), 'If you roll anything else, you lose your bet.'))
inst.append(Rectangle(Point(max_x/2-59,190), Point(max_x/2+59, 210)))
inst.append(Text(Point(max_x/2, 200), 'CLICK TO ROLL'))
for item in inst:
item.draw(p_win)
bet_text = str(p_def_bet)
bet_input = Entry(Point (max_x/2+100, 20),5)
bet_input.setText(bet_text)
bet_input.draw(p_win)
p_win.getMouse()
bet_text = bet_input.getText()
bet = int(bet_text)
bet_input.undraw()
for item in inst:
item.undraw()
return bet
#Shows winnings, checks for winner, updates total, and returns the updated total
def show_winnings(p_win, p_winnings):
inst = []
inst.append(Text(Point(max_x/2,90), "Your WINNINGS:"+str(winnings)))
inst.append(Rectangle(Point(max_x/2-50,190), Point(max_x/2+50, 210)))
inst.append(Text(Point(max_x/2, 200), 'PLAY AGAIN'))
for item in inst:
item.draw(p_win)
p_win.getMouse()
for item in inst:
item.undraw()
#Shows bet
def show_bet_invalid(p_win):
inst = []
inst.append(Text(Point(max_x/2,90), "YOUR BET WAS INVALID"))
inst.append(Rectangle(Point(max_x/2-50,190), Point(max_x/2+50, 210)))
inst.append(Text(Point(max_x/2, 200), 'TRY AGAIN'))
for item in inst:
item.draw(p_win)
p_win.getMouse()
for item in inst:
item.undraw()
#Shows game over
def show_game_over(p_win):
inst = []
inst.append(Text(Point(max_x/2,90), "YOU ARE OUT OF MONEY"))
inst.append(Rectangle(Point(max_x/2-50,190), Point(max_x/2+50, 210)))
inst.append(Text(Point(max_x/2, 200), 'QUIT'))
for item in inst:
item.draw(p_win)
p_win.getMouse()
for item in inst:
item.undraw()
# M A I N and balances along with random outputs
#################################################
dice = []
for d in range(0,3):
dice.append(dice_t(max_x/2-90+d*60,5))
balance = 100
def_bet = 10
while ( balance > 0 ):
bet_invalid = True
while (bet_invalid):
bet = get_bet(win,balance,def_bet)
if (bet>=1) and (bet<=balance):
bet_invalid = False
else:
show_bet_invalid(win)
def_bet = bet
rolls = []
for r in range(0,3):
roll = randrange(1, 7)
dice[r].draw(win,roll)
rolls.append(roll)
winnings = check_winner(rolls) * bet
balance += winnings
show_winnings(win, winnings)
for r in range(0,3):
dice[r].undraw()
show_game_over(win)
main()
回答1:
I'd suggest using a gui framework like tkinter
import tkinter
root = tkinter.tk()
def on_click():
print('clicked')
btn = tkinter.Button(root, command=on_click)
root.mainloop()
回答2:
How can I make it so the program closes if you click anywhere outside the box
This is simple to do given the way you've designed your interface. We can change this code:
inst.append(Rectangle(Point(max_x/2-59,190), Point(max_x/2+59, 210)))
...
p_win.getMouse()
To instead be:
rectangle = Rectangle(Point(max_x/2 - 59, 190), Point(max_x/2 + 59, 210))
inst.append(rectangle)
...
point = p_win.getMouse()
if not inside(point, rectangle):
p_win.close()
exit()
Where inside()
is defined as:
def inside(point, rectangle):
p1 = rectangle.getP1()
p2 = rectangle.getP2()
return p1.getX() <= point.getX() <= p2.getX() and p1.getY() <= point.getY() <= p2.getY()
And we can do the same for 'PLAY AGAIN'
.
However, your code is hard to follow as it is dense and embedded inside main()
. I've reworked your code below to extract it from main()
, make the above changes, and work on the style:
from random import randrange
from graphics import *
MAX_X, MAX_Y = 500, 300
PIP_SIZE = 4
DICE_SIZE = 50
class Pips():
""" Draw pips """
def __init__(self, x, y, dice_size):
self.m_x = x
self.m_y = y
d = dice_size / 4
self.m_items = []
self.m_items.append(Circle(Point(x + 2 * d, y + 2 * d), PIP_SIZE))
self.m_items.append(Circle(Point(x + 1 * d, y + 1 * d), PIP_SIZE))
self.m_items.append(Circle(Point(x + 1 * d, y + 2 * d), PIP_SIZE))
self.m_items.append(Circle(Point(x + 1 * d, y + 3 * d), PIP_SIZE))
self.m_items.append(Circle(Point(x + 3 * d, y + 1 * d), PIP_SIZE))
self.m_items.append(Circle(Point(x + 3 * d, y + 2 * d), PIP_SIZE))
self.m_items.append(Circle(Point(x + 3 * d, y + 3 * d), PIP_SIZE))
for pip in self.m_items:
pip.setFill('black')
def undraw(self):
for pip in self.m_items:
pip.undraw()
def draw(self, p_win, p_num):
""" Draw Dice """
self.undraw()
if p_num == 1:
self.m_items[0].draw(p_win)
elif p_num == 2:
self.m_items[3].draw(p_win)
self.m_items[4].draw(p_win)
elif p_num == 3:
self.m_items[0].draw(p_win)
self.m_items[3].draw(p_win)
self.m_items[4].draw(p_win)
elif p_num == 4:
self.m_items[1].draw(p_win)
self.m_items[3].draw(p_win)
self.m_items[4].draw(p_win)
self.m_items[6].draw(p_win)
elif p_num == 5:
self.m_items[0].draw(p_win)
self.m_items[1].draw(p_win)
self.m_items[3].draw(p_win)
self.m_items[4].draw(p_win)
self.m_items[6].draw(p_win)
elif p_num == 6:
self.m_items[1].draw(p_win)
self.m_items[2].draw(p_win)
self.m_items[3].draw(p_win)
self.m_items[4].draw(p_win)
self.m_items[5].draw(p_win)
self.m_items[6].draw(p_win)
class Dice_t:
""" Prepares for next roll """
def __init__(self, x, y):
self.m_x = x
self.m_y = y
self.m_s = DICE_SIZE
self.m_item = Rectangle(Point(x, y), Point(x + self.m_s, y + self.m_s))
self.m_item.setFill('white')
self.m_pips = Pips(x, y, self.m_s)
def draw_die(self, p_win):
self.m_item.undraw()
self.m_item.draw(p_win)
def draw(self, p_win, p_num):
self.draw_die(p_win)
self.m_pips.draw(p_win, p_num)
def undraw(self):
self.m_item.undraw()
self.m_pips.undraw()
def inside(point, rectangle):
p1 = rectangle.getP1()
p2 = rectangle.getP2()
return p1.getX() <= point.getX() <= p2.getX() and p1.getY() <= point.getY() <= p2.getY()
def get_bet(p_win, p_balance, p_def_bet):
""" Text and instructions/rules"""
inst = []
inst.append(Text(Point(MAX_X/2, 20), "MAKE YOUR BET:"))
inst.append(Text(Point(MAX_X/2, 40), "BALANCE: " + str(p_balance)))
inst.append(Text(Point(MAX_X/2, 70), "Rules:"))
inst.append(Text(Point(MAX_X/2, 90), "If you roll a 3 or 18 in total your bet winnings will be 10x your bet."))
inst.append(Text(Point(MAX_X/2, 110), "If you roll a 4 or 17 in total your bet winnings will be 5x your bet."))
inst.append(Text(Point(MAX_X/2, 130), "If you roll triples besides a 3 and 18 your bet winnings will be 2x your bet."))
inst.append(Text(Point(MAX_X/2, 150), "If you roll anything else, you lose your bet."))
rectangle = Rectangle(Point(MAX_X/2 - 59, 190), Point(MAX_X/2 + 59, 210))
inst.append(rectangle)
inst.append(Text(Point(MAX_X/2, 200), 'CLICK TO ROLL'))
for item in inst:
item.draw(p_win)
bet_input = Entry(Point(MAX_X/2 + 100, 20), 5)
bet_input.setText(str(p_def_bet))
bet_input.draw(p_win)
point = p_win.getMouse()
if not inside(point, rectangle):
p_win.close()
exit()
bet = int(bet_input.getText())
bet_input.undraw()
for item in inst:
item.undraw()
return bet
def show_winnings(p_win, p_winnings):
""" Shows winnings, checks for winner, updates total, and returns the updated total """
inst = []
inst.append(Text(Point(MAX_X/2, 90), "Your WINNINGS: " + str(p_winnings)))
rectangle = Rectangle(Point(MAX_X/2 - 50, 190), Point(MAX_X/2 + 50, 210))
inst.append(rectangle)
inst.append(Text(Point(MAX_X/2, 200), 'PLAY AGAIN'))
for item in inst:
item.draw(p_win)
point = p_win.getMouse()
if not inside(point, rectangle):
p_win.close()
exit()
for item in inst:
item.undraw()
def check_winner(p_rolls):
""" Winnings and losing calculation """
last = None
total = 0
triple = True
for r in p_rolls:
if last is not None and last != r:
triple = False
last = r
total += r
if total == 3 or total == 18:
return 10
if total == 4 or total == 17:
return 5
if triple:
return 2
return -1
def show_bet_invalid(p_win):
""" Shows invalid bet """
inst = []
inst.append(Text(Point(MAX_X/2, 90), "YOUR BET WAS INVALID"))
inst.append(Rectangle(Point(MAX_X/2 -50, 190), Point(MAX_X/2 + 50, 210)))
inst.append(Text(Point(MAX_X/2, 200), 'TRY AGAIN'))
for item in inst:
item.draw(p_win)
p_win.getMouse()
for item in inst:
item.undraw()
def show_game_over(p_win):
""" Shows game over """
inst = []
inst.append(Text(Point(MAX_X/2, 90), "YOU ARE OUT OF MONEY"))
inst.append(Rectangle(Point(MAX_X/2 - 50, 190), Point(MAX_X/2 + 50, 210)))
inst.append(Text(Point(MAX_X/2, 200), 'QUIT'))
for item in inst:
item.draw(p_win)
p_win.getMouse()
for item in inst:
item.undraw()
def main():
""" Drives the program """
# M A I N and balances along with random outputs
#################################################
win = GraphWin("Dice Rolls", MAX_X, MAX_Y)
dice = [Dice_t(MAX_X/2 - 90 + d * 60, 5) for d in range(3)]
balance = 100
def_bet = 10
while balance > 0:
bet_invalid = True
while bet_invalid:
bet = get_bet(win, balance, def_bet)
if 1 <= bet <= balance:
bet_invalid = False
else:
show_bet_invalid(win)
def_bet = bet
rolls = []
for r in range(3):
roll = randrange(1, 7)
dice[r].draw(win, roll)
rolls.append(roll)
winnings = check_winner(rolls) * bet
balance += winnings
show_winnings(win, winnings)
for r in range(3):
dice[r].undraw()
show_game_over(win)
main()
And they're called pips, not dots.
来源:https://stackoverflow.com/questions/53863106/detect-if-you-click-inside-a-box-in-python-zelle-graphics