Detect if you click inside a box in Python Zelle graphics

前提是你 提交于 2019-12-08 14:18:13

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!