Как получить случайные значения int в префаб, который вызывается несколько раз (без повторения одного и того же значения)? - PullRequest
0 голосов
/ 08 февраля 2019

Я создал префаб, который содержит текст (a * b =) и поле ввода (чтобы получить ответ пользователя).и я вызываю этот сборный 5 раз, используя c # скрипт.Я назначил a & b для random.range (1,10), чтобы получить 5 разных сумм.но в моем случае я получаю одинаковые значения для всех 5 сумм.

Я пробовал цикл foreach, и он выбирает случайные числа из заданного диапазона, и при нажатии кнопки проверки он показывает даже правильные ответы красным цветом (как неправильные),Это первый раз, когда я имею дело с вызовом prefab несколько раз через скрипт.поэтому нужна помощь, чтобы решить ее, пожалуйста.

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 голосов
/ 08 февраля 2019

У вас много пользовательского интерфейса, но на вашем месте и если я не хочу получать дубликаты, я бы создал отдельный скрипт для получения случайных значений, например:

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 для a и 8 для b, но также 8 для a и 6 для b оба приведут к 48 в конце.

0 голосов
/ 08 февраля 2019

Если у вас есть набор значений и вы хотите убедиться, что вы никогда не получите дважды одинаковые, то лучше всего, чтобы они были в пуле, и они удаляли их при использовании.

Допустим, выхотите иметь 5 возможных умножений из 10 разных цифр.

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 может использоваться в других методах для создания пользовательского интерфейса.

0 голосов
/ 08 февраля 2019

Вы должны получить случайное значение внутри цикла, в противном случае вы получите те же значения.

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

Вы также должны сохранить a и b в 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 + "  = ";        
    }
}
...