简体   繁体   中英

Check a value in a String matches an element in an array C# unity,

I am trying to check if the value in string word from one class matches any element in the array stringAnswers in another and if it does i want the score to increment by 1. For some reason the code im using below increments the score by 1,2 and 3 depending on the word that is displayed any help would be awesome cheers.

public class Player : MonoBehaviour 
{
    public int Score = 0;

    private string[] StringAns = {"steve", "grace", "lilly"};

    // Use this for initialization
    void Start () 
    {
    }

    // Update is called once per frame
    void Update ()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            RaycastHit hit;

            if (Physics.Raycast(transform.position, transform.forward, out hit))
            {
                if (hit.transform.GetComponent<ButtonNo>()  != null)
                {
                    foreach (string stringAnsers in StringAns)
                    {

                        if (stringAnsers.Equals(FindObjectOfType<GameController>().word))
                        {
                            Debug.Log(" Button has been looked at");
                            FindObjectOfType<GameController>().RandText();
                        }
                        else
                        {
                            Debug.Log(" Button has been looked at");
                            FindObjectOfType<GameController>().RandText();

                            Score++;
                        }
                    }
                }
            }

            if (Physics.Raycast(transform.position, transform.forward, out hit))
            {
                if (hit.transform.GetComponent<ButtonYes>() != null)
                {
                    foreach (string stringAnsers in StringAns)
                    {
                        if (stringAnsers.Equals( FindObjectOfType<GameController>().word) )
                        {
                            Debug.Log(" Button has been looked at");
                            FindObjectOfType<GameController>().RandText();

                            Score++;
                        }
                        else
                        {
                            FindObjectOfType<GameController>().RandText();
                        }
                    }
                }
            }
        }
    }
}

GameController

public class GameController : MonoBehaviour 
{
    public TextMesh InfoText;
    public TextMesh WallText;
    public string word;
    public Player player;

    public string[] Strings = { "stev", "lilly", "grace" };

    // Use this for initialization
    void Start()
    {
        RandText();
    }

    // Update is called once per frame
    void Update()
    {

        InfoText.text = "Is this Spelling Correct ?\n Score: " + player.Score;
    }

    public void RandText()
    {
         word = Strings[Random.Range(0, Strings.Length)];

        WallText = GameObject.Find("WallText").GetComponent<TextMesh>();
        WallText.text = word;
    }
}

In general you should call FindObjectOfType<GameController>() only once eg in Start

private GameController _gameController;

private void Start()
{
    _gameController= FindObjectOfType<GameController>();
}

and than reuse that _gameController reference everywhere instead of FindObjectOfType<GameController>() .

The same for WallText in GameController :

public TextMesh WallText;

private void Start()
{
    WallText = GameObject.Find("WallText").GetComponent<TextMesh>();
    RandText();
}

public void RandText()
{
    word = Strings[Random.Range(0, Strings.Length)];
    WallText.text = word;
}

better would even be you already reference those in the Inspector in Unity via drag&drop than you don't have to use Find at all


Than to your problem: You are setting a new value for word in every iteration for the loop

foreach (string stringAnsers in StringAns)
{
    if (stringAnsers.Equals(FindObjectOfType<GameController>().word))
    {
        Debug.Log("Button has been looked at");
        FindObjectOfType<GameController>().RandText();
    }
    else
    {
        Debug.Log("Button has been looked at");
        FindObjectOfType<GameController>().RandText();

        Score++;
    }
}

So it might happen that the word doesn't match so you call Score++; but at the same time you do FindObjectOfType<GameController>().RandText(); everytime so a new random word is generated/selected for each iteration.

So in the next iteration of the foreach loop you check against a new random word which might or might not match the next answer string in the list.


Instead you should only generate a new random word after the loop is done eg like

foreach (string stringAnsers in StringAns)
{
    if (stringAnsers.Equals(FindObjectOfType<GameController>().word))
    {
        Debug.Log("Button has been looked at-> matched");
        Score++;
    }
    else
    {
        Debug.Log("Button has been looked at -> didn't match");
    }
}

FindObjectOfType<GameController>().RandText();

Note this would still add 1-3 points depending how many of the given stringAnswer match the word. So you should add a break; after increasing Score once if you want only 1 added.


Using Linq you could also do this in only one line instead a loop:

if(StringAns.Any(answer => string.Equals(answer, _gameController.word)))) Score++;

_gameController.RandText();

or for the No button

if(!StringAns.Any(answer => string.Equals(answer, _gameController.word)))) Score++;

I guess the problem is that you are generating a new random word inside the foreach loop that check the word itself. Also, i suggest you not to use a foreach loop, because items inside the array could be more that 3 items, so it could slow the method. I suggest you to use contains instead, like so:

if (StringAns.Contains(FindObjectOfType<GameController>().word))
{
      Debug.Log(" Button has been looked at");
      Score++;
}
else
      Debug.Log(" Button has *not* been looked at");

FindObjectOfType<GameController>().RandText();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM