Interview Question: Coding Challenge
- santosh nalla
- Dec 13, 2019
- 4 min read
Today i attended an interview, in which i was asked to make a simple game in unity.
The game goes like, there will be a grid(ex: 4 * 4) with random numbers in each box. For the first 5 seconds of the game, those random numbers are shown to the user. After five seconds those numbers are hidden. Now, you have to identify same pairs of numbers by clicking on the grid cells before the timer runs out.
Hmm, Let me explain you with images.
For the first 5 seconds,

After 5 seconds,

Now if you can see in the first pic, Grid(2,1)th element is equal to Grid(3,1)th element that is 2. So if i click on those both i get a point added to my score. See the below picture,

Hmm, this was quite challenging to solve. I am sharing this logic with you below.
Before we code, we need to set up few things.
1. Add a panel (called GamePlay Panel) and add Grid Layout Group to that panel.
2. Create a button prefabs and add image as a child to that Button. Disable it first.
I have segregated the code in 2 scripts: BUTTONSCRIPT AND GAMEMANAGER.
BUTTONSCRIPT:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class ButtonScript : MonoBehaviour, IPointerClickHandler
{
public void OnPointerClick(PointerEventData eventData) //This event is called when you click on the buton
{
FindObjectOfType<GameManager>().getStringOfButton(transform.GetComponentInChildren<Text>().text, transform.gameObject); //This fetches you the button text and the button game object on which you clicked
}
}
GAMEMANAGER:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class GameManager : MonoBehaviour
{
[SerializeField] Sprite buttonImageGrayed; // Image to hide the numbers for Buttons we spawned in grid
[SerializeField] GameObject cell; // A complete cell with number and image as child
// [SerializeField] GameObject cell_image;
[Header("PANNELS")]
[SerializeField] GameObject gamePlayPannel; // GamePlay panel where we spawn our Grids
[SerializeField] GameObject startingPannel; // To prevent user form clicking when Grid shows numbers for the first 5 seconds
[SerializeField] GameObject gameOverPannel; // Game Over Pannel
[Header("UI ELEMENTS")]
[SerializeField] Text scoreText; // Text to hold score
[SerializeField] Text timerTextt; // Text to nite down Timer
[SerializeField] Text gameOverText; // Text to display on GameOver
[SerializeField] Text bestTime; // Text to score Best time by whioh you could complete the game
[Header("GRID PROPERTIES")]
[SerializeField] int columns;
[SerializeField] int rows;
[Header("PRIVATE VARIABLES")]
int score; // To store score in our game
List<GameObject> Button_temp; // Every second time you click a button, first clicked button and second clicked button are stored in this list with size 2.
List<GameObject> image_covers; // Stores all the images, which are child of the cell prefab which we created. So for the first 5 seconds these are set to false active so that user can see the number on the grid
string s1, s2; // 2 continuous clicks(text) are stores here
int clickCount; // Click count. To track if its first or second click
int totalNumberOfCells; // Calculate total number of cells by multiplying rows and columns
float timer = 0f; // Increases with time.deltaTime in floats
int time = 25; // Game timer
[Header("RANDOM NUMBERS LIST")]
[SerializeField] List<int> random_Numbers_List; // Random numbers which are to be displayed in the grid are written here. Remember always write them in pairs(Ex: 1,1,2,2,3,3,4,4 etc)
// Start is called before the first frame update
void Start()
{
Time.timeScale = 1;
startingPannel.SetActive(true); // This makes sure user doesn't click on grid when the grid is being shown
gameOverPannel.SetActive(false); //Disable game Over Pannel
Button_temp = new List<GameObject>(); //Store two two button clicks into list
image_covers = new List<GameObject>(); //Masking all the buttons with image after 5 seconds
clickCount = 0; //increases, the moment you click active grid button
totalNumberOfCells = rows * columns;
for (int i = 0; i < totalNumberOfCells; i++) // This fo rloop is spawning grids with random numbers and also storing the image of each button into an array so that to make it active after 5 seconds
{
GameObject temp_Button = Instantiate(cell);
image_covers.Add(temp_Button.transform.GetChild(1).gameObject); // Adding images to an array as they are child of button prefab
temp_Button.transform.SetParent(gamePlayPannel.transform);
//Logic to spawn random numbers in PAIRS, so that no number is left out
int indexNum = Random.Range(0, random_Numbers_List.Count);
temp_Button.GetComponentInChildren<Text>().text = random_Numbers_List[indexNum].ToString();
random_Numbers_List.RemoveAt(indexNum);
}
Invoke("activateGame", 5.0f); // Mask grid by activating images stored in array after 5 seconds
}
void Update()
{
scoreText.text = score.ToString(); //Updating score text
timerTextt.text = "Time: " + time;
TimerFuncntion(); //Runnign timer function for every frame.
}
//This function compares the 2 button clicks we performed.
public void getStringOfButton(string s, GameObject buttonGameObject)
{
clickCount++;
if (clickCount == 1)
{
s1 = s;
Button_temp.Add(buttonGameObject);
}
if (clickCount == 2)
{
s2 = s;
Button_temp.Add(buttonGameObject);
if (Button_temp[0] == Button_temp[1])
{
clickCount = 0;
s1 = null;
s2 = null;
for (int i = 0; i < 2; i++)
{
Button_temp.Clear();
}
}
else
{
clickCount = 0;
if (s1.Equals(s2))
{
score++;
s1 = null;
s2 = null;
for (int i = 0; i < 2; i++)
{
Button_temp[i].GetComponent<Image>().sprite = buttonImageGrayed;
Destroy(Button_temp[i].GetComponent<ButtonScript>());
}
for (int i = 0; i < 2; i++)
{
Button_temp.Clear();
}
}
else
{
s1 = null;
s2 = null;
for (int i = 0; i < 2; i++)
{
Button_temp.Clear();
}
}
}
}
}
//Masking the grid and allowing the user to play the game
public void activateGame()
{
startingPannel.SetActive(false);
foreach (var item in image_covers)
{
item.SetActive(true);
Debug.Log(item.gameObject);
}
}
//Timer function to maintain Timer and check score/clock
void TimerFuncntion()
{
bestTime.text = "Best Time: " + (25 - PlayerPrefs.GetInt("BestTimeT")).ToString();
if (score == ((rows * columns) / 2))
{
Time.timeScale = 0;
if(time < PlayerPrefs.GetInt("BestTimeT",25))
{
PlayerPrefs.SetInt("BestTimeT", time);
bestTime.text = "Best Time: " + (25 - PlayerPrefs.GetInt("BestTimeT")).ToString();
}
gameOverPannel.SetActive(true);
gameOverText.text = "YOU WON";
}
timer = timer + Time.deltaTime;
if (timer > 1.0f)
{
time = time - 1;
timer = 0;
}
if(time < 1)
{
if (score != ((rows * columns) / 2))
{
Time.timeScale = 0;
gameOverPannel.SetActive(true);
gameOverText.text = "YOU LOST";
bestTime.text = null;
}
if(score == ((rows * columns) / 2))
{
Time.timeScale = 0;
gameOverPannel.SetActive(true);
gameOverText.text = "YOU WON";
}
}
}
//Resets the game
public void onRestartButtonClicked()
{
SceneManager.LoadScene("SampleScene");
}
}
I have commented every line of code. just drop me an email if you are having any doubts.
Thank you and Happy coding :)
Comments