Originated in the United States and played widely in the 19th century, Twenty Questions is a spoken parlor game which encourages deductive reasoning and creativity. In that tutorial, you are going to learn how to recreate the Twenty Questions Game in Java.
You can also discover this tutorial in video on YouTube:
In the Twenty Questions game, one player is chosen to be the answerer. That person chooses an object or an animal but doesn’t reveal this to the others. The other player is the questioner. He asks questions which can be answered with a simple “Yes” or “No”. Sample questions could be : “Can it fly?” or “Does it sometimes live in water?”. If the questioner guesses the correct answer before asking for 20 Questions, he wins. Otherwise, if he asks 20 questions without a correct guess, the answerer has stumped the questioner and he won.
Recently, the Akinator game took the original concept of the Twenty Questions game and adapted it to Android and iOS smartphones with great success. Even better, the version of the Akinator game is a more complex one since the answer “Maybe” is allowed in addition to the simple “Yes” and “No”.
For our implementation, we will be satisfied with the original game with the simple answers “Yes” and “No” and we will not limit the number of questions to 20 to give more chances to the computer, which will play the role of the questioner, to find the object that the player will think of. For making our Twenty Questions Game more attractive, we will use a Swing UI.
Our game will be based on a tree containing questions with simple “Yes” and “No” answers. We will therefore be in the presence of a binary tree. Before starting the implementation, you can find out more about trees, their implementation and their traversal algorithms with examples in Java in the following article:
Representing the Tree
Our Tree will have nodes represented by the TreeNode class. Each node can be a Question or an Answer. We will use a Type enum for representing that. Each node have a String data and can have two children : a yes and a no TreeNode instances. Obviously, if the TreeNode is an answer, he will have no children.
The decision tree containing the questions will be loaded from a raw file. Each line representing a question will start with a “Q:” flag and each line representing an answer will start with a “A:” flag. So, we need to add two constants in our TreeNode and when we will set data of the TreeNode object, we will determine the type of the TreeNode according this flag.
It gives us the following code for the TreeNode class:
Loading the Decision Tree data
Most important part of the Twenty Questions Game is probably to have a great Decision Tree of questions and answers. It will make the difference and it will let our computer to find fastly the object thought by the user. To make our program more flexible and reusable, the data will be loaded from a raw text file. Like that, it would be easy to extend our Twenty Questions Game to let users load new Decision Tree data.
The data are stored in the raw file following Breadth First Search strategy. It is important to know that information for the loading method we will write in our Tree class. The Tree class has a root property of TreeNode type. We define a loadTree method taking in parameter the filename of a raw file containing Decision Tree data.
We open the file and we call a buildTree method with the root in parameter and the BufferedReader instance used to read the file line by line. When we read a line, we make the following actions :
- Set data in the current node
- If current node is a question :
– We create a yes TreeNode and a no TreeNode.
– We set these nodes as children of the currentNode.
– We call recursively buildTree method for building the yesNode subTree from the file.
– We call recursively buildTree method for building the noNode subTree from the file
It gives us the following implementation for the Tree class:
Note that our animals_questions.txt data file for the Decision Tree has the following form :
Q:Is it white?
Q:Is it a male?
Q:Is it yellow?
Q:Is it related to the cat family?
Q:Can it be all animals?
Q:Are you going to click yes for the last question?
Q:Are you going to answer “no” for this question?
Q:Can it do everything?
Creating the User Interface
Now, it’s time to create the User Interface of our Twenty Questions Game. Our UI will have a text area for displaying questions to the user and three buttons :
- Yes button for letting user to click yes and progressing in our Decision Tree
- Start button for starting a new game
- No button for letting user to click no and progressing in our Decision Tree
It will look like this:
You can note that our Decision Tree data are centered on animals. So, we ask to the user to think only to an animal.
We use the Swing API for building this User Interface. The text area is a JTextPane object and we use a BorderLayout instance to dispose the object in the content pane of the JFrame. The three buttons are represented via the JButton class.
It gives us the following buildUI method:
Interaction with the player
So, we have a Decision Tree implementation, some data and a User Interface. Now, we need to implement interaction with the player during the Twenty Questions game. We add an ActionListener instance to the three buttons for that. We define three methods :
- yes method to manage behavior of our Twenty Questions Game when the player clicks on Yes for a question
- no method to manage behavior of our Twenty Questions Game when the player clicks on No for a question
- start method to manage the starting of the game
We assemble our game in a TwentyQuestions class. We define a currentNode property to keep a pointer of our position in the Decision Tree. At the beginning of the Twenty Questions game, currentNode points to the root of the Decision Tree. This step is implemented in the restart method.
When the yes method is called, we know that the user has clicked on yes for the current question or answer displayed. So, we need to follow the yes path of our current node. If the new current node is a question, we display the data contained within it on the screen. Otherwise, we display a message to the user if he thought to the answer present in the current node. If the new current node was null, we know that we found the good answer and we can display a “I found :)” message to the user.
The logic is the same for the no method. The difference is when the current node obtained by following the no path of the current node is null, we need to display a “I lose :(“ message to the user.
Complete code of the Twenty Questions Game
It gives us the following complete code for the TwentyQuestions class:
We thought to an animal. An OSTRIGE for example :).
We click on Start and we answer to the question of the computer with “Yes” or “No”. At the end, the computer finds our animal and asks us the following question:
We click on “Yes”, and the we have the following display:
That’s all for that tutorial.
To discover more tutorials on Java and Android development, you can visit the SSaurel’s Channel on YouTube:
If you want to discover some books to learn Java programming, I advice you to read the following article with my selection of the Top 6 Best Books for Java programming: