如何获得一个随机的int值到一个被称为多次的预制件(不重复相同的值)?

时间:2019-02-08 07:29:56

标签: c# unity3d random duplicates

我创建了一个包含文本(a * b =)和输入字段(以获取用户答案)的预制件。并且我使用c#脚本将此预制称为5次。我已经将a&b分配给random.range(1,10),所以我可以获得5个不同的和。但就我而言,我所有5个总和的值都相同。

我尝试了foreach循环,它使随机数超出了给定范围,单击检查按钮,它甚至以红色显示了正确答案(不正确)。 这是我第一次通过脚本多次调用预制件。所以需要一些帮助来解决它。

TestModeQuestionUI.cs

using Helper.Keyboard;
using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

public class TestModeQuestionUI : MonoBehaviour
{
internal RectTransform refRectTransform;
[SerializeField]
TextMeshProUGUI valueA; // valueB;
[SerializeField]
MyInputField AnswerInputField;
internal int id;
internal Action<TestModeQuestionUI> onSubmitValueOfInputFieldAction;
internal Action<TestModeQuestionUI> onSelectInputFieldAction;

Color defaultColorOfAnswer = new Color(0.19f, 0.19f, 0.19f, 1f);
Color correctColorOfAnswer = new Color(0f, 0.44f, 0f, 1f);
Color incorrectColorOfAnswer = new Color(1f, 0f, 0f, 1f);

public static TestModeQuestionUI curSelectedAnswerInputField;

//-------------------------------------------------------------------------

void Awake()
{
    refRectTransform = GetComponent<RectTransform>();
}


private void SetNextAnswerInputFieldAsSelected(TestModeQuestionUI 
curSelectedAnswerInputField)
{
    throw new NotImplementedException();
}

public void SetQuestionLabel(string v)
{
    valueA.text = v;        
}

public void ActiveAnswerInputField(bool active)
{
    AnswerInputField.gameObject.SetActive(active);
}

public int GetAnswerInputField()
{
    int result = -1;
    int.TryParse(AnswerInputField.textComponent.text, out result);
    return result;
}

public void SetAnswerInputField(string msg)
{
    AnswerInputField.textComponent.text = msg;
}

public void SelectAnswerInputField()
{
    DeSelectCurSelectedAnswerInputField();
    AnswerInputField.ActivateInputField();
    curSelectedAnswerInputField = this;   
}

public static void DeSelectCurSelectedAnswerInputField()
{
    if (curSelectedAnswerInputField != null)
    {            
       curSelectedAnswerInputField.AnswerInputField.DeactivateInputField();   
    }
       curSelectedAnswerInputField = null;
}

public void SetResultOfAnswerInputField(int result)
{
    switch (result)
    {
        //==================================
        // Default Color For Answer Has Not Checked
        case 0:
            AnswerInputField.textComponent.color = defaultColorOfAnswer;
            break;

        //==================================
        // Correct Color For Answer Has Checked Correct
        case 1:
            AnswerInputField.textComponent.color = correctColorOfAnswer;
            break;

        //==================================
        // Incorrect Color For Answer Has Checked Incorrect
        case 2:
            AnswerInputField.textComponent.color = incorrectColorOfAnswer;
            break;
    }
}

public void OnSelectInputField()
{
    //Debug.Log("On Select : " + id);
    if (curSelectedAnswerInputField != this)
        DeSelectCurSelectedAnswerInputField();
    curSelectedAnswerInputField = this;

    if (onSelectInputFieldAction != null)
        onSelectInputFieldAction(this);
}

public void OnSubmitValueOfInputField()
{
    if (onSubmitValueOfInputFieldAction != null)
        onSubmitValueOfInputFieldAction(this);
}

}

