Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pygame Basic calculator

Tags:

python

pygame

I am trying to make a basic calculator but the problem I am having is how do I output the text? How do I make it so when I click plus it allows me to add or if I click divide it allows me to divide and shows the output on the yellow part on my screen

enter image description here

This is what I have right now. You could run it; there is nothing special. My question is how could I make the calculator make it so when I click plus and then go and add up numbers it allows me to add or when I click divide it allows me to divide my numbers and show the outputs on the screen?

import pygame,math
pygame.init()

window_height = 500
window_width = 500
window  = pygame.display.set_mode((window_height,window_width))

    # the buttons for the shop MENU
class button():
    def __init__(self, color, x,y,width,height, text=''):
        self.color = color
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.text = text
        self.over = False

    def draw(self,window,outline=None):
                #Call this method to draw the button on the screen
        if outline:
            pygame.draw.rect(window, outline, (self.x-2,self.y-2,self.width+4,self.height+4),0)
                    
        pygame.draw.rect(window, self.color, (self.x,self.y,self.width,self.height),0)
                
        if self.text != '':
            font = pygame.font.SysFont('comicsans', 60)
            text = font.render(self.text, 1, (0,0,0))
            window.blit(text, (self.x + (self.width/2 - text.get_width()/2), self.y + (self.height/2 - text.get_height()/2)))

    def isOver(self, pos):
                #Pos is the mouse position or a tuple of (x,y) coordinates
        if pos[0] > self.x and pos[0] < self.x + self.width:
            if pos[1] > self.y and pos[1] < self.y + self.height:
                return True
                    
        return False

    def playSoundIfMouseIsOver(self, pos, sound):
        if self.isOver(pos):            
            if not self.over:
                beepsound.play()
                self.over = True
        else:
            self.over = False
                    
white = (255,255,255)
# the numbers for the calcaltor
s_1s = button((0,255,0),40,450,30,30, '1')
s_2s = button((0,255,0),40,400,30,30, '2')
s_3s = button((0,255,0),40,350,30,30, '3')
s_4s = button((0,255,0),100,450,30,30, '4')
s_5s = button((0,255,0),100,400,30,30, '5')
s_6s = button((0,255,0),100,350,30,30, '6')
s_7s = button((0,255,0),150,450,30,30, '7')
s_8s = button((0,255,0),150,400,30,30, '8')
s_9s = button((0,255,0),150,350,30,30, '9')
s_0s = button((0,255,0),200,450,30,30, '0')

numbers = [s_1s,s_2s,s_3s,s_4s,s_5s,s_6s,s_7s,s_8s,s_9s,s_0s]

# the symbols!
d_1s = button((0,255,0),260,450,30,30, '+')
d_2s = button((0,255,0),260,400,30,30, '-')
d_3s = button((0,255,0),260,350,30,30, 'x')
d_4s = button((0,255,0),200,400,30,30, '÷')

symbols = [d_1s,d_2s,d_3s,d_4s]

# input tap
inputtap = button((253,100,32),10,280,450,50,"")

# redraw window
def redraw():
    # draw all the numbers
    for button in numbers:
        button.draw(window)

    # the symbols
    for button in symbols:
        button.draw(window)

    inputtap.draw(window)
 
def Symbols():
    
    if event.type == pygame.MOUSEBUTTONDOWN:
        pos = pygame.mouse.get_pos()
            
        if d_1s.isOver(pos):
            print("+")

        if d_2s.isOver(pos):
            print("-")

        if d_3s.isOver(pos):
            print("x")

        if d_4s.isOver(pos):
            print("÷")
    

def MOUSEOVERnumbers():
    if event.type == pygame.MOUSEBUTTONDOWN:
        pos = pygame.mouse.get_pos()          
        if s_1s.isOver(pos):
            print("1")
        if s_2s.isOver(pos):
            print("2")
        if s_3s.isOver(pos):
            print("3")
        if s_4s.isOver(pos):
            print("4")
        if s_5s.isOver(pos):
            print("5")
        if s_6s.isOver(pos):
            print("6")
        if s_7s.isOver(pos):
            print("7")
        if s_8s.isOver(pos):
            print("8")
        if s_9s.isOver(pos):
            print("9")
        if s_0s.isOver(pos):
            print("0")            

# the main loop
run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

        MOUSEOVERnumbers()

        Symbols()

    redraw()
    pygame.display.update()
pygmae.quit()

like image 208
Habib Ismail Avatar asked Aug 01 '20 00:08

Habib Ismail


People also ask

How do you calculate in Python?

