Creating a Guess the Animal Game with .NET

Introduction

I have been writing about games quite often, and the major undertone of each of those games (I will provide links to a few games at the end of this article) have been that: as long as you can figure out the logic behind the game, you are more than halfway there; some games are different, though. With a few games, you need more than logic.

Today, I will cover a game which seems simple enough, but is actually pretty complicated! In this article, you will learn how to create a game which can think for itself, and the beauty is that there is no real Artificial Intelligence involved.

What Is a Guess the Animal Game?

A Guess the Animal game, or Guess the Object game, is a game that asks you questions. Based on your answers, either yes or no for example, the game knows what question to ask next. The game thinks for itself and records your answers as your play; this then assists in the game in knowing what to ask next.

Say, for example, the game asks you: “Is it an animal?” and you say: “yes,” the game will proceed in asking if the animal has a trunk. If you provide “no” as an answer, the game might ask another question to determine the correct animal. If you said “yes” to the previous question, the game would respond in saying that the animal is an Elephant.

This ability is beginner level A.I. and is known as a Binary Tree.

Binary Trees

A Binary Tree is a hierarchical data structure in which each node (parent) has children. The topmost node is called the root. Elements with no children are called leaves.

Our Project

Open Visual Studio and create a Console Application in either VB.NET or C#. You may name your project anything you desire. Once the project has been loaded, add the BinaryTree class.

C#

   class BinaryTree
   {
      BinaryTreeNode btnRoot;
      public BinaryTree(string strQuestion, string strYes,
         string strNo)
      {

         btnRoot = new BinaryTreeNode(strQuestion);

         btnRoot.StoreYes(new BinaryTreeNode(strYes));
         btnRoot.StoreNo(new BinaryTreeNode(strNo));

      }
      public void Play()
      {

         btnRoot.Guess();

      }
   }

VB.NET

   Private btnRoot As BinaryTreeNode
   Public Sub New(ByVal strQuestion As String, ByVal strYes As _
         String, ByVal strNo As String)

      btnRoot = New BinaryTreeNode(strQuestion)

      btnRoot.StoreYes(New BinaryTreeNode(strYes))
      btnRoot.StoreNo(New BinaryTreeNode(strNo))

   End Sub

   Public Sub Play()

      btnRoot.Guess()

   End Sub

The BinaryTree class instantiates a BinaryTreeNode object. You will create the BinaryTreeNode class next. Inside the BinaryTree class’ initialization, the seeding values for the game get stored. Without these values, there is no game and no intelligence. Let’s add the BinaryTreeNode class now.

