2017-10-09 32 views
2

我有一個所謂訪問獨特的陣列的名字

public int[] box1 = {1, 0, 2}; 
public int[] box2 = {3, 1, 0}; 
public int[] box3 = {2, 3, 1}; 

什麼,我需要做的唯一的數組名被動態地訪問他們,並從它返回一個隨機元素,使用類似的一組整數數組這 -

foo="box"+2[random int]; 

其中foo是我的,包括「盒子」的前綴字符串溫度,增加我想「盒子」的數量,正從「BOX2」一個隨機元素。 (例如:foo = 3)

如果我通過字符串方法執行此操作,它會創建正確的nomanclature,但它只是一個字符串,我無法使用它實際在腳本中以實際的類/數組元素的形式訪問它們,將它們傳遞給別的東西。

我該怎麼做呢?幾個小時閱讀手冊,嘗試列表,但我認爲我沒有做正確的事情。謝謝!

+1

您正在尋找'Dictionary'。 – Programmer

+1

不是'Dictionary','Lookup' –

+1

不是''Dictionary''或''Lookup'',而是一個帶有''indexer''的自定義類 –

回答

3

就壞了你真正想要什麼做,你會看到它是多麼容易。就像我在評論部分提到Dictionary一樣,您仍然需要其他兩個C#功能來完成確切的語法。

你希望能夠做到這一點:

foo="box"+2[random int]; 

這是,與此相同:

int valueFromArray = arrayVariableName [index]; 

在下面的例子中,我們可以假定MyScript是我們的劇本的名字。

。您需要可以保存名稱和int數組名稱的字典。

Dictionary<string, int[]> boxes 

。你需要一種方法來"box"+2arrayVariableName轉換爲當前的腳本實例。這可以通過C#中的隱式轉換運算符功能來完成。您可以將"box"+2arrayVariableName合併到此隱式MyScript中,然後將其存儲到全局變量中以用於下一步。

//The global variable that holds the arrayVariableName to access 
static string targetBox = null; 

//Implicit conversion operators (box array name to this script(MyScript) instance) 
public static implicit operator MyScript(string box) 
{ 
    return setTargetAndGetInstance(box); 
} 

public static MyScript setTargetAndGetInstance(string box) 
{ 
    if (instance.boxes.ContainsKey(box)) 
    { 
     //Set the box requested. This will be needed in the Indexer overloading above 
     targetBox = box; 
     return instance; 
    } 
    else 
     return null; 
} 

。現在,你可以實現[index]語法。這可以通過索引器重載功能來完成。

//Indexer overloading (index to int (value in array)) 
public int this[int index] 
{ 
    get 
    { 
     //Get value based on value set in the implicit operators 
     return accessBox(targetBox, index); 
    } 
} 

現在,當你這樣做,"box"+2,它將與implicit轉換操作符的幫助下返回這個(MyScript)的實例。然後它將允許您使用索引器重載功能執行[random int]


下面的代碼是在你的問題和其他類似的方法來做到這一點的語法的例子。 包括相似的人,因爲他們看起來比更好的你是什麼要求

用一個簡單的功能:

int test1 = accessBox("box" + 2, UnityEngine.Random.Range(0, 3)); 
Debug.Log(test1); 

隨着arrayVariableName [index]語法:

您正在尋找這一點,但鑄造MyScript看起來很糟糕

int test2 = ((MyScript)("box" + 2))[UnityEngine.Random.Range(0, 3)]; 
Debug.Log(test2); 

隨着[arrayVariableName][index]語法:

int test3 = this["box" + 2][UnityEngine.Random.Range(0, 3)]; 
Debug.Log(test3); 

隨着[arrayVariableName, index]語法

int test4 = this["box" + 2, UnityEngine.Random.Range(0, 3)]; 
Debug.Log(test4); 

完整的功能例如:

using System.Collections.Generic; 
using UnityEngine; 

public class MyScript : MonoBehaviour 
{ 

    public int[] box1 = { 1, 0, 2 }; 
    public int[] box2 = { 3, 1, 0 }; 
    public int[] box3 = { 2, 3, 1 }; 


    public Dictionary<string, int[]> boxes = new Dictionary<string, int[]>(); 
    private static MyScript instance; 

