How to Run it Without Python

Hello Everyone.

I completed a challenge from the book Python Programming for the Absolute Beginner, Third Edition on GUI development. I had to make a GUI version of a “Guess my number” game. I did it well (according to me), I will leave my code below. But I was wandering, How would a user that does not have Python installed on their PC play the game? Will I have to make it an app file or something?

#Guess my Number GUI Edition
#Import all necesarry modules (random, games and * from tkinter)

import random, games
from tkinter import *

class Adivina(Frame):
    """Guess My Number GUI Version"""
 
    def __init__(self, master):
        """Set the attributes"""
        
        #inherit master's attributes
        super(Adivina, self).__init__(master)
        self.min_num = 1 #minimum number to guess
        self.max_num = 30 #maximum number to guess
        self.max_attempts = 5 #maximum number of attempts
        
        #This to do to display first GUI widgets
        self.grid()
        self.first_GUI_widgets()

    def first_GUI_widgets(self):
        """Creates first GUI elements"""
       
        #display instructions label
        Label(self, text = "Guess a number"\
              " between " + str(self.min_num) + " and " \
              + str(self.max_num)).grid(row = 0, column = 0, sticky = N, pady = 15)

        #display label and input for number of trials
        self.label_attempts = Label(self, text = "How many attempts would you like? "\
              "(" + str(self.max_attempts) + " maximum" + ")")
        
        self.label_attempts.grid(row = 3, column = 0, sticky = W)

        self.entry_attempts = Entry(self)
        self.entry_attempts.grid(row = 4, column = 0, sticky = N, pady = 10)

        #display a submit button for that when it's done
        self.button_attempts = Button(self, text = "Submit", command = self.attempts_number)
        self.button_attempts.grid(row = 5, column = 0, sticky = S, pady = 5)

    def attempts_number(self):
       """Function to work with the maximum number of attemps."""
       
       try:
           #convert what user enters to a integer
            self.attempts = int(self.entry_attempts.get())

       except ValueError:
           #display if user enters something that is not a integer
            games.error_box("Input error",
                            "You must enter a whole positive number.")

       else:
           #run if user enters a integer

           if self.attempts <= 0:
               #ensure the user enters a positive integer
               games.warning_box("Warning",
                               "You must enter a whole number greater than 0.")

           elif  self.attempts > 5:
               #ensure attempts are not greater that five
               games.warning_box("Warning", "Attempts cannot be "\
                                 "greater than 5.")
           else:
                #call the other_GUI_widgets method
                self.other_GUI_widgets()

                
    def other_GUI_widgets(self):
        """Other GUI widgets."""

        #Define the number to guess
        self.the_number = random.randint(self.min_num, self.max_num)
        
        #Remove attempts widgets
        self.label_attempts.grid_remove()
        self.entry_attempts.grid_remove()
        self.button_attempts.grid_remove()

        #Display main game widgets
        self.entry_number = Entry(self)
        self.entry_number.grid(row = 4, column = 0, sticky = N, pady = 5)

        #Create a submit number for the guessed number
        self.button_number = Button(self, text = "Submit Guess",
                                    command = self.game_logic)
        self.button_number.grid(row = 5, column = 0, sticky = N, pady = 5)

        #Create a variable for text in result label
        self.label_text = ""
        self.label_number = Label(self, text = self.label_text)
        self.label_number.grid(row = 6, column = 0, sticky = S)

        #Create a label that displays the number of attempts user has
        self.show_attempts = Label(self, text = "Attempts: " + str(self.attempts))
        self.show_attempts.grid(row = 1, column = 0, sticky = N)
        

    def game_logic(self):
        """Main logic of the game"""
  
        try:
            #Declare the guessed number variable
            self.guessed_number = int(self.entry_number.get())

        except ValueError:
            #display error if user does not enter an integer
            games.error_box("Input error",
                            "You must enter a whole positive number.")

        else:
            #run if user enters a integer

            #decrease the number of attempts by one
            self.attempts -= 1
            #display it on the label
            self.show_attempts["text"] = "Attempts: " + str(self.attempts)

            #what to do if we ran out of attempts
            if self.attempts <= 0:
                self.show_attempts["text"] = "Out of attempts!!"

                #remove widgets to enter guessed number
                self.entry_number.grid_remove()
                self.button_number.grid_remove()
                self.label_number.grid_remove()

                #Tell the player about the loss
                self.end_label = Label(self, text = "The number was " + str(self.the_number))
                self.end_label.grid(row = 4, column = 0, sticky = N, pady = 5)

                self.end_label_2 = Label(self, text = "Good luck next time")
                self.end_label_2.grid(row = 5, column = 0, sticky = N, pady = 5)
                
                #Let the player decide to wheter play again or not
                self.again_button = Button(self, text = "Play Again",
                                           command = self.all_again)
                                          

                self.again_button.grid(row = 6, column = 0, sticky = N, pady = 5)

            #When user guess is greater than the random number
            if self.guessed_number > self.the_number:
                self.label_text = "lower..."
                self.label_number["text"] = self.label_text

            elif self.guessed_number < self.the_number:
                self.label_text = "HIGHER!!!"
                self.label_number["text"] = self.label_text

            elif self.guessed_number == self.the_number:
                #remove widgets to enter guessed number
                self.entry_number.grid_remove()
                self.button_number.grid_remove()
                self.label_number.grid_remove()

                self.end_label = Label(self, text = "You guessed it!!")
                self.end_label.grid(row = 4, column = 0, sticky = N, pady = 5)

                self.end_label_2 = Label(self, text = "The number was " + str(self.the_number))
                self.end_label_2.grid(row = 5, column = 0, sticky = N, pady = 5)

                #Let the player decide to wheter play again or not
                self.again_button = Button(self, text = "Play Again",
                                           command = self.all_again)

                self.again_button.grid(row = 6, column = 0, sticky = N, pady = 5)
                

    def all_again(self):
        """Run when player presses the 'Play Again' button."""
        self.remove_last_widgets()
        self.first_GUI_widgets()

    def remove_last_widgets(self):
        """Remove last widgets to restart all."""

        self.end_label.grid_remove()
        self.end_label_2.grid_remove()
        self.again_button.grid_remove()
        self.show_attempts.grid_remove()

games.make_GUI_work(Adivina,"Guess My Number GUI Edition")


The following are the games module (module I made up) functions I used:

def message_box(title, message = ""):
     """Displays an alert box."""
     import tkinter
     from tkinter import messagebox

     box = tkinter.Tk()
     box.withdraw()

     messagebox.showinfo(title, message)
     
def make_GUI_work(class_name,title):
     #Create a root window
     import tkinter
     root = tkinter.Tk()
     root.title(title)

    #instantiate the object
     game = class_name(root)

    #Have the GUI running in an infinite while loop until the user closes it
     root.mainloop()

def error_box(title, message = ""):
     """Displays an error box."""
     import tkinter
     from tkinter import messagebox

     box = tkinter.Tk()
     box.withdraw()

     messagebox.showerror(title,message)

def warning_box(title, message = ""):
     """Displays a warning message."""
     import tkinter
     from tkinter import messagebox

     box = tkinter.Tk()
     box.withdraw()

     messagebox.showwarning(title, message)

Yes, if you don’t want your user to install python, you need to give them an executable that works on their machine. I knew there were utilities for that but I never used them so I looked it up. This webpage gives an overview of different techniques for distribution, the one I was thinking of is option 3: https://python-compiler.com/post/how-to-distribute-python-program

Thank you very much @sfiquet.

Add a shebang & make the script executable. That’s all you need.