2016-12-07 2 views
1

// EDIT: これは「ListとLinkedListのどちらを使うべきか」と重複していません。私が下で提供した答えをチェックしてください。 適切に注文されたリスト(その場合はLinkedList)が既に作成されている場合、誰かが特定の場所にいくつかのポジションを挿入したい場合でも、LinkedListは役に立ちます。 //ランダムに生成された数値のセットを逆方向に(入力を一時停止して)繰り返す方法はありますか?

ランダムに生成された数値のセットを逆方向に(プレーヤーの入力のために一時停止して)繰り返しますか?

私はターンベースのゲームを構築しようとしています。アクションの順序は、そのような何かの結果によって決定されます

int randomPosition = Random.Range(1,31) + someModifier; 

// please note that someModifier can be a negative number! 
// There is no foreseeable min or max someModifier. 
// Let's assume we can't set limits. 

私はすでにオブジェクトの名前とそれに対応するrandomPositionを含むです。KeyValueペアのリストを持っています。 // Update:その値は、カスタムソート(Sort)関数によって既にソートされています。

// A list of KeyValue pairs containing names of objects and their corresponding randomPosition. 
public List<KeyValuePair<string, int>> turnOrder = new List<KeyValuePair<string, int>>(); 

// GameObject names are taken from a list of player and AI GameObjects. 
List <GameObject> listOfCombatants = new List<GameObjects>(); 

// Each GameObject name is taken from listOfCombatants list. 
listOfCombatants[i].name; 

多分、playerとAI GameObjectsをそれぞれのrandomPositionに等しいインデックス位置のリストに追加してみましょう。残念なことに、汎用リストには「ギャップ」はありません。だから私たちはそれを作成することはできません。

また、私はforループがプレーヤーの入力を待つのを止める方法がわかりません。私はボタンを持っていますが、これはアクションスイッチの状態を示し、いくつかの機能を実行します。

Button combat_action_button; 
combat_action_button.onClick.AddListener (AttackButton); 

// When player takes his turn, so in TurnState.PLAYER_ACTION: 

    public void AttackButton() { 
switch(actionState) { 
case PlayerAction.ATTACK: 
     Debug.Log (actionState); 
     // Do something here - run function, etc. Then... 
     currentState = TurnState.ENEMY_ACTION; 
    break; 
} 

状況を悪化させるために、whileループはパフォーマンスを良くするものではありません。それは、プレイヤーの入力をループから取り除く方が良いということです。 ループのためにさらにを作成し、最後のGameObjectが動作するまで位置から位置まで新しいループを繰り返し、いくつかのデリゲート/イベントを使用する必要があります。players/AIが行うことができるスクリプト(クラス)があります。 これはリアルタイムのプロジェクトではないため、可能な限り最大のターン時間を除いて、何時でも何かの基礎を作ることはできません。 もう1つのことは、いくつのゲームオブジェクトが交代するかわかりません。

しかし、おそらく、インデックス位置の間にギャップを持ってGameObjectsを格納し、問題なくループを繰り返すことができるコレクションタイプがありますか? できるだけシンプルにしたいと思います。

+0

あなたのリストにギャップの問題はありえない:それぞれの "ギャップ"について - 1を使用し、リストを参照するときにLINQを使用して - 1以外のすべてのデータを照会する。 – aguertin

+2

ランダムのリスト整数。 **あなたはそれが後方にあるとどのように言えるでしょうか?**彼らはランダムです。ランダムなコインフリップのリストは、フォワードと同様にランダムに見えます。 –

+0

ソートされた辞書は何ですか? –

答えて

0

ユーザーの入力とループを同時に行う問題については、バックグラウンドワーカーやスレッド/タスクを調べることをおすすめします。これは一度に2つのことを同時に行うことであなたの問題を容易にするはずです。

私は個人的にもリストを好むので、 - 1のような特定の文字で各「ギャップ」を指定し、データを参照するときに - 1を無視します。ギャップを無視するために、LINQ LINQを使用したくない場合は、問題ではありません。

EDIT *

私はユニティ程度が、人々は複数のスレッドを実行しているか、問題になる可能性がありますように聞こえると言ってきたものとはほとんど知りません。私はこの問題を調べて、あなたはバックグラウンドスレッドから統一APIを呼び出すことができないように思えます。だから、基本的には、あなたが背景のスレッドから統一APIを参照していない限り、あなたはokでなければなりません。これで、あなたはおそらく、バックグラウンドワーカーの内部のapiを呼び出す必要があるかもしれません。これを行うには、バックグラウンドワーカースレッドの前または後に呼び出しを呼び出す必要があります。私はかなり確信しているが、同時に、workerスレッドのプロパティをtrueに設定することで、メインスレッドからの同時呼び出しもある。

+0

唯一の問題は、このアプローチでは、実際には非現実的な数字を、おそらく1000または-1000のような「ギャップ」に挿入する必要があるということです。 そして、-1、4、15、22、30のような既存のインデックス位置の間の "ギャップ"に1000(または-1000)を挿入するループを実行する必要があります。 )。したがって、インデックス番号ごとに1000の位置が1000であるint配列を作成する方が良いかどうかはわかりません。ほとんどのrandomPositionは-5〜30になるので少しばかです。 –