For straightforward mathematical calculations in Python, you can use the built-in mathematical operators, such as addition ( + ), subtraction ( - ), division ( / ), and multiplication ( * ). But more advanced operations, such as exponential, logarithmic, trigonometric, or power functions, are not built in.


2 Answers

You could add a = button, so every time user clicks it, calculate the user input with python eval() function.

As for the user input, you first need to record it globally . Then you can pass user input to the string field of inputtap = button((253,100,32),10,280,450,50,"") to show it on the window.

import pygame, math

pygame.init()

window_height = 500
window_width = 600
window  = pygame.display.set_mode((window_height,window_width))

# the buttons for the shop MENU
class button():
    def __init__(self, color, x,y,width,height, text=''):
        self.color = color
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.text = text
        self.over = False

    def draw(self,window,outline=None):
        #Call this method to draw the button on the screen
        if outline:
            pygame.draw.rect(window, outline, (self.x-2,self.y-2,self.width+4,self.height+4),0)
                    
        pygame.draw.rect(window, self.color, (self.x,self.y,self.width,self.height),0)
                
        if self.text != '':
            font = pygame.font.SysFont('comicsans', 60)
            text = font.render(self.text, 1, (0,0,0))
            window.blit(text, (self.x + (self.width/2 - text.get_width()/2), self.y + (self.height/2 - text.get_height()/2)))

    def isOver(self, pos):
        #Pos is the mouse position or a tuple of (x,y) coordinates
        if pos[0] > self.x and pos[0] < self.x + self.width:
            if pos[1] > self.y and pos[1] < self.y + self.height:
                return True
        return False

    def playSoundIfMouseIsOver(self, pos, sound):
        if self.isOver(pos):            
            if not self.over:
                beepsound.play()
                self.over = True
        else:
            self.over = False
                    
white = (255,255,255)
# the numbers for the calcaltor
s_1s = button((0,255,0),40,450,30,30, '1')
s_2s = button((0,255,0),40,400,30,30, '2')
s_3s = button((0,255,0),40,350,30,30, '3')
s_4s = button((0,255,0),100,450,30,30, '4')
s_5s = button((0,255,0),100,400,30,30, '5')
s_6s = button((0,255,0),100,350,30,30, '6')
s_7s = button((0,255,0),150,450,30,30, '7')
s_8s = button((0,255,0),150,400,30,30, '8')
s_9s = button((0,255,0),150,350,30,30, '9')
s_0s = button((0,255,0),200,450,30,30, '0')

numbers = [s_1s,s_2s,s_3s,s_4s,s_5s,s_6s,s_7s,s_8s,s_9s,s_0s]

# the symbols!
d_1s = button((0,255,0),260,450,30,30, '+')
d_2s = button((0,255,0),260,400,30,30, '-')
d_3s = button((0,255,0),260,350,30,30, 'x')
d_4s = button((0,255,0),200,400,30,30, '÷')
d_5s = button((0,255,0),200,350,30,30, '=')
d_6s = button((0,255,0),260,500,30,30, 'C')

symbols = [d_1s,d_2s,d_3s,d_4s,d_5s,d_6s]


# redraw window
def redraw(inputtap):
    # draw all the numbers
    for button in numbers:
        button.draw(window)

    # the symbols
    for button in symbols:
        button.draw(window)

    inputtap.draw(window)

def Symbols():
    global user_input
    global python_input
    global is_finished

    if event.type == pygame.MOUSEBUTTONDOWN:
        pos = pygame.mouse.get_pos()

        try:
            if is_finished or user_input[-1] in ["+", "-", "x", "÷", "="]:
                # User shouldn't type two symbols continuously
                # User shouldn't input any symbols when game finished because there is no number
                return
        except IndexError:
            # User shouldn't input any symbols if there is no number
            return


        if d_1s.isOver(pos):
            print("+")
            user_input += "+"
            python_input += "+"

        if d_2s.isOver(pos):
            print("-")
            user_input += "-"
            python_input += "-"

        if d_3s.isOver(pos):
            print("x")
            user_input += "x"
            python_input += "*"

        if d_4s.isOver(pos):
            print("÷")
            user_input += "÷"
            python_input += "/"

        if d_5s.isOver(pos):
            print("=")
            result = eval(python_input)
            python_input = ""
            user_input += f"={result:.2f}"
            is_finished = True

        if d_6s.isOver(pos):
            print("C")
            python_input = ""
            user_input = ""

