问题
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