+0

Ohおそらく私たちは少し話題になりました。私はより少ないステップを目指していましたので、それらのインデックス位置にGameObjectを挿入したいと思いました。リストまたは配列のタイプはであることが最適です。したがって、おそらくギャップに「null」を挿入する必要があります。次にヌルでないかどうかを確認します...まだギャップを作る必要性について心配しています。しかし、もっと良い方法はないかもしれません。 –

+2

答えの最初の部分はUnity3dにはあまり適用されません。バックグラウンドワーカーやタスクはUnityゲームエンジンで通常行われるものではありません。 –

0

自分の解決策を共有することに決めました。自分の質問に対する正確な答えを開発したと思います。

enter image description here

溶液#1。まず、配列、2つの変数および1つの機能宣言:

int[] arrayOrderedCombatants; 
int min = 100000; 
int max; 

public void SomePlayerAction() { 
    Debug.Log ("This is some player or AI action."); 
} 

public void IterateThroughTurnOrderPositions() { 
    for (int i=max; i >= min; i--) { 
     if (arrayOrderedCombatants [i] >= 0 && arrayOrderedCombatants [i] >= min) { 
      Debug.Log ("This is an existing position in turn order: " + arrayOrderedCombatants [i]); 
      foreach (var position in turnOrder) { 
       if (position.Value == arrayOrderedCombatants [i]) { 
        max = (arrayOrderedCombatants [i] - 1); 
        goto ExitLoop; 
       } 
      } 
     } 
    } 
    ExitLoop: 
    SomePlayerAction(); 
} 

その後に、私たちのテスト目的のためのがInput.GetKeyDownによってトリガアップデート()メソッドを使用してみましょう:

if (Input.GetKeyDown (KeyCode.O)) { 
     arrayOrderedCombatants = new int[turnOrder[0].Value + 1]; 

     Debug.Log ("This is arrayOrderedCombatants Length: " + arrayOrderedCombatants.Length); 

     foreach (var number in turnOrder) {    
      if (number.Value < min) 
       min = number.Value;  
     } 
     Debug.Log ("This is min result in random combat order: " + min); 

     for (int i=0; i < arrayOrderedCombatants.Length; i++) 
      arrayOrderedCombatants[i] = min -1; 

     foreach (var combatant in turnOrder) { 
      if (combatant.Value >= 0) { 
       arrayOrderedCombatants [combatant.Value] = combatant.Value; 
      } 
     } 
     max = turnOrder [0].Value; 
     while (max >= min) 
      IterateThroughTurnOrderPositions(); 
    } 

上記のコードは答える私質問。残念ながら、この解決策の問題は2つかもしれません。まず、負のインデックス位置を持つことはできません。したがって、someModifierによってrandomPositionが0未満になると、動作しません。第2の問題 - randomPositionの値が2回以上出現した場合、arrayOrderedCombatantsに1回だけ追加されます。だからそれも一度繰り返されます。 しかし、それは明らかです。int型配列のインデックス位置を占める複数の値を持つことはできません。

だから私はあなたにもっと良い解決策を提供します。それは別のアプローチですが、そうする必要があります。

Solution#2。まず、ゲームオブジェクトのリスト宣言:アップデートには、次に

List<GameObject> orderedCombatants = new List<GameObject>(); 

を()メソッド:

if (Input.GetKeyDown (KeyCode.I)) { 
     orderedCombatants.Clear(); 
     foreach (var combatant in initiative) { 
      Debug.Log (combatant); 
      for (int i=0; i < listOfCombatants.Count; i++) { 
       if (listOfCombatants[i].name.Contains(combatant.Key)) { 
        orderedCombatants.Add(listOfCombatants[i]); 
       } 
      } 
     } 
     foreach (var combatant in orderedCombatants) { 
      Debug.Log (combatant.name); 
     } 
    } 

は、上記すでに正しい順序に設定されゲームオブジェクトの新しいリストを作成します。今度はそれを繰り返し、各ゲームオブジェクトに簡単にアクセスして、必要なアクションを実行できます。

関連する問題