def MOUSEOVERnumbers():
    global user_input
    global python_input
    global is_finished

    if event.type == pygame.MOUSEBUTTONDOWN:
        if is_finished:
            user_input = ""
            python_input = ""
            is_finished = False
        pos = pygame.mouse.get_pos()          
        if s_1s.isOver(pos):
            print("1")
            user_input += "1"
            python_input += "1"
        if s_2s.isOver(pos):
            print("2")
            user_input += "2"
            python_input += "2"
        if s_3s.isOver(pos):
            print("3")
            user_input += "3"
            python_input += "3"
        if s_4s.isOver(pos):
            print("4")
            user_input += "4"
            python_input += "4"
        if s_5s.isOver(pos):
            print("5")
            user_input += "5"
            python_input += "5"
        if s_6s.isOver(pos):
            print("6")
            user_input += "6"
            python_input += "6"
        if s_7s.isOver(pos):
            print("7")
            user_input += "7"
            python_input += "7"
        if s_8s.isOver(pos):
            print("8")
            user_input += "8"
            python_input += "8"
        if s_9s.isOver(pos):
            print("9")
            user_input += "9"
            python_input += "9"
        if s_0s.isOver(pos):
            print("0")
            user_input += "0"
            python_input += "0"

# the main loop
run = True
user_input = ""
python_input = ""
is_finished = True

while run:
    # input tap
    inputtap = button((253,100,32),10,280,450,50,f"{user_input}")

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

        MOUSEOVERnumbers()

        Symbols()

    redraw(inputtap)
    pygame.display.update()

pygame.quit()

You then can add a reset button to reset the user input. Also after user clicks = button, start a new user input rather then concatting on the old one.

The reset button is labeled with C in this example. Every time user clicks it, empty the user input string and the python input string.

I also use a global is_finished boolean variable to check if user clicks = button. If user clicks it, it means user has finished the calculation, so that next time user clicks any symbols button, the user input string is cleared.

In the meanwhile, user shouldn't input two sysmbols except C button at the same time. I judge it by comparing the last character user inputs and the current character user inputs.

Also, user shouldn't input any symbol before inputting any number. I judge it with global variable is_finished. If is_finished is true, it means user doesn't start inputting, so there is no value in the user input string. I also use a IndexError exception just in case because empty user input string cann't work with negative index.

To distinguish between integer and float result, you can judge if there is dot in the result:

>>> '.' in '45.3'
True
>>> '.' in '453'
False

At last, you can also simplify those if logic with button.text properties like what Rabbid76 does:

        for number_button in numbers:
            if number_button.isOver(pos):
                print(number_button.text)
                user_input += number_button.text
                python_input += number_button.text
like image 71
Ynjxsjmh Avatar answered Nov 14 '22 21:11

Ynjxsjmh


Implement a class that can perform arithmetic operations and stores the current text, which has to be displayed (self.currentText) on the display:

class Calculate:
    def __init__(self):
        self.currentValue = 0
        self.newNumber = 0
        self.currentOperation = None
        self.currentText = ""
    def newDigit(self, text):
        self.newNumber = self.newNumber * 10 + int(text) 
        self.currentText = str(self.newNumber)
    def newOperation(self, op):
        try:
            if self.currentOperation == '+':
                self.currentValue += self.newNumber
            elif self.currentOperation == '-':
                self.currentValue -= self.newNumber
            elif self.currentOperation == 'x':
                self.currentValue *= self.newNumber
            elif self.currentOperation == '÷':
                self.currentValue /= self.newNumber
            elif self.currentOperation != "=":
                self.currentValue = self.newNumber
        except:
            self.currentValue = 0
        self.currentOperation = op
        self.currentText = str(self.currentValue)
        self.newNumber = 0

calculator = Calculate()

Draw the text self.currentText in redraw

def redraw():
    # [...]

    inputtap.draw(window)
    inputtext = font.render(calculator.currentText, True, (0, 0, 0))
    window.blit(inputtext, (inputtap.x + inputtap.width - inputtext.get_width() - 4, inputtap.y + 4))

Invoke calculator.newDigit when a digit is pressed:

def MOUSEOVERnumbers():
    if event.type == pygame.MOUSEBUTTONDOWN:
        for button in numbers:
            if button.isOver(event.pos):
                print(button.text)  
                calculator.newDigit(button.text)

Invoke calculator.newOperation when an operation button is pressed:

def Symbols():  
    if event.type == pygame.MOUSEBUTTONDOWN:
        for button in symbols:
            if button.isOver(event.pos):
                print(button.text)
                calculator.newOperation(button.text)
        if clearButton.isOver(event.pos):
            calculator = Calculate()

See the complete example:

import pygame,math
pygame.init()

window_height = 500
window_width = 500
window  = pygame.display.set_mode((window_height,window_width))

