Search Unity

Tic-Tac-Toe Tutorial (aka Noughts and Crosses) Q&A

Discussion in 'Community Learning & Teaching' started by Adam-Buckner, Apr 22, 2016.

  1. Paulusp

    Paulusp

    Joined:
    Sep 27, 2019
    Posts:
    3
    Hi, I've just completed this course in 2019.2.8f1 and it's all good. I found it an excellent course and learned a lot about the Unity UI so thanks very much. I now want to extend the game to include the list below and happy to share the final result if anyone's interested.
    // Sound on keypress - just the grid to complete now but I want to play a different sound depending on X or O turn, tips appreciated.
    // I would also like to change the gid text colour depending on the player to make potential winning lines more obvious
    // Add 1 or 2 player, 2 player is obviously done but for 1 player I want to add AI for the computer that still has a random edge to it so the AI doesn't always win. Already have some ideas on this so watch this space!
     
    Last edited: Oct 5, 2019
    nitrofurano likes this.
  2. nitrofurano

    nitrofurano

    Joined:
    Jun 7, 2019
    Posts:
    92
    i wasn't that “lucky”... please share Assets and ProjectSettings folders of it! ;)
     
  3. Paulusp

    Paulusp

    Joined:
    Sep 27, 2019
    Posts:
    3
    Hi Nitro, my effort after the project is here:
    https://bit.ly/31XmaaN
    Still working on the AI :)
    Assets & Project Settings attached. Hope that helps.
     

    Attached Files:

    nitrofurano likes this.
  4. nitrofurano

    nitrofurano

    Joined:
    Jun 7, 2019
    Posts:
    92
    excellent! thanks a lot, Paulusp!
     
  5. Paulusp

    Paulusp

    Joined:
    Sep 27, 2019
    Posts:
    3
    And complete package now with loading screen and AI if you're interested:

    Here is a link to the completed game: https://bit.ly/33vajRY
     

    Attached Files:

    Last edited: Oct 14, 2019
    nitrofurano likes this.
  6. NewbieOneKanobie

    NewbieOneKanobie

    Joined:
    Dec 17, 2019
    Posts:
    3
    In Tutorial Section 3, when I created the Grid Space Prefab, the Text child folder did not get created in the Project window.

    So I added the Text child folder in my Project window, and tried dragging the Text from the Hierarchy window to Prefab folder in the Project window. I got the message: "Cannot restructure Prefab instance Children of a Prefab instance cannot be deleted or moved, and components cannot be reordered. You can open the Prefab in Prefab Mode to restructure the Prefab Asset itself, or unpack the Prefab instance to remove the Prefab connection."

    In my Hierarchy window, when Grid Space is selected, the Inspector has a label Prefab, with 3 buttons to the right: Open, Select, and Overrides. I

    n my Hierarchy window, when Text is selected, the Inspector does not have a Prefab label and none of with 3 buttons to the right. Somehow, (can't duplicate how!) I also got this message: "Cannot restructure Prefab instance The Prefab asset is missing. You have to unpack the Prefab instance to be able to create a new Prefab."

    I'm using Unity 2018.4.14, which I believe I read is the correct installation to use.

    I have also downloaded the 2019.2.17f1.

    Please help.
    Thank you.
     
  7. Valjuin

    Valjuin

    Joined:
    May 22, 2019
    Posts:
    481
    See this thread:
    Copying button and child text from Hierachy to projects window.
     
    NewbieOneKanobie likes this.
  8. NewbieOneKanobie

    NewbieOneKanobie

    Joined:
    Dec 17, 2019
    Posts:
    3
  9. Hifsa

    Hifsa

    Joined:
    Nov 20, 2020
    Posts:
    1
    Hi,

    I am facing a problem in Tic Tac Toe that my playerside variable in GridSpace.cs is not updated while playing and on Grid Space “X” is always displaying it donot change to "O". Dont know how to fix it .Can anybody help me doing it.
    1.png 2.png

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. public class GridSpace : MonoBehaviour
    4. {
    5.     public Button button;
    6.     public Text buttonText;
    7.     public string playerSide;
    8.  
    9.     private GameController gameController;
    10.  
    11.     public void SetGameControllerReference(GameController controller)
    12.     {
    13.         gameController = controller;
    14.     }
    15.     public void SetSpace()
    16.     {
    17.         buttonText.text = playerSide;
    18.         button.interactable = false ;
    19.         gameController.EndTurn();
    20.     }
    21. }
    22.  
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5.  
    6. [System.Serializable]
    7. public class Player
    8. {
    9.     public Image panel;
    10.     public Text text;
    11.     public Button button;
    12. }
    13.  
    14. [System.Serializable]
    15. public class PlayerColor
    16. {
    17.     public Color panelColor;
    18.     public Color textColor;
    19. }
    20.  
    21.  
    22. public class GameController : MonoBehaviour
    23. {
    24.     public Text[] buttonList;
    25.     public GameObject gameOverPanel;
    26.     public Text gameOverText;
    27.     private string playerSide;
    28.     private int moveCount;
    29.     public GameObject restartButton;
    30.     public Player playerX;
    31.     public Player playerO;
    32.     public PlayerColor activePlayerColor;
    33.     public PlayerColor inactivePlayerColor;
    34.     public GameObject startInfo;
    35.  
    36.     void Awake()
    37.     {
    38.         SetGameControllerReferenceOnButton();
    39.         gameOverPanel.SetActive(false);
    40.         moveCount = 0;
    41.         restartButton.SetActive(false);
    42.     }
    43.  
    44.     void SetGameControllerReferenceOnButton()
    45.     {
    46.         for (int i = 0; i < buttonList.Length; i++)
    47.         {
    48.             buttonList [i].GetComponentInParent<GridSpace> ().SetGameControllerReference(this);
    49.         }
    50.     }
    51.  
    52.     public void SetStartingSide(string startingSide)
    53.     {
    54.         playerSide = startingSide;
    55.         if (playerSide == "X")
    56.         {
    57.             SetPlayerColors(playerX, playerO);
    58.         }
    59.         else
    60.         {
    61.             SetPlayerColors(playerO, playerX);
    62.         }
    63.  
    64.         StartGame();
    65.     }
    66.  
    67.     void StartGame()
    68.     {
    69.         SetBoardInteractable(true);
    70.         SetPlayerButtons(false);
    71.         startInfo.SetActive(false);
    72.  
    73.  
    74.     }
    75.  
    76.     public string GetPlayerSide()
    77.     {
    78.         return playerSide;
    79.     }
    80.  
    81.     public void EndTurn()
    82.     {
    83.         moveCount++;
    84.         if (buttonList[0].text == playerSide && buttonList[1].text == playerSide
    85.             && buttonList[2].text == playerSide)
    86.         {
    87.             GameOver(playerSide);
    88.  
    89.         }
    90.  
    91.  
    92.         else if (buttonList[3].text == playerSide && buttonList[4].text == playerSide
    93.             && buttonList[5].text == playerSide
    94.             )
    95.         {
    96.             GameOver(playerSide);
    97.         }
    98.  
    99.  
    100.         else if (buttonList[6].text == playerSide && buttonList[7].text == playerSide
    101.             && buttonList[8].text == playerSide
    102.             )
    103.         {
    104.             GameOver(playerSide);
    105.         }
    106.  
    107.  
    108.         else if (buttonList[0].text == playerSide && buttonList[3].text == playerSide
    109.             && buttonList[6].text == playerSide
    110.             )
    111.         {
    112.             GameOver(playerSide);
    113.         }
    114.  
    115.  
    116.         else if (buttonList[1].text == playerSide && buttonList[4].text == playerSide
    117.             && buttonList[7].text == playerSide
    118.             )
    119.         {
    120.             GameOver(playerSide);
    121.         }
    122.  
    123.  
    124.         else if (buttonList[2].text == playerSide && buttonList[5].text == playerSide
    125.             && buttonList[8].text == playerSide
    126.             )
    127.         {
    128.             GameOver(playerSide);
    129.         }
    130.  
    131.  
    132.         else if (buttonList[0].text == playerSide && buttonList[4].text == playerSide
    133.             && buttonList[8].text == playerSide
    134.             )
    135.         {
    136.             GameOver(playerSide);
    137.         }
    138.  
    139.  
    140.         else if (buttonList[2].text == playerSide && buttonList[4].text == playerSide
    141.             && buttonList[6].text == playerSide
    142.             )
    143.         {
    144.             GameOver(playerSide);
    145.         }
    146.  
    147.         else if (moveCount >= 9)
    148.         {
    149.             GameOver("DRAW!");
    150.         }
    151.         else
    152.         {
    153.             ChangeSides();
    154.         }
    155.  
    156.     }
    157.  
    158.     void ChangeSides()
    159.     {
    160.         //playerSide = (playerSide == "X") ? "O" : "X";
    161.         playerSide = (playerSide == "X") ? "O" : "X";
    162.         if (playerSide == "X")
    163.         {
    164.             SetPlayerColors(playerX, playerO);
    165.  
    166.         }
    167.         else if((playerSide == "O"))
    168.         {
    169.             SetPlayerColors(playerO, playerX);
    170.  
    171.         }
    172.     }
    173.  
    174.     void SetPlayerColors(Player newPlayer, Player oldPlayer)
    175.     {
    176.         newPlayer.panel.color = activePlayerColor.panelColor;
    177.         newPlayer.text.color = activePlayerColor.textColor;
    178.         oldPlayer.panel.color = inactivePlayerColor.panelColor;
    179.         oldPlayer.text.color = inactivePlayerColor.textColor;
    180.     }
    181.  
    182.     void GameOver(string winningPlayer)
    183.     {
    184.         SetBoardInteractable(false);
    185.         if (winningPlayer == "draw")
    186.         {
    187.             SetGameOverText("Draw!");
    188.             SetPlayerColorsInactive();
    189.             restartButton.SetActive(true);
    190.  
    191.  
    192.         }
    193.         else
    194.         {
    195.             SetGameOverText(winningPlayer + " Won!");
    196.             restartButton.SetActive(true);
    197.  
    198.         }
    199.  
    200.     }
    201.  
    202.     void SetGameOverText(string value)
    203.     {
    204.         gameOverPanel.SetActive(true);
    205.         gameOverText.text = value;
    206.     }
    207.  
    208.     public void RestartGame()
    209.     {
    210.         moveCount = 0;
    211.         gameOverPanel.SetActive(false);
    212.         restartButton.SetActive(false);
    213.         SetPlayerButtons(true);
    214.         SetPlayerColorsInactive();
    215.         startInfo.SetActive(true);
    216.  
    217.         for (int i = 0; i < buttonList.Length; i++)
    218.         {
    219.             buttonList [i].text = "";
    220.         }
    221.     }
    222.  
    223.     void SetBoardInteractable (bool toggle)
    224.     {
    225.         for(int i=0; i < buttonList.Length; i++)
    226.         {
    227.             buttonList[i].GetComponentInParent<Button>().interactable = toggle;
    228.         }
    229.     }
    230.  
    231.     void SetPlayerButtons(bool toggle)
    232.     {
    233.         playerX.button.interactable = toggle;
    234.         playerO.button.interactable = toggle;
    235.     }
    236.  
    237.     void SetPlayerColorsInactive()
    238.     {
    239.         playerX.panel.color = inactivePlayerColor.panelColor;
    240.         playerX.text.color = inactivePlayerColor.textColor;
    241.         playerO.panel.color = inactivePlayerColor.panelColor;
    242.         playerO.text.color = inactivePlayerColor.textColor;
    243.     }
    244. }
    245.  
     
  10. Valjuin

    Valjuin

    Joined:
    May 22, 2019
    Posts:
    481
    You’ve missed a couple of instructions at the end of Step 5. Controlling the game.

    Check your GridSpace script with final script shown at end of this section.
     
  11. muskan13

    muskan13

    Joined:
    Oct 22, 2021
    Posts:
    1
    I'm getting this error in Unity 2020.3.19f1 with the code i've written following this TicTacToe tutorial.
     

    Attached Files:

  12. Valjuin

    Valjuin

    Joined:
    May 22, 2019
    Posts:
    481
    “panel” in lines 125 and 127 refers to the public Image variable defined in line 8, which you have called “Panel” instead of “panel”. Capitalisation matters.
     
  13. Myst_Frosty

    Myst_Frosty

    Joined:
    Dec 13, 2021
    Posts:
    1
    Hi Adam I am just wondering whats the best build settings for the game because when it builds in 1920 x 1080 its quite small and when it its 4:3 it cuts off the top so I need help with that.

    Thnaks!
     
  14. PajamaJohn

    PajamaJohn

    Joined:
    Dec 2, 2017
    Posts:
    20
    It's common to set your Game View to 16:9 aspect and work from there.