Do you want to learn how to use Python GUI to make an entertaining and challenging game? Look no further than the Hi-Lo game! This game is a great practice for beginning and intermediate Python programmers because it demands players predict a randomly generated integer inside a given range. In this post, we’ll walk you through the process of using the Python and Delphi ecosystem to construct the Hi-Lo game. After reading this article, you can wow your friends and advance your Python programming abilities. So, let’s get started!
Table of Contents
What Are the Rules of a Hi-Lo Game?
The Hi-Lo app for Android is a fast-paced game that challenges your mind on the go. The app presents you with a random number as the starting number, and your goal is to guess whether the next number will be higher or lower. If you guess correctly, the app reveals the next number, and you continue to the next round. However, if you guess incorrectly, the game ends, and your score is based on the number of correct guesses you made in a row. Your aim is to achieve the highest score possible by making correct guesses for as long as you can.
Why Use Delphi For Python to Create this App?
Delphi for Python is a useful set of tools for Python developers looking to create such a game with efficient and visually appealing Graphical User Interfaces (GUIs). These tools, such as Delphi FMX provides powerful tools and cross-platform support, enabling developers to build flexible and sophisticated GUIs that operate across multiple platforms without writing separate code for each. Delphi’s UI design tools, including the Delphi4PythonExporter tool, can help accelerate development and ensure functional and aesthetically appealing GUIs. The open-source Delphi Community Edition and PythonFMXBuilder are also available for developers who prefer to work with open-source tools. Delphi for Python can help streamline the development process and ensure smooth and efficient operation across all platforms.
How to Create an Amazing Hi-Lo App?
What Are the Prerequisites for this App?
To create the memory game desktop app, you must install Delphi and the FireMonkey GUI framework on your device. Additionally, you will need a text editor or IDE that supports Python, such as PyScripter and the Delphi4PythonExporter tool.
If you don’t have these tools installed, we recommend checking out the article “Powerful Python GUI Project Setup” to help you get started. Once you have all the required tools, you can proceed with the tutorial to create your memory game desktop app using Delphi
You can grab the code for this tutorial from our GitHub repository using the following link: https://github.com/Embarcadero/PythonBlogExamples/tree/main/HiLo_Game
How To Create Basic Forms For this App in Delphi CE?
We will start by opening the Delphi CE application and creating a blank project. To do this, navigate to File > New > Multi-Device Application > Blank Application > Ok
. In this tutorial, we have named our project HiLoGame
.
If you are not familiar with the various sections of the Delphi IDE, we recommend referring to our free eBook bundle, which covers the Delphi Python EcoSystem and all Python GUI offerings.
To start, let’s give our form a name. Right-click on the form and select QuickEdit. Here, we will name our form MainForm
with the caption MainMenu
.
Next, we need to resize our form which will help it fit in our Android devices. So, go to the object inspector and search ClientHeight
and ClientWidth
in the properties tab. We will set them to 500
and 360
, respectively.
Moreover, we will also rename the source file of our MainMenu
form to MainMenu.pas
to make it easier to keep track of.
As you may have guessed, this form will serve as the main screen of our app where the users will be greeted and can start the game. Now what we will need to do is enhance the user experience by adding components to our app. First, let’s start by adding a title to our app. To do this, navigate to the standard palette and locate the TLabel
component. Next, drag and drop this component onto the form.
Next, let’s modify the text style. To do this we will use the TextSettings
property. So, navigate to the Object Inspector and search for TextSettings
. Select Font beneath it and click “...
” to see options for modifying the label’s font, size, and style based on your preferences. Here we have set our font family as Segoe UI with a font size of 48.
Next, we will center the text using the HorzAlign
and VertAlign
properties in TextSettings
. So select the label component and select the adjust the properties to Center
.
Additionally, we must follow intuitive naming convention for our app components so that they can be tracked more easily. Therefore, we will name our TLabel
component “Title
” with the “Memory Game
” text.
Next, let’s add another label that will display the rules for our app.
Next, we need a way to navigate to our game form where we will be playing our game. To do this, we will be using a TButton
component. So go to the Palette
and add a button using the TButton
component.
Now, let’s make this button a bit more appealing. Let’s change the font size to Segoe UI with a font size of 18 and change the size of the button. Additionally, we will name the button Start
and display the text as “START
”. Here is what our form looks like:
Finally, let’s adjust the form’s background color by navigating to the Object Inspector
and selecting the form’s fill
property.
Here is what our form looks like:
Finally, we can explore the power of styles using DelphiFMX. To do this you will need to download the free ebook bundle which comes with a variety of styles. Download your FMX styles zip file and extract it into your desktop. Next, select a style that you want to use. You can find other styles online, such as delphistyles.com. For now we will be using Light.style
available in the bundle.
Head to Palette
and TStyleBook
object to your form
Next, double click on the object. This will open up your Style Designer. Now press the click on the open button.
Navigate to the .style
file of your choosing and click on exit. Now select the form and head over to the Object Inspector. Here we will search for the StyleBook property. Select the drop down menu and select StyleBook1.
This will apply the style to your form. Here is what our final MainForm looks like:
Now that we are done with the main menu, let’s create a new form that will display our game. So right-click on HiLoGame.exe
and select Add New > Multi-Device Form
.
This will create a new form that will serve the main game. Here we have named the form as GameForm
and its corresponding source file as Game.pas
. We also used QuickEdit to change the form Caption to HiLo Game
and changed its dimension to match our MainForm
.
Now, let’s start by changing the background of our form using the fill
property.
Next, we will add labels and buttons to our form. We will first add three labels to our form. The first label, which we will name Number
will help show the number that is to be predicted. The next label is the ScoreLabel
which will display the current score of the user. For now, we will set the default caption of Number as “-” and the ScoreLabel
as “Score :0
”. Finally, we add a third label StatusLabel
right below the ScoreLabel
to help us display some information. We will set its default caption as empty.
Finally, we will add 3 buttons to our app. The HighButton
and LowButton
will help the user predict whether the next number will be high or low, respectively. The AgainButton
will help the user restart the game.
Additionally, we will set the AgainButton
as disabled by selecting the button and setting its Enabled
property as False
.
Finally, apply the style of your choosing to your form. Here is what our final GameForm
looks like:
Now that our forms are complete, the final step is to add functionality to each button. So go to each form and double-click each button to add an OnClick
method to that button. The procedure will be created in the .pas
file corresponding to the .fmx
form. This allows you to add unique functionality to each button when clicked.
After creating the OnClick
method for each button, add at least one comment (//
) to each procedure. This is recommended to preserve the method when you export the form as a Python file, as we do not export the run-time implementation using the Delphi4PythonExporter.
Can I Export This GUI to Python Code?
Now that our forms are ready, we can save our project as a Python script by selecting Tools > Export To Python > Export Current Entire Project
.
Here rename your project to HiLoGame
, and select the main form as MainForm
. Finally, select the directory of your choosing and click Export:
Delphi will generate 5 files, 3 Python scripts named MainMenu.py
, Game.py
, and HiLoGame.py
. The HiLoGame.py
is used to launch our Delphi app, while Game.py
, MainMenu.py
python files contain the classes for the individual forms. Along with the Python file for each form, Delphi also generates a .pyfmx
script of the same name as each form that contains the visual information of that form. Here are the contents of each file.
HiLoGame.py
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
from delphifmx import * from MainMenu import MainForm def main(): Application.Initialize() Application.Title = 'HiLoGame' Application.MainForm = MainForm(Application) Application.MainForm.Show() Application.Run() Application.MainForm.Destroy() if __name__ == '__main__': main() |
MainMenu.py
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import os from delphifmx import * class MainForm(Form): def __init__(self, owner): self.Title = None self.Rules = None self.Start = None self.LoadProps(os.path.join(os.path.dirname(os.path.abspath(__file__)), "MainMenu.pyfmx")) def StartClick(self, Sender): pass |
Game.py
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
import os from delphifmx import * class GameForm(Form): def __init__(self, owner): self.ScoreLabel = None self.Number = None self.HighButton = None self.LowButton = None self.AgainButton = None self.StatusLabel = None self.LoadProps(os.path.join(os.path.dirname(os.path.abspath(__file__)), "Game.pyfmx")) def HighButtonClick(self, Sender): pass def LowButtonClick(self, Sender): pass def AgainButtonClick(self, Sender): pass |
How Can I Add Functionality to This Amazing GUI?
Now that our forms are ready, we can add functionality to our game. Let’s start with our MainForm
. So open up MainMenu.py
and navigate to the StartClick
function.
The MainForm
only serves the purpose of launching the game. The StartClick
will enable us to launch our GameForm
. So start by importing the GameForm
, from Game.py
:
1 2 |
from Game import GameForm |
Next, in the StartClick
function, create a new variable named Game
, and initialize it with a new instance of the GameForm
. Now, we will simply use the Show()
method to display our GameForm
. Here is what the StartClick
function looks like:
1 2 3 4 |
def StartClick(self, Sender): Game = GameForm(self) Game.Show() |
Finally, lets display the rules of the game by defining them in the Rules
label. This is done using the .Text
property of the label component:
1 2 3 4 5 |
self.Rules.Text = """Rules: nThe rules for the game are simple. The game will generate a random number between 1 and 10. Your job will be to predict whether the next number will be higher or lower than the current number. """ |
Here are the contents of our final MainMenu.py
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
import os from delphifmx import * from Game import GameForm class MainForm(Form): def __init__(self, owner): self.Title = None self.Rules = None self.Start = None self.LoadProps( os.path.join(os.path.dirname(os.path.abspath(__file__)), "MainMenu.pyfmx") ) self.Rules.Text = """Rules: nThe rules for the game are simple. The game will generate a random number between 1 and 10. Your job will be to predict whether the next number will be higher or lower than the current number. """ def StartClick(self, Sender): Game = GameForm(self) Game.Show() |
Now, lets open up Game.py
and start coding our game.
Let’s start by navigating to our __init__
function. The first thing we will need to do is create a variable named self.Score
and initialize it to a value of 0
. This will help keep track of our score.
1 2 |
self.Score = 0 |
Next, we import the random
library in our Game.py
file.
1 2 |
import random |
Now, navigate to the __init__
function and generate a random integer between 0 and 10. Next, we display this value to our Number
label using the .Text
property. Here is what our __init__
function looks like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
def __init__(self, owner): self.ScoreLabel = None self.Number = None self.HighButton = None self.LowButton = None self.AgainButton = None self.StatusLabel = None self.LoadProps(os.path.join(os.path.dirname(os.path.abspath(__file__)), "Game.pyfmx")) # Additional initializations self.Score = 0 self.GuessNumber = random.randint(0, 10) # Generate a random number between 0 and 10 self.Number.Text = str(self.GuessNumber) |
Next, let’s define a function called __UpdateGame
that takes in a single string parameter compare
to compare the GuessNumber
to the selected button. The compare parameter will either be a >
or a <
string that will help compare the current GuessNumber
. We start by clearing the StatusLabel
of any text and then storing the current GuessNumber
in a new variable called prev
. We will use prev
to check whether the guess is correct or not.
Next, we then generate a new random number and store it in GuessNumber
and, finally, display the next number into our Number
label regardless of the users’ prediction.
1 2 3 4 5 6 |
def __UpdateGame(self, compare): self.StatusLabel.Text = "" # Clear the status label each time button clicked prev = self.GuessNumber # Store the guess number self.GuessNumber = random.randint(0, 10) # Generate a new random number within a range self.Number.Text = str(self.GuessNumber) |
Now that we have our guess number, we start comparing. We will use an if
statement to check which button the user has pressed based on the compare
parameter. If compare
equals “>
“, then the user presses the HighButton
. We then check if the last number is greater than the new number. If this is true, we update the Status
label to show that the user was correct. We then increment the Score
, and display it as a string into our ScoreLabel
. Similarly, if the user presses the LowButton
, the compare parameter will be defined as “<
“, which we would then use to compare whether the user predicts the next number to be less than or equal to the current number.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
def __UpdateGame(self, compare): self.StatusLabel.Text = "" # Clear the status label each time button clicked prev = self.GuessNumber # Store the guess number self.GuessNumber = random.randint(0, 10) # Generate a new random number within a range self.Number.Text = str(self.GuessNumber) if compare==">" and prev > self.GuessNumber: # If the player guessed lower and the new number is actually lower self.StatusLabel.Text = "That's right" self.Score +=1 # Increment the score self.ScoreLabel.Text = "Score:" + str(self.Score) elif compare=="<" and prev <= self.GuessNumber: # If the player guessed higher and the new number is actually higher self.StatusLabel.Text = "That's right" self.Score +=1 # Increment the score self.ScoreLabel.Text = "Score:" + str(self.Score) |
Finally, if the user guesses the number wrong, then we simply set the StatusLabel
to “GAME OVER
“. We then disable the HighButton
, and LowButton
buttons and enable the AgainButton
. Here is what our final __UpdateGame
function looks like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
def __UpdateGame(self, compare): self.StatusLabel.Text = "" # Clear the status label each time button clicked prev = self.GuessNumber # Store the guess number self.GuessNumber = random.randint(0, 10) # Generate a new random number within a range self.Number.Text = str(self.GuessNumber) if compare==">" and prev > self.GuessNumber: # If the player guessed lower and the new number is actually lower self.StatusLabel.Text = "That's right" self.Score +=1 # Increment the score self.ScoreLabel.Text = "Score:" + str(self.Score) elif compare=="<" and prev <= self.GuessNumber: # If the player guessed higher and the new number is actually higher self.StatusLabel.Text = "That's right" self.Score +=1 # Increment the score self.ScoreLabel.Text = "Score:" + str(self.Score) else: # If the player guessed wrong self.StatusLabel.Text = "GAME OVER" self.LowButton.Enabled = False # Disable the low button self.HighButton.Enabled = False # Disable the high button self.AgainButton.Enabled = True # Enable the again button |
Now that our __UpdateFunction
is ready, all we need to do is call it in the HighButtonClick
and LowButtonClick
functions. If the HighButton
button is pressed, we call the HighButtonClick
function with the __UpdateFunction
with the “<
” parameter. Similarly, if the LowButtion
is pressed, we call the LowButtonClick
function with the “>
” parameter in the LowButtonClick
function. Here is what our button functions look like:
1 2 3 4 5 6 |
def HighButtonClick(self, Sender): self.__UpdateGame("<") # If the high button is clicked, update the game def LowButtonClick(self, Sender): self.__UpdateGame(">") # If the low button is clicked, update the game |
We are now ready to implement our final AgainButtonClick
function.
The purpose of the AgainButtonClick
function is to reset the game. This button will only be enabled when the game ends, which we have defined in our __UpdateFunction
. Therefore, to implement this function, we all need to generate a new random number, reset all the buttons, and reset all the labels to their default values. Here is what our AgainButtonClick
function looks like:
1 2 3 4 5 6 7 8 9 10 |
def AgainButtonClick(self, Sender): self.Score = 0 # Reset the score to 0 self.ScoreLabel.Text = "Score:" + str(self.Score) # Update the score label self.GuessNumber = random.randint(0, 10) # Generate a new random number between 0 and 10 self.Number.Text = str(self.GuessNumber) self.LowButton.Enabled = True # Enable the low button self.HighButton.Enabled = True # Enable the high button self.AgainButton.Enabled = False # disable the again button self.StatusLabel.Text = "" # Clear the status label |
Here is what our final Game.py
file looks like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
import os from delphifmx import * import random class GameForm(Form): def __init__(self, owner): self.ScoreLabel = None self.Number = None self.HighButton = None self.LowButton = None self.AgainButton = None self.StatusLabel = None self.LoadProps(os.path.join(os.path.dirname(os.path.abspath(__file__)), "Game.pyfmx")) # Additional initializations self.Score = 0 self.GuessNumber = random.randint(0, 10) # Generate a random number between 0 and 10 self.Number.Text = str(self.GuessNumber) def __UpdateGame(self, compare): self.StatusLabel.Text = "" # Clear the status label each time button clicked prev = self.GuessNumber # Store the guess number self.GuessNumber = random.randint(0, 10) # Generate a new random number within a range self.Number.Text = str(self.GuessNumber) if compare==">" and prev > self.GuessNumber: # If the player guessed lower and the new number is actually lower self.StatusLabel.Text = "That's right" self.Score +=1 # Increment the score self.ScoreLabel.Text = "Score:" + str(self.Score) elif compare=="<" and prev <= self.GuessNumber: # If the player guessed higher and the new number is actually higher self.StatusLabel.Text = "That's right" self.Score +=1 # Increment the score self.ScoreLabel.Text = "Score:" + str(self.Score) else: # If the player guessed wrong self.StatusLabel.Text = "GAME OVER" self.LowButton.Enabled = False # Disable the low button self.HighButton.Enabled = False # Disable the high button self.AgainButton.Enabled = True # Enable the again button def HighButtonClick(self, Sender): self.__UpdateGame("<") # If the high button is clicked, update the game def LowButtonClick(self, Sender): self.__UpdateGame(">") # If the low button is clicked, update the game def AgainButtonClick(self, Sender): self.Score = 0 # Reset the score to 0 self.ScoreLabel.Text = "Score:" + str(self.Score) # Update the score label self.GuessNumber = random.randint(0, 10) # Generate a new random number between 0 and 10 self.Number.Text = str(self.GuessNumber) self.LowButton.Enabled = True # Enable the low button self.HighButton.Enabled = True # Enable the high button self.AgainButton.Enabled = False # disable the again button self.StatusLabel.Text = "" # Clear the status label |
How Does the Desktop App look like?
Now, we can run our app by executing HiLoGame.py
. Here is what MainForm
looks like:
We can start the game by clicking the START
button. Here is what our GameForm
looks like:
Can I Create an Android App From this Code?
Now that our HiLoGame
is running let’s convert this into an Android application.
But before we can create our app, we need to make important changes to the code to allow us to run our project on Android. Let’s create a new file named HiLoGame_Android.py
and paste the contents of HiLoGame.py
.
Next, open up the HiLoGame_Android.py
file and start making some changes. Firstly, because Delphi initialed Android applications automatically, we don’t need to initialize it or set a title manually. The Application.MainForm
doesn’t need to be initialized either but just needs a variable. Finally, like the MainForm
initialization, we don’t need to launch or destroy the program as Android handles both tasks. Here are the contents of our final HiLoGame_Android.py
:
1 2 3 4 5 6 7 8 9 10 |
from delphifmx import * from MainMenu import MainForm def main(): Application.MainForm = MainForm(Application) Application.MainForm.Show() if __name__ == '__main__': main() |
Now open up FMXBuilder and click on Project > New project
on the toolbar. Enter the name of the project that you want to build here. Here we define our project as HiLoGame
.
Next, add your Python and .pyfmx
files by right-clicking on the App and selecting Add file. We won’t add HiLoGame.py
, but instead will be adding the HiLoGame_Android.py
. HiLoGame.py
will only be used to run our desktop application.
Now, right-click on HiLoGame_Android.py
file and set it to the main file.
Now that everything is ready, we must create the .apk
file for the app using the Build Project
button.
When the .apk
is fully generated, you will be prompted with a “Build process done
” message in the Messages
box. You can then check out your generated file in the pathtoPythonFMXBuilderGUIexeFolderappsHiLoGamebin folder
.
Now, you must copy the .apk
file into your phone’s storage. Next, install this file by accessing it on your Android device. Once your app is installed, you can use it like any other app on your phone.
Does the App Run as Expected on an Android Device?
Here is what our app looks like:
When we press the start button, we are taken to the main game screen:
Upon making a correct guess, the user is prompted and their score is incremented:
Upon an incorrect guess for the next number, the user is prompted and the play again button is enabled while the other two buttons are disabled:
Now, we can reset the game and play again:
Are You Ready to Create Other Android Apps with Delphi For Python?
With the help of a robust ecosystem of development tools and libraries, cross-platform compatibility, and access to the FireMonkey GUI framework, DelphiFMX is a strong and adaptable solution for Python developers. DelphiFMX is the perfect option for developers wishing to create cross-platform games that may appeal to a wider audience, including Android users, thanks to its aesthetically pleasing and highly functional user interfaces.
We invite Python developers interested in producing aesthetically appealing and highly functioning games to learn more about DelphiFMX and utilize its features and tools. You can speed up the app creation process and produce apps that work flawlessly on several platforms with DelphiFMX.
So, what are you waiting for? Start building your next app with DelphiFMX today.
What Are Some FAQs Related to this Article?
Can I create apps for mobile devices using DelphiFMX?
DelphiFMX provides cross-platform support, allowing developers to build apps for various mobile devices, including Android and iOS.
What is the best approach to building games with Python and DelphiFMX?
The best approach to building games with Python and DelphiFMX is to start with a clear design and choose appropriate game mechanics. Then, utilize the features of DelphiFMX to create a visually appealing and highly functional user interface. Finally, optimize the game’s performance and test it thoroughly before release.
What resources are available to help me learn how to use DelphiFMX for game development?
Many resources are available to help you learn how to use DelphiFMX for game development. The Embarcadero website provides documentation, tutorials, and sample projects to get you started. Additionally, there are online communities and forums where developers can ask questions and share ideas about game development with DelphiFMX. Lastly, Delphi’s ebook would help you understand the entire Delphi ecosystem much better, allowing you to kickstart your career in Python GUI!
Is Python the only language I can use with DelphiFMX for app development?
No, DelphiFMX supports several programming languages, including C++ and Object Pascal. However, Python developers may find it beneficial to use DelphiFMX. It provides an efficient way to build graphical user interfaces (GUIs) and supports cross-platform development, making it easier to create apps that work across multiple devices and operating systems.