質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

2353閲覧

Unity5 C# Whileの使い方、ランダムで数値をリストから引き出していく方法で詰まっています。

Hide_O

総合スコア7

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2016/12/25 09:27

###前提・実現したいこと
プログラム初心者です。
Unityで01234の数字が入っているリストを用意して、
そのリストからランダムに1つの数字を抜き出して使い、
もしその数字を使ってしまっている場合は他の数字をランダムで
抜き出して使う。
それをリストに残っている数分実行したいのです。
###発生している問題・エラーメッセージ

無限ループから脱出できないのか、フリーズします・・・。
知識が薄く大変申し訳ありませんがご助力いただけると助かります。

###該当のソースコード
C# ここに言語を入力

ここにご自身が実行したソースコードを書いてください
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class RandomAttackTest : MonoBehaviour {
public List<int> Atknum = new List<int>();
private List<int> RandomList = new List<int>();
private int Ncount = 0;

// Use this for initialization void Start () { StartCoroutine (randattack()); } // Update is called once per frame void Update () { } private IEnumerator randattack() { while (true) { int i = Random.Range(0, Atknum.Count - 1); //iは0~Atknumの配列数から1引いた数の間のランダムな数字 if (RandomList.Contains(i)) //もしランダムリストの中にiが含まれていた場合は { continue; //もう一回 } Debug.Log(Atknum[i]); //そうでなかったなら選んだAtknumをログ Ncount++; //あらかじめ用意していたらカウントを上げる RandomList.Add(i); //ランダムリストにiを加える if (Ncount >= Atknum.Count) //Ncount が Atknumの数以上になったら { break; //whileをストップ } yield return new WaitForSeconds(1.0f); Debug.Log("おしまい"); } }

}

###試したこと
whileの使い方がわかってなさそうだと思い、
条件とかをわかりやすくして試していて以下のようなものは試したのですが
continueとbreakを両方使って条件を整えていくのがわかりませんでした・・。

private IEnumerator randattack()
{
int i = XCount;

while (true) { if (XCount < 10) { i++; Debug.Log(i); } break; } yield return null; Debug.Log("おしまい"); }

###補足情報(言語/FW/ツール等のバージョンなど)
より詳細な情報

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

こんにちは。
Unityには詳しくないので推測なんですが、解答してみます。

まず一つ目に、
Atknumの中身は何になっていますか?

csharp

1public List<int> Atknum = new List<int>();

と書かれているので、Atknumの中身が0なのではないかと疑いました。
もしどこかでAtknumの中身を設定しているならこの話は無視してください。

次に、

csharp

1Random.Range(0, Atknum.Count - 1);

が少し気になります。(UnityだとRangeっていうstaticメソッドなんですかね?)
C#の標準のRandomは、値の範囲を指定する方法で乱数を生成する場合、maxValueを「含まない」範囲で値を生成します。
なので、Random.Rangeが同じ仕様なら、Atknum.Count - 1をmaxValueにすると、Atknum.Count - 2までの範囲で値が生成されていると思われます。
その結果、Ncount >= Atknum.Countの条件を満たすことなくRandomListに生成される範囲の値が全てAddされてしまい、最初のifで無限にcontinueしているのではないかと予想しました。

最後に、
コードを質問文に書く時はコードブロックで囲んでください。
コードブロックにしないとインデントが残らず大変見づらいです。


おまけです。
whileループで乱数を生成し続けて、まだ出ていない値が出るまでガチャし続けるっていうのはかなり効率が悪いコードだと思います。
もうちょっと単純に考えられないですかね?例えば、「Atknumをシャッフルしておいて、それから順番に取り出す」とか。

csharp

1// Atknumをシャッフルしておいて、それを順番にDebug.Logに入れるだけ 2private IEnumerator randattack() 3{ 4 var shuffled = Atknum.OrderBy(_ => Guid.NewGuid()); // Atknumをシャッフルされたものにする 5 foreach (var x in shuffled) 6 { 7 Debug.Log(x); // シャッフルされたAtknumから1つ取り出したもの(質問のコードでいうAtknum[i]に相当) 8 yield return new WaitForSeconds(1.0f); 9 } 10}

投稿2016/12/25 12:33

tamoto

総合スコア4105

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Hide_O

2016/12/26 02:47

ご回答、ご指摘ありがとうございます! やりたかったことができました。 オマケもなるほど!ととても勉強になりました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問