Search Unity

Very basic math quiz with Unity 4.6 uGui

Discussion in 'Scripting' started by bundibundi, Oct 1, 2014.

  1. bundibundi

    bundibundi

    Joined:
    Sep 30, 2014
    Posts:
    1
    Hi all. I'm an absolute beginner to both Unity and scripting. After watching a few basic tutorials I have made a very simple math quiz using Unity 4.6 in order to teach myself the basics of Unity and C#.

    Id love it if someone could give me some ideas as to how to improve my code, it seems a bit bloated at the moment and it is admittedly very basic. I'm not really interested in adding any new features, I'd rather just focus on writing good code.

    Ive included the code and some screenshots of it running. Any other newbies can feel free to use it for themselves!

    (Number at top is a countdown timer and number at bottom is the total score (10 for correct answer + whatever is left on the timer)

    screen1.png screen2.png

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using System.Collections;
    4.  
    5. public class GameControl : MonoBehaviour {
    6.  
    7.     public static int value1;
    8.     public static int value2;
    9.     public static int value3;
    10.     public static int value4;
    11.     public static int value5;
    12.     public static int value6;
    13.     public static int value7;
    14.     public static int random1;
    15.     public static int random2;
    16.     public static bool correct;
    17.     public Text question;                    //used to attach Unity text component to script
    18.     public Text timer;
    19.     public Text score;
    20.     public Button button1;                    //used to attach Unity button component to script
    21.     public Button button2;
    22.     public Button button3;
    23.     public Button button4;
    24.     public static float timeLeft = 10f;        //deltaTime must be a float
    25.     public static float scoreCount;
    26.     public static float scores;
    27.     public void Update()
    28.         {
    29.             if (correct == false)
    30.                 {
    31.                     timeLeft -= Time.deltaTime;
    32.                     timer.text = timeLeft.ToString("f0");        //f0 reduces float to 0 decimal positions
    33.                 }
    34.      
    35.             if(timeLeft < 0f)
    36.                 {
    37.                     correct = true;
    38.                 }
    39.             scores = scoreCount;
    40.             score.text = scores.ToString("f0");
    41.         }
    42.  
    43.  
    44.  
    45.      
    46.     void Start () {
    47.         value1 = Random.Range(0,101);            //give random values for question and answers
    48.         value2 = Random.Range(0,101);
    49.         value3 = value1 + value2;
    50.         value4 = Random.Range(0,201);
    51.         value5 = Random.Range(0,201);
    52.         value6 = Random.Range(0,201);
    53.         value7 = Random.Range(0,201);
    54.         random1 = Random.Range(0,3);            //randomise +/-/x
    55.         random2 = Random.Range(0,4);            //randomise location of correct answer
    56.         correct = false;                        //used for timer stop/start, scoring system, avoid double click get more points
    57.         timeLeft = 10f;
    58.      
    59.      
    60.         question.text = value1.ToString() + " + " + value2.ToString() + " =";
    61.         button1.GetComponentInChildren<Text>().text = value4.ToString();    //used to display random values in the text
    62.         button2.GetComponentInChildren<Text>().text = value5.ToString();     //attached to a button
    63.         button3.GetComponentInChildren<Text>().text = value6.ToString();
    64.         button4.GetComponentInChildren<Text>().text = value7.ToString();
    65.      
    66.      
    67.  
    68.         if (random1 == 0)                                                                //randomise +/-/x
    69.             {
    70.                 value1 = Random.Range(0,15);
    71.                 value2 = Random.Range(0,15);
    72.                 value3 = value1 * value2;
    73.                 question.text = value1.ToString() + " x " + value2.ToString() + " =";
    74.             }
    75.         else if (random1 == 1)
    76.             {
    77.                 value1 = Random.Range(0,101);
    78.                 value2 = Random.Range(0,101);
    79.          
    80.             if (value1 < value2)                                        //make sure value x is larger than y so dont create negative answer
    81.                 {
    82.                     value1 += value2;
    83.                 }
    84.             value3 = value1 - value2;
    85.             question.text = value1.ToString() + " - " + value2.ToString() + " =";
    86.             }
    87.  
    88.         switch (random2)                                                                //randomise which button answer attached
    89.         {
    90.         case 0:
    91.         button1.GetComponentInChildren<Text>().text = value3.ToString();
    92.         break;
    93.         case 1:
    94.         button2.GetComponentInChildren<Text>().text = value3.ToString();
    95.         break;
    96.         case 2:
    97.         button3.GetComponentInChildren<Text>().text = value3.ToString();
    98.         break;
    99.         case 3:
    100.         button4.GetComponentInChildren<Text>().text = value3.ToString();
    101.         break;
    102.         }
    103.  
    104.         if (value4 == value3)                                                    //make sure no 'incorrect' button has same value as answer
    105.             {
    106.                 value4 += 11;
    107.             }
    108.         else if (value5 == value3)
    109.             {
    110.                 value5 += 11;
    111.             }
    112.         else if (value6 == value3)
    113.             {
    114.             value6 += 11;
    115.             }
    116.         else if (value7 == value3)
    117.             {
    118.             value7 += 11;
    119.             }
    120.         }
    121.      
    122.     public void Restart()                                                //restart level
    123.         {
    124.             Application.LoadLevel(Application.loadedLevel);
    125.         }
    126.  
    127.     public void CheckAnswer ()                 //each method attached to the buttons 'OnClick()' script in inspector
    128.         {
    129.                 if (button1.GetComponentInChildren<Text>().text == value3.ToString() && correct == false)
    130.                     {
    131.                         correct = true;
    132.                         question.text = "yay";
    133.                         scoreCount = scores + timeLeft + 10f;
    134.                     }
    135.                 else
    136.                     {
    137.                         question.text = "boo";
    138.                     }
    139.         }
    140.     public void CheckAnswer1 ()
    141.         {
    142.                 if (button2.GetComponentInChildren<Text>().text == value3.ToString() && correct == false)
    143.                 {
    144.                     correct = true;
    145.                     question.text = "yay";
    146.                     scoreCount = scores + timeLeft + 10f;
    147.                 }
    148.             else
    149.                 {
    150.                     question.text = "boo";
    151.                 }
    152.         }
    153.     public void CheckAnswer2 ()
    154.         {
    155.             if (button3.GetComponentInChildren<Text>().text == value3.ToString() && correct == false)
    156.                 {
    157.                     correct = true;
    158.                     question.text = "yay";
    159.                     scoreCount = scores + timeLeft + 10f;
    160.                 }
    161.             else
    162.                 {
    163.                     question.text = "boo";
    164.                 }
    165.         }
    166.     public void CheckAnswer3 ()
    167.         {
    168.             if (button4.GetComponentInChildren<Text>().text == value3.ToString() && correct == false)
    169.                 {
    170.                     correct = true;
    171.                     question.text = "yay";
    172.                     scoreCount = scores + timeLeft + 10f;
    173.                 }
    174.             else
    175.                 {
    176.                     question.text = "boo";
    177.                 }
    178.         }  
    179. }
     
  2. Cpt Chuckles

    Cpt Chuckles

    Joined:
    Dec 31, 2012
    Posts:
    86
    looks like your whole game is being handled in one single script? if it works, i don't see a huge problem for a game of this size. not right now, anyway. but having said that, i think it would benefit your coding habits greatly to study object-oriented programming practices, and the principle of encapsulation, and re-structure this entire game so that each button is its own object and the game functions as an interaction between objects who know as little as possible about each other. being able to do that will prepare you for greater things

    and i just want to say that i greatly admire your humble start, most newcomers get on here wanting to make the next greatest FPSMMORPG but your project is excellent as a starting point to experiment in programming and understand how things work :D
     
  3. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,079
    Nice job. :)

    This:
    Code (csharp):
    1.  
    2. if(correct == false)
    3.  
    can also be written like this:
    Code (csharp):
    1.  
    2. if(!correct)
    3.  
    Your way is probably more clear, I just wanted to show another option.

    I would probably eventually change value1...7 to different names and use arrays. I do things the way you did them too when first figuring out how to make things work, but then sometimes change them. For instance, value1 and value2 might be done something like this:

    Code (csharp):
    1.  
    2. float[] questionTerms = new questionTerms[2];
    3.  
    Then can be accessed like this:

    Code (csharp):
    1.  
    2. questionTerms[0] = Random.Range(0,101);
    3. questionTerms[1] = Random.Range(0,101);
    4.  
    Or better yet, loop through them one at a time so you are free to add more questionTerms like this:
    Code (csharp):
    1.  
    2. for(int i = 0; i < questionTerms.Length; i++)
    3.     questionTerms[i] = Random.Range(0,101);
    4.  

    Your value3 then maybe can become "correctAnswer." In this case there's only one so I wouldn't make an array, but still would change the name. So instead of this:

    Code (csharp):
    1.  
    2. value3 = value1 + value2;
    3.  
    You have this:

    Code (csharp):
    1.  
    2. correctAnswer = questionTerms[0] + questionTerms[1];
    3.  
    This would let you easily add more terms to the question. You could then loop through them all to get the sum like this:
    Code (csharp):
    1.  
    2. correctAnswer = 0;
    3. for(int i = 0; i<questionTerms.Length; i++)
    4. {
    5. correctAnswer += questionTerms[i];
    6. }
    7.  
    See how that works? It just goes through all the questionTerms and keeps adding until it runs out of questionTerms.

    You could then change value4....7 to another array like this:
    Code (csharp):
    1.  
    2. float[] buttonAnswerValue = new float[4];
    3.  
    Which would let the if statements where you check to make sure more than one button doesn't show the correct value here:

    Code (csharp):
    1.  
    2. if (value4 == value3)                                                    //make sure no 'incorrect' button has same value as answer
    3.             {
    4.                 value4 += 11;
    5.             }
    6.         else if (value5 == value3)
    7.             {
    8.                 value5 += 11;
    9.             }
    10.         else if (value6 == value3)
    11.             {
    12.             value6 += 11;
    13.             }
    14.         else if (value7 == value3)
    15.             {
    16.             value7 += 11;
    17.             }
    18.         }
    19.  
    To something much simpler. You can just cycle through their replacement buttonAnswerValue[] array, checking each one individually to see if the value is the same as the answer and adding your 11 to it like this. Note the if statement that avoids overwriting the button that is supposed to have the correct answer in it:

    Code (csharp):
    1.  
    2. int theButtonIndexWithTheCorrectAnswer = random2;
    3. for(int i = 0; i<buttonAnswerValue.Length; i++)
    4. {
    5.     if(i != theButtonIndexWithTheCorrectAnswer && buttonAnswerValue[i] == correctAnswer)
    6.     {
    7.         buttonAnswerValue[i] += 11;
    8.     }
    9. }
    10.  
    Do you understand that logic part in the middle? It's saying "if this button is not theButtonIndexWithTheCorrectAnswer and (&&) the buttonAnswerValue is the correctAnswer, add 11 to the buttonAnswerValue" so you don't get more than one button with the correct answer. This replaces that big "if/else if" block which would require more code added if you ever wanted to add more buttons.

    I haven't run this code, just writing this in wordpad and copying it in, so any bugs there will be an exercise for you.

    Another thing is all the GetComponentInChildren<Text> calls. In your application it's perfectly fine because it's not trying to do it a million times per second, but it may be useful to point out that you can save those references and use them later. For instance, in Start() you did this:
    Code (csharp):
    1.  
    2. button1.GetComponentInChildren<Text>().text = value4.ToString();    //used to display random values in the text
    3.  
    Then that is basically repeated a bunch of times. Another way is to create a reference to that button1 text something like below. (I'm not entirely sure if that .text is a GUIText, you will probably need to double check this next one to make sure I have it correct. Even if it's wrong, it shows the basic idea of creating a reference and using that instead of repeatedly calling GetComponentInChildren.):

    Code (csharp):
    1.  
    2.  
    3. //
    4. //Outside of the functions do something like this:
    5. private GUIText button1Text;
    6. //
    7.  
    8. //Then inside Start() do something like this:
    9. button1Text = button1.GetComponentInChildren<Text>().text;
    10.  
    11. //Now any time you set the text value it would be a call something like this:
    12. button1Text.text = value4.ToString();  
    13. //Or better yet, use the new arrays discussed earlier
    14.  

    Like Cpt Chuckles said, at some point it might be good to think about having each button use its own script. It's probably overkill for this application (I'd have done it pretty much the same way you did), but it could be a good learning exercise at some point.
     
  4. Pra_Castle

    Pra_Castle

    Joined:
    Sep 7, 2015
    Posts:
    1
    thats good, but I don't know the component must I place in unity.
    can I know your component, so I can learn from your project, thanks.