I did a job application to a Unity developer position and i was given a coding challenge which was implementing a Rock Paper Scissors game or a variation of it. I have implemented the game using Unity and C# and the feed back I got was my implementation being "too mathematical" and "lacking object oriented principles". So i am a bit confused so i thought i should ask four your feedback.
I have actually implemented Rock Paper Scissors Lizard Spock from The Big Bang Theory show and had a simple logic having elements in a list and calculating who wins based on these indexes in the list. So it works like this:
If the absolute difference between Player and Opponent element index is even, then element with smaller index wins and if it is odd, the element with bigger index wins.
I have two scripts for achieving this, one is attached to all elements(Rock,Paper etc.) in the game which just handle IO operations and send the selected input to GameController
like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ElementController : MonoBehaviour
{
public GameObject Controller;
private Renderer rend;
private GameController GameController;
private Color previousColor;
private List<string> Elements = new List<string>() { "Spock", "Lizard", "Rock", "Paper", "Scissor" };
void Start()
{
rend = gameObject.GetComponent<Renderer>();
previousColor = rend.material.color;
GameController = Controller.GetComponent<GameController>();
}
void OnMouseEnter()
{
rend.material.color = Color.yellow;
previousColor = Color.yellow;
}
void OnMouseExit()
{
rend.material.color = Color.white;
previousColor = Color.white;
}
void OnMouseDown()
{
//Mouse can be clicked only if Coroutine is not running
if (!GameController.isRunning)
{
// Passing the selected element by user to GameController
GameController.Game(Elements.IndexOf(gameObject.name));
rend.material.color = Color.red;
}
}
}
And then the GameController
runs a coroutine and gives the result of each round like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class GameController : MonoBehaviour
{
#region UIElements
public Button Restart;
public Text RoundResult;
public Text PlayerScoreText;
private int PlayerScore = 0;
public Text OpponentScoreText;
private int OpponentScore = 0;
#endregion UIElements
[HideInInspector]
public bool isRunning = false;
public GameObject Opponent;
public float flipDuration;
//Indexes are required to calculate winner of each round
private readonly List<string> Elements = new List<string>() { "Spock", "Lizard", "Rock", "Paper", "Scissor" };
private int OppMove;
void Start()
{
Restart.onClick.AddListener(RestartGame);
}
public void Game(int PlayerElement)
{
StartCoroutine(RoundResultCoroutine(PlayerElement));
}
//Coroutine running every round
IEnumerator RoundResultCoroutine(int PlayerElement)
{
//Since Range with integers are not maximally inclusive
OppMove = Random.Range(0, 5);
//Activate child Opponent played
Opponent.transform.GetChild(OppMove).transform.gameObject.SetActive(true);
float t = 0;
//isRunning is used in order to prevent user inteference during each round is held.
isRunning = true;
while (t < flipDuration)
{
t += Time.deltaTime;
Opponent.transform.eulerAngles = Vector3.Lerp(new Vector3(0, 0, 0), new Vector3(0, 180, 0), t / flipDuration);
yield return null;
}
/*
* Player has equal probability of winning or losing since there are odd number of elements.
* From the rules we can infer with the indexing of Spock = 0, Lizard = 1, Rock = 2, Paper = 3, Scissor = 4
* if the absolute difference between Player and opponent element is even, then element with smaller index wins
* if it is odd, the element with bigger index wins. Because as we can see from the graph and imagine it as a directed graph
* an element always wins against the next element and loses against the previous element. Also it wins against next element of its directed
* neighbor. This mathematical solution is implemented in order to eliminate keeping track of all possible Rules between two chosen elements.
* Also this aproach would work with any N = #elements given that N is odd. N should be odd to have same probability for each element in order to
* have a fair game.
*/
if (PlayerElement == OppMove)
{
RoundResult.text = "It is a tie";
RoundResult.GetComponent<Text>().color = Color.white;
}
//Having even absolute difference
else if (Mathf.Abs(OppMove - PlayerElement) % 2 == 0)
{
if (PlayerElement > OppMove)
{
UpdateScore("Opponent", PlayerElement, OppMove);
}
else
{
UpdateScore("Player", PlayerElement, OppMove);
}
}
//Having odd absolute difference
else
{
if (PlayerElement > OppMove)
{
UpdateScore("Player", PlayerElement, OppMove);
}
else
{
UpdateScore("Opponent", PlayerElement, OppMove);
}
}
yield return new WaitForSeconds(flipDuration * 2);
RoundResult.text = " ";
t = 0;
while (t < flipDuration)
{
t += Time.deltaTime;
Opponent.transform.eulerAngles = Vector3.Lerp(new Vector3(0, 180, 0), new Vector3(0, 0, 0), t / flipDuration);
yield return null;
}
Opponent.transform.GetChild(OppMove).transform.gameObject.SetActive(false);
isRunning = false;
}
// Method used for updating score and modifying round result text
private void UpdateScore(string winner, int PlayerMove, int OpponentMove)
{
if (winner == "Player")
{
PlayerScore++;
PlayerScoreText.text = PlayerScore.ToString();
RoundResult.text = Elements[PlayerMove] + " wins against " + Elements[OpponentMove];
RoundResult.GetComponent<Text>().color = Color.green;
}
else if (winner == "Opponent")
{
OpponentScore++;
OpponentScoreText.text = OpponentScore.ToString();
RoundResult.text = Elements[PlayerMove] + " loses against " + Elements[OpponentMove];
RoundResult.GetComponent<Text>().color = Color.red;
}
}
private void RestartGame()
{
if (!isRunning)
{
PlayerScore = 0;
PlayerScoreText.text = PlayerScore.ToString();
OpponentScore = 0;
OpponentScoreText.text = OpponentScore.ToString();
}
}
}
In general, i wanted to ask you how would i complete this task with better oo handling. Should i have used Singleton
for game controller or instead of this mathematical solution have a static list of rules and check from that list.
Too mathematical
? \$\endgroup\$