font = pygame.font.SysFont('comicsans', 60)

    # the buttons for the shop MENU
class Button():
    def __init__(self, color, x,y,width,height, text=''):
        self.color = color
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.text = text
        self.over = False
        self.image = font.render(self.text, 1, (0,0,0))

    def draw(self,window,outline=None):
                #Call this method to draw the button on the screen
        if outline:
            pygame.draw.rect(window, outline, (self.x-2,self.y-4,self.width+4,self.height+8),0)
                    
        pygame.draw.rect(window, self.color, (self.x,self.y-2,self.width,self.height+4),0)
                
        if self.text != '':
            w, h = self.image.get_size()
            window.blit(self.image, (self.x + (self.width//2 - w//2), self.y + (self.height//2 - h//2 + 2)))

    def isOver(self, pos):
                #Pos is the mouse position or a tuple of (x,y) coordinates
        if pos[0] > self.x and pos[0] < self.x + self.width:
            if pos[1] > self.y and pos[1] < self.y + self.height:
                return True
                    
        return False

    def playSoundIfMouseIsOver(self, pos, sound):
        if self.isOver(pos):            
            if not self.over:
                beepsound.play()
                self.over = True
        else:
            self.over = False

class Calculate:
    def __init__(self):
        self.currentValue = 0
        self.newNumber = 0
        self.currentOperation = None
        self.currentText = ""
    def newDigit(self, text):
        self.newNumber = self.newNumber * 10 + int(text) 
        self.currentText = str(self.newNumber)
    def newOperation(self, op):
        try:
            if self.currentOperation == '+':
                self.currentValue += self.newNumber
            elif self.currentOperation == '-':
                self.currentValue -= self.newNumber
            elif self.currentOperation == 'x':
                self.currentValue *= self.newNumber
            elif self.currentOperation == '÷':
                self.currentValue /= self.newNumber
            elif self.currentOperation != "=":
                self.currentValue = self.newNumber
        except:
            self.currentValue = 0
        self.currentOperation = op
        self.currentText = str(self.currentValue)
        self.newNumber = 0

calculator = Calculate()
        
                    
white = (255,255,255)
# the numbers for the calcaltor
s_1s = Button((0,255,0),40,450,30,30, '1')
s_2s = Button((0,255,0),40,400,30,30, '2')
s_3s = Button((0,255,0),40,350,30,30, '3')
s_4s = Button((0,255,0),100,450,30,30, '4')
s_5s = Button((0,255,0),100,400,30,30, '5')
s_6s = Button((0,255,0),100,350,30,30, '6')
s_7s = Button((0,255,0),150,450,30,30, '7')
s_8s = Button((0,255,0),150,400,30,30, '8')
s_9s = Button((0,255,0),150,350,30,30, '9')
s_0s = Button((0,255,0),200,450,30,30, '0')

numbers = [s_1s,s_2s,s_3s,s_4s,s_5s,s_6s,s_7s,s_8s,s_9s,s_0s]

# the symbols!
d_1s = Button((0,255,0),260,450,30,30, '+')
d_2s = Button((0,255,0),260,400,30,30, '-')
d_3s = Button((0,255,0),260,350,30,30, 'x')
d_4s = Button((0,255,0),200,400,30,30, '÷')
d_5s = Button((0,255,0),320,450,30,30, '=')

symbols = [d_1s,d_2s,d_3s,d_4s,d_5s]

clearButton = Button((0,255,0),200,350,30,30, 'C')

allButtons = numbers + symbols + [clearButton]

# input tap
inputtap = Button((253,100,32),10,280,450,50,"")

# redraw window
def redraw():
    for button in allButtons:
        button.draw(window)

    inputtap.draw(window)
    inputtext = font.render(calculator.currentText, True, (0, 0, 0))
    window.blit(inputtext, (inputtap.x + inputtap.width - inputtext.get_width() - 4, inputtap.y + 4))
 
def Symbols():  
    global calculator
    if event.type == pygame.MOUSEBUTTONDOWN:
        for button in symbols:
            if button.isOver(event.pos):
                print(button.text)
                calculator.newOperation(button.text)
        if clearButton.isOver(event.pos):
            calculator = Calculate()
    
def MOUSEOVERnumbers():
    if event.type == pygame.MOUSEBUTTONDOWN:
        for button in numbers:
            if button.isOver(event.pos):
                print(button.text)  
                calculator.newDigit(button.text)

# the main loop
run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

        MOUSEOVERnumbers()
        Symbols()

    redraw()
    pygame.display.update()
pygmae.quit()
like image 30
Rabbid76 Avatar answered Nov 14 '22 21:11

Rabbid76