    void Awake() 
    { 
     instance = this; 

     //Add to Dictionary 
     addBox(); 

     int test1 = accessBox("box" + 2, UnityEngine.Random.Range(0, 3)); 
     Debug.Log(test1); 

     int test2 = ((MyScript)("box" + 2))[UnityEngine.Random.Range(0, 3)]; 
     Debug.Log(test2); 

     int test3 = this["box" + 2][UnityEngine.Random.Range(0, 3)]; 
     Debug.Log(test3); 

     int test4 = this["box" + 2, UnityEngine.Random.Range(0, 3)]; 
     Debug.Log(test4); 
    } 

    void addBox() 
    { 
     boxes.Add("box1", box1); 
     boxes.Add("box2", box2); 
     boxes.Add("box3", box3); 
    } 

    public int accessBox(string box, int index) 
    { 
     //Return the array from the Dictionary 
     int[] tempVar; 
     if (boxes.TryGetValue(box, out tempVar)) 
     { 
      //Return the spicified index 
      return tempVar[index]; 
     } 
     else 
     { 
      //ERROR - return -1 
      return -1; 
     } 
    } 


    //Indexer overloading (index to int (value in array)) 
    public int this[int index] 
    { 
     get 
     { 
      //Get value based on value set in the implicit operators 
      return accessBox(targetBox, index); 
     } 
    } 

    static string targetBox = null; 

    //Implicit conversion operators (box array name to this script(MyScript) instance) 
    public static implicit operator MyScript(string box) 
    { 
     return setTargetAndGetInstance(box); 
    } 

    public static MyScript setTargetAndGetInstance(string box) 
    { 
     if (instance.boxes.ContainsKey(box)) 
     { 
      //Set the box requested. This will be needed in the Indexer overloading above 
      targetBox = box; 
      return instance; 
     } 
     else 
      return null; 
    } 

    //Indexer overloading (box array name to this script(MyScript) instance) 
    public MyScript this[string box] 
    { 
     get 
     { 
      return setTargetAndGetInstance(box); 
     } 
    } 

    //Indexer overloading (box array name to int) 
    public int this[string box, int index] 
    { 
     get 
     { 
      setTargetAndGetInstance(box); 
      return accessBox(box, index); 
     } 
    } 
} 
1

這裏是一個通用的解決問題的方法,使用Dictionary<TKey,TValue>

主要代碼:

using System; 
using System.Collections.Generic; 

public class Class1 
{ 
    public void Example() 
    { 
     // a dictionary with string keys 

     var string1 = "abcd"; 
     var string2 = "efgh"; 

     var dictionary1 = new Dictionary<string, int[]> 
     { 
      {string1, new[] {0, 1, 2}}, 
      {string2, new[] {3, 4, 5}} 
     }; 


     // a dictionary with custom type 

     var box1 = new Box(10, 10); 
     var box2 = new Box(20, 20); 

     var dictionary2 = new Dictionary<Box, int[]> 
     { 
      {box1, new[] {0, 1, 2}}, 
      {box2, new[] {3, 4, 5}} 
     }; 

     // get random value from both dictionnaries 

     var i1 = GetRandomInteger(dictionary1, string1); 
     var i2 = GetRandomInteger(dictionary2, box1); 
    } 

    private int GetRandomInteger<TKey>(IDictionary<TKey, int[]> dictionary, TKey key) 
    { 
     if (!dictionary.ContainsKey(key)) 
      throw new KeyNotFoundException(); 

     var array = dictionary[key]; 

     // prefer UnityEngine.Random here since it's static 
     var index = new Random().Next(array.Length); 

     var value = array[index]; 

     return value; 
    } 
} 

額外的代碼:

public struct Box 
{ 
    // a dictionary key should be immutable, therefore I use a struct 
    // implement equality members so that when querying the dictionary, 
    // it will find the value associated to the key 
    // see https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/how-to-define-value-equality-for-a-type 

    public int Width { get; } 
    public int Height { get; } 

    public Box(int width, int height) 
    { 
     Width = width; 
     Height = height; 
    } 

    public bool Equals(Box other) 
    { 
     return Width == other.Width && Height == other.Height; 
    } 

    public override bool Equals(object obj) 
    { 
     if (ReferenceEquals(null, obj)) 
      return false; 
     return obj is Box && Equals((Box) obj); 
    } 

    public override int GetHashCode() 
    { 
     unchecked 
     { 
      return (Width * 397)^Height; 
     } 
    } 

    public static bool operator ==(Box left, Box right) 
    { 
     return left.Equals(right); 
    } 

    public static bool operator !=(Box left, Box right) 
    { 
     return !left.Equals(right); 
    } 
}