C#

   [Serializable]
   class BinaryTreeNode
   {
      string strMess;

      BinaryTreeNode btnYes;
      BinaryTreeNode btnNo;

      public BinaryTreeNode(string strMessage)
      {

         strMess = strMessage;

         btnNo = null;
         btnYes = null;

      }
      public void Guess()
      {

         if (ValidQuestion())
         {

            Console.WriteLine(strMess);
            Console.Write("Enter 'Y' for YES and 'N' for NO: ");

            char chrInput = Answer();

            if (chrInput == 'y' || chrInput == 'Y')

               btnYes.Guess();

            else if (chrInput == 'n' || chrInput == 'N')

               btnNo.Guess();

         }

         else

            Query();
      }
      public void Query()
      {

         Console.WriteLine("Are you thinking of a(n) " + strMess +
            "?");

         Console.Write("Enter 'Y' for YES and 'N' for NO: ");

         char chrInput = Answer();

         if (chrInput == 'y' || chrInput == 'Y')

            Console.Write("Computer Wins!");

         else if (chrInput == 'n' || chrInput == 'N')

            PlayerWin();

      }
      private void PlayerWin()
      {

         Console.Write("You win! What Animal were you thinking
            of?");

         string strUserAnimal = Console.ReadLine();

         Console.Write("Please enter a question to
            distinguish a(n) "  + strMess + " from " +
            strUserAnimal + ": ");

         string strQuestion = Console.ReadLine();

         Console.Write("If you were thinking of a(n) " +
            strUserAnimal + ", what would have been the answer
            to that question?");

         char chrInput = Answer();

         if (chrInput == 'y' || chrInput == 'Y')
         {

            btnNo = new BinaryTreeNode(strMess);
            btnYes = new BinaryTreeNode(strUserAnimal);

         }

         else if (chrInput == 'n' || chrInput == 'N')
         {

            btnYes = new BinaryTreeNode(strMess);
            btnNo = new BinaryTreeNode(strUserAnimal);

         }

         Console.Write("Knowledge Increased");

         StoreMessage(strQuestion);

      }

      public bool ValidQuestion()
      {

         if (btnNo == null && btnYes == null)

            return false;

         else

           return true;
      }

      private char Answer()
      {
         char chrInput = ' ';

         while (chrInput != 'y' && chrInput != 'Y' &&
            chrInput != 'n' && chrInput != 'N')
         {

            chrInput = Console.ReadLine().ElementAt(0);
            chrInput = Char.ToLower(chrInput);

         }

         return chrInput;

      }

      public void StoreMessage(string strMessage)
      {

         strMess = strMessage;

      }
      public string GetMessage()
      {

         return strMess;

      }
      public void StoreNo(BinaryTreeNode btnNode)
      {

         btnNo = btnNode;

      }
      public BinaryTreeNode GetNo()
      {

         return btnNo;

      }
      public void StoreYes(BinaryTreeNode btnNode)
      {

         btnYes = btnNode;

      }
      public BinaryTreeNode GetYes()
      {

         return btnYes;

      }
   }

VB.NET

<Serializable>
Class BinaryTreeNode

   Private strMess As String

   Private btnYes As BinaryTreeNode

   Private btnNo As BinaryTreeNode

   Public Sub New(ByVal strMessage As String)

      strMess = strMessage

      btnNo = Nothing
      btnYes = Nothing

   End Sub

   Public Sub Guess()

      If ValidQuestion() Then

         Console.WriteLine(strMess)

         Console.Write("Enter 'Y' for YES and 'N' for NO: ")

         Dim chrInput As Char = Answer()

         If chrInput = "y"c OrElse chrInput = "Y"c Then

            btnYes.Guess()

         ElseIf chrInput = "n"c OrElse chrInput = "N"c Then

            btnNo.Guess()

         End If

      Else

         Query()

      End If

   End Sub

   Public Sub Query()

      Console.WriteLine("Are you thinking of a(n) " & strMess _
         & "?")

      Console.Write("Enter 'Y' for YES and 'N' for NO: ")

      Dim chrInput As Char = Answer()

      If chrInput = "y"c OrElse chrInput = "Y"c Then

         Console.Write("Computer Wins!")

      ElseIf chrInput = "n"c OrElse chrInput = "N"c Then

         PlayerWin()

      End If

   End Sub

   Private Sub PlayerWin()

      Console.Write("You win! What Animal were you thinking of?")

      Dim strUserAnimal As String = Console.ReadLine()

      Console.Write("Please enter a question to distinguish a(n) " _
         & strMess & " from " & strUserAnimal & ": ")

      Dim strQuestion As String = Console.ReadLine()

      Console.Write("If you were thinking of a(n) " & _
         strUserAnimal & ", what would have been the answer _
         to that question?")

      Dim chrInput As Char = Answer()

      If chrInput = "y"c OrElse chrInput = "Y"c Then

         btnNo = New BinaryTreeNode(strMess)
         btnYes = New BinaryTreeNode(strUserAnimal)

      ElseIf chrInput = "n"c OrElse chrInput = "N"c Then

         btnYes = New BinaryTreeNode(strMess)
         btnNo = New BinaryTreeNode(strUserAnimal)

      End If

      Console.Write("Knowledge Increased")

      StoreMessage(strQuestion)

   End Sub

   Public Function ValidQuestion() As Boolean

      If btnNo Is Nothing AndAlso btnYes Is Nothing Then _
         Return False Else Return True

   End Function

   Private Function Answer() As Char

      Dim chrInput As Char = " "c

      While chrInput <> "y"c AndAlso chrInput <> "Y"c _
         AndAlso chrInput <> "n"c AndAlso chrInput <> "N"c

         chrInput = Console.ReadLine().ElementAt(0)
         chrInput = Char.ToLower(chrInput)

      End While

      Return chrInput

   End Function

   Public Sub StoreMessage(ByVal strMessage As String)

      strMess = strMessage

   End Sub

   Public Function GetMessage() As String

      Return strMess

   End Function

   Public Sub StoreNo(ByVal btnNode As BinaryTreeNode)

      btnNo = btnNode

   End Sub

   Public Function GetNo() As BinaryTreeNode

      Return btnNo

   End Function

   Public Sub StoreYes(ByVal btnNode As BinaryTreeNode)

      btnYes = btnNode

   End Sub

   Public Function GetYes() As BinaryTreeNode

      Return btnYes

   End Function

End Class

The btnYes and btnNo fields are BinaryTreeNode objects themselves, making them recursive by using them. The Guess Sub procedure allows you to enter your responses and calls the Query sub procedure. The Query sub interrogates the user and calls the PlayerWin sub, where most of the action happens. In the IF statement, after a question was asked, the game’s logic determines what was answered and how to proceed further with the game. Finally, add the Main sub’s code inside the Program file or Module file.

C#

   class Program
   {
      static BinaryTree btAnimals;
      static void Main(string[] args)
      {

         NewGame();

         Console.WriteLine("Let's Start!");

         btAnimals.Play();


      }

      static void NewGame()
      {

         Console.WriteLine("Initializing.");

         Console.WriteLine("Enter a question about an Animal: ");
         string strQuestion = Console.ReadLine();

         Console.Write("Enter a guess for Yes: ");
         string strYesSeed = Console.ReadLine();

         Console.Write("Enter a guess for No: ");
         string strNoSeed = Console.ReadLine();

         btAnimals = new BinaryTree(strQuestion, strYesSeed,
            strNoSeed);

      }
   }

VB.NET

Module Module1

   Public btAnimals As BinaryTree

   Public Sub Main()

      NewGame()

      Console.WriteLine("Let's Start!")

      btAnimals.Play()

   End Sub

   Private Sub NewGame()

      Console.WriteLine("Initializing.")

      Console.WriteLine("Enter a question about an Animal: ")
      Dim strQuestion As String = Console.ReadLine()

      Console.Write("Enter a guess for Yes: ")
      Dim strYesSeed As String = Console.ReadLine()

      Console.Write("Enter a guess for No: ")
      Dim strNoSeed As String = Console.ReadLine()

      btAnimals = New BinaryTree(strQuestion, strYesSeed, _
         strNoSeed)

   End Sub

End Module

When you run the program, you will get a screen with the output shown in Figure 1.

Running
Figure 1: Running

Previous Games

As promised, here are links to a few games I have written about in the past:

Conclusion

Some games are more complicated than others; even I am amazed how complicated this little project has become. Hopefully, I can think of another game idea for you soon. Until then, play nice!

Hannes DuPreez
Hannes DuPreez
Ockert J. du Preez is a passionate coder and always willing to learn. He has written hundreds of developer articles over the years detailing his programming quests and adventures. He has written the following books: Visual Studio 2019 In-Depth (BpB Publications) JavaScript for Gurus (BpB Publications) He was the Technical Editor for Professional C++, 5th Edition (Wiley) He was a Microsoft Most Valuable Professional for .NET (2008–2017).

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read