TestModeManager.cs

 public class TestModeManager : MonoBehaviour
 {
 public static TestModeManager instance;
 [SerializeField]
 GameObject refTestModeQuestionExampleParent;
 [SerializeField]
 GameObject refTestModeQuestionExamplePrefab;
 [SerializeField]
 GameObject checkButton;
 [SerializeField]
 GameObject nextButton;

 private int a, b;
 List<TestModeQuestionUI> testModeQuestionExampleList;


 void Start()
 {
    CreateUI();
 }

 void Update()
 {        
 #if UNITY_EDITOR
    if (Input.GetKeyDown(KeyCode.KeypadEnter))
    {    SetNextAnswerInputFieldAsSelected(TestModeQuestionUI.curSelectedAnswerInputField);          



    }
 #endif

    if (Input.GetKeyDown(KeyCode.Escape))
    {
        if (Keyboard.instance.gameObject.activeInHierarchy)
            Keyboard.Close();
        else
            Application.Quit();
    }
 }


 void CreateUI()
 {
    GameObject _GO;
    TestModeQuestionUI _TestModeQuestionUIRefrence;

    if (testModeQuestionExampleList == null)
        testModeQuestionExampleList = new List<TestModeQuestionUI>();

   //  a = UnityEngine.Random.Range(1, 20);
  //   b = UnityEngine.Random.Range(1, 10);

    for (int id = 1; id <= 5; id++)
    {
        _GO = Instantiate(refTestModeQuestionExamplePrefab, 
 refTestModeQuestionExampleParent.transform);
        _GO.name = "TestModeQuestion Example " + id;
        _TestModeQuestionUIRefrence = _GO.GetComponent<TestModeQuestionUI> 
 ();
        _TestModeQuestionUIRefrence.id = id;
        _TestModeQuestionUIRefrence.onSubmitValueOfInputFieldAction = 
  SetNextAnswerInputFieldAsSelected;
        testModeQuestionExampleList.Add(_TestModeQuestionUIRefrence);

  }

    ResetUI();               
  }

  void ResetUI()
  {
    // Reset Multiplication Examples
    a = UnityEngine.Random.Range(1, 10);
    b = UnityEngine.Random.Range(1, 10);
    foreach (TestModeQuestionUI _TestModeQuestionUIRefrence in 
  testModeQuestionExampleList)
    {
        _TestModeQuestionUIRefrence.SetQuestionLabel(a + " " + b + "  = ");

   //loop to get 5 different sums
   var questions = GameObject.FindGameObjectsWithTag("question");
   foreach (var question in questions)
   {
         // a++;
         //b++;
  }

   }
  //==================================
    // Set First Answer Input Field As Selected
    SetNextAnswerInputFieldAsSelected();

  }
  void SetNextAnswerInputFieldAsSelected(TestModeQuestionUI _ 
  TestModeQuestionUIRefrence = null)
  {
    if (_TestModeQuestionUIRefrence == null)
    {
        //==================================
        // Get First Input Field And Set As Selected
        _TestModeQuestionUIRefrence = GettestModeQuestionExampleList(1);
        if (_TestModeQuestionUIRefrence != null)
            _TestModeQuestionUIRefrence.SelectAnswerInputField();
    }
    else
    {
        //==================================
        // Get Next Input Field And Set As Selected
        _TestModeQuestionUIRefrence = 
  GettestModeQuestionExampleList(_TestModeQuestionUIRefrence.id + 1);
        if (_TestModeQuestionUIRefrence != null)
            _TestModeQuestionUIRefrence.SelectAnswerInputField();
        else
        {
            Keyboard.Close();
            StartCoroutine(highlighCheckButton());
        }
    }
  }

  TestModeQuestionUI GettestModeQuestionExampleList(int id)
  {
    foreach (TestModeQuestionUI _TestModeQuestionUIRefrence in 
  testModeQuestionExampleList)
    {
        if (_TestModeQuestionUIRefrence.id == id)
        {
            return _TestModeQuestionUIRefrence;
        }
    }
    return null;
  }
  IEnumerator EnableKeyboardAfterSometime(float time)
  {
    yield return new WaitForSeconds(time);
    Keyboard.Open();
  }

IEnumerator highlighCheckButton()
{
    checkButton.transform.localScale = new Vector3(1f, 1f, 1f);
    float animtionTime = 0.3f;
    float scaleUpTo = 1.2f;
    for (int i = 0; i < 4; i++)
    {
        yield return AnimationController.animate(scaleCheckButton, 
        animtionTime, 1f, scaleUpTo);
        yield return AnimationController.animate(scaleCheckButton, 
        animtionTime, scaleUpTo, 1f);
    }
    checkButton.transform.localScale = new Vector3(1f, 1f, 1f);
}

void scaleCheckButton(float value)
{
   checkButton.transform.localScale = new Vector3(value, value, value);
}

public void CheckButton()
{
    int answer;
    foreach (TestModeQuestionUI _TestModeQuestionUIRefrence in 
testModeQuestionExampleList)
    {
        answer = _TestModeQuestionUIRefrence.GetAnswerInputField();
        if ((a * b) == answer)
        {
            _TestModeQuestionUIRefrence.SetResultOfAnswerInputField(1);
        }
        else
        {
            _TestModeQuestionUIRefrence.SetResultOfAnswerInputField(2);
        }
    }

    checkButton.SetActive(false);
    nextButton.SetActive(true);
}

public void NextButton()
{
    ResetUI();
    nextButton.SetActive(false);

}

3 个答案:

答案 0 :(得分:0)

您应该在循环内获取随机值,否则您将获得相同的值。

foreach (TestModeQuestionUI _TestModeQuestionUIRefrence in testModeQuestionExampleList)
{
    int a = UnityEngine.Random.Range(1, 10);
    int b = UnityEngine.Random.Range(1, 10);
    _TestModeQuestionUIRefrence.SetQuestionLabel(a, b);
}

您还应该将ab保存在TestModeQuestionUI中,因为它们在实例之间是不同的。

public class TestModeQuestionUI : MonoBehaviour
{
    private int a, b;

    public void SetQuestionLabel(int a, int b)
    {
        this.a = a;
        this.b = b;
        valueA.text = a + " " + b + "  = ";        
    }
}

答案 1 :(得分:0)

您有很多UI内容,但是如果我是您,并且如果我不想重复,那么我将创建一个单独的脚本来获取这样的随机值:

public class RandomIntegers {

   private static List<int> myNumbersA = new List<int>();
   private static List<int> myNumbersB = new List<int>();

   public static void  RandomValues(out int a,out int b)
   {
      if (myNumbersA.Count == 0)
      {
           for (int i = 0; i < 10; i++)
           {
               myNumbersA.Add(i + 1);
               myNumbersB.Add(i + 1);
           }
       }
       int indexA = Random.Range(0, myNumbersA.Count);
       int indexB = Random.Range(0, myNumbersB.Count);
       a = myNumbersA[indexA];
       b = myNumbersB[indexB];
       myNumbersA.RemoveAt(indexA);
       myNumbersB.RemoveAt(indexB);
    }
}

然后在您的ResetUI函数中,您可以使用 RandomIntegers.RandomValues(out a,out b);之所以以这种方式实现,是因为您的预制实例可以在实例化时访问它,并且由于它是静态的,因此对于a和b您将不会获得相同的随机结果。但是可以说,您可能获得6的{​​{1}}和a的{​​{1}},但{{1}的8和{{1} {1}}都将以b结尾。

答案 2 :(得分:0)

如果您拥有一套价值,并且想要确保自己永远不会获得相同的价值,那么最好是将它们放在一个池中,并在使用它们时将其删除。

假设您要在10个不同的数字中进行5种可能的乘法运算。

Vector2[] vec;
private void GenerateOperations() 
{
    List<int> list = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; // store all needed values
    this.vec = new Vector2[5]; // your 5 results
    for (int i = 0; i < vec.Length; i++)
    {
        int x = GetValue(list);  // get x value
        int y = GetValue(list);  // get y value
        vec[i] = new Vector2(x,y); // store in the index of the collection
        Debug.Log(vec[i].ToString()); // print to check
    }
}
private static int GetValue(List<int>list)
{
    int rand = Random.Range(0, list.Count); // Get a random value from 0 to how many left in the list (last value is discarded so no out of bound exception)
    int value = list[rand]; // Get the value at index
    list.RemoveAt(rand); // remove that entry in the collection so it does not get picked again
    return value; // return
}

现在,您将vec作为向量2的数组,它将给出操作的两个值。删除使用的值后,就不能再使用相同的值了。

您的vec集合可用于其他方法来创建UI。