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

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

ただいまの
回答率

91.05%

  • C#

    5541questions

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

  • Unity

    2800questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

配列をランダムに置き換えたい

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 294

YukioMaki

score 6

...
using UnityEngine;
using System.Collections;

public class Stage : MonoBehaviour {

public Material[] material;
private string[] layer =
{ "word1","word2","word3","word4","word5","word6","word7","word8","word9", "word10"};



void Word()
{
wd = Instantiate(WordPrefab, new Vector3(0, 1, 1), Quaternion.identity) as GameObject;
string layer = "word" + 1.ToString();
wd.gameObject.layer = LayerMask.NameToLayer(layer);
Renderer rend = wd.GetComponentInChildren<Renderer>();
rend.material = material[i];
i += 1;
}
・・・

マウスを押すごとにlayerの配列に入れたテキスチャーを表示するようにして実行出来たのですが、配列のまま表示しては面白くないのでアトランダムに表示したいと思います。
初心者でどう書いていいのか分からず詳しく教えていただけませんか。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • 退会済みユーザー

    2017/12/18 08:48

    複数のユーザーから「やってほしいことだけを記載した丸投げの質問」という意見がありました
    「質問を編集する」ボタンから編集を行い、調査したこと・試したことを記入していただくと、回答が得られやすくなります。

回答 2

checkベストアンサー

+1

以下のページが参考になるので、一度読んでみてください。
参考ページ1
参考ページ2


2017/12/18 20:50 コメントを受けて追記

ソースコードはほぼ合っています。
一部 } の数などがおかしいので、動くように直すとこう。

private string[] layer = {"word1","word2","word3","word4","word5","word6","word7","word8","word9", "word10"};

for (int j = 0; j < layer.Length; j++)
{
    string temp = layer[j]; //stringで問題無いです。
    int randomIndex = Random.Range(0, layer.Length);
    layer[j] = layer[randomIndex];
    layer[randomIndex] = temp;
}


「かと言ってintをstringにかえても??」
何故疑問に思ったか分かりませんが、まさにそれが答えです。

Random.Rangeは検索すると分かりますが「第一引数から'第二引数-1'の内、ランダムな数1つを返す」というメソッドです。
layer.Lengthは10なので、Random.Range(0, layer.Length)は「0から9までのランダムな数字1つ」と同じ意味です。
これ自体はただのintを返すだけで、「Random.Rangeが配列の要素そのものを指すわけではない」ことに注意です。

これを踏まえてfor文の挙動を見てみましょう。

j = 0の時
tempにlayer[0]格納(temp = "word1")
randomIndexにランダムな数字が入る(randomIndex = 3とする)
layer[0]にlayer[3]が入る(layer[0] = "word4", layer[3] = "word4")
layer[3]にtempが入る(layer[0] = "word4", layer[3] = "word1")

現在のlayer:0番目と3番目が入れ替わった
{"word4","word2","word3","word1","word5","word6","word7","word8","word9", "word10"}

j = 1の時
tempにlayer[1]格納(temp = "word2")
randomIndexにランダムな数字が入る(randomIndex = 2とする)
layer[1]にlayer[2]が入る(layer[1] = "word3", layer[2] = "word3")
layer[2]にtempが入る(layer[1] = "word3", layer[2] = "word2")

現在のlayer:1番目と2番目が入れ替わった
{"word4","word3","word2","word1","word5","word6","word7","word8","word9", "word10"}

(以下、j=9まで続く)

というように、シャッフルが行われます。
挙動がおかしい場合は、「エラーコードを見て問題点を探す」「初めて見るメソッドはまず検索してみる」「プログラムや実際の挙動を日本語で書いてみる」等すると自力解決しやすいです。

なお、この方法だと低確率で「シャッフルされない」「1項目だけしかシャッフルされない」などのケースが出ます。

  • 全てのループでrandomIndexがjと同値になった場合(同じ場所のものを入れ替えるので並び替えされない)
  • シャッフル後に元に戻った場合(「j=0の時randomIndex=1、j=1の時randomIndex=0」などが続いた時) など

「絶対シャッフルされたい」「なるべくバラバラにシャッフルされたい」という場合は別の方法を調べてみてください。


2017/12/21 20:50 コメントを受けて追記

「layerの配列をシャッフルしたい」という質問だったのでそう答えましたが、
そもそもの話をすると、質問文のコードはlayer配列を使用していません。

void Word() の中で
string layer = "word" + 1.ToString();
と記載しているので、layer変数には常に"word1"が入っています。
更に言うとこのlayerはレイヤーマスクを指定しているだけであり、テクスチャの変更はしていないです。

順番に表示されているのは「マテリアルの配列(material変数)」です。
これで表示が切り替わるということは、material配列にテクスチャ違いのマテリアルが複数入っているということですね。

もう面倒臭いので「恐らくこういうことがしたいのだろう」という全コード書きますね。

//配列をシャッフルしてから順番に使用するパターン
using UnityEngine;
using System.Collections;

public class Stage : MonoBehaviour {

public Material[] material;
private string[] layer =
{ "word1","word2","word3","word4","word5","word6","word7","word8","word9", "word10"};    //定義していますが使っていません
private int i;

void Start() {
    Shuffle ();  //最初に配列シャッフルする
}

//配列をシャッフルするコード
void Shuffle () {
    for (int j = 0; j < material.Length; j++)
    {
        Material temp = material[j];
        int randomIndex = Random.Range(0, material.Length);
        material[j] = material[randomIndex];
        material[randomIndex] = temp;
    }
}

//シャッフルされた配列を使う
void Word()
{
    GameObject wd = Instantiate(WordPrefab, new Vector3(0, 1, 1), Quaternion.identity) as GameObject;
    string layer = "word1";
    wd.gameObject.layer = LayerMask.NameToLayer(layer);
    Renderer rend = wd.GetComponentInChildren<Renderer>();
    rend.material = material[i];
    i += 1;

    //materialの数以上になるとエラーになるので、その場合0に戻す
    if (i >= material.Length) {
        i = 0;
    }
}
//別解:毎回ランダムで取得するパターン(かつ要らない変数をごっそり削除)
using UnityEngine;
using System.Collections;

public class Stage : MonoBehaviour {

public Material[] material;

void Word()
{
    GameObject wd = Instantiate(WordPrefab, new Vector3(0, 1, 1), Quaternion.identity) as GameObject;
    wd.gameObject.layer = LayerMask.NameToLayer("word1");
    Renderer rend = wd.GetComponentInChildren<Renderer>();
    rend.material = material[Random.Range(0, material.Length)];
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/18 18:36

    Sakura_hanaさん回答ありがとうございます。
    参考ページ2を開いて私なりに下記のスクリプト書き換えて追加してみました。
    ・・・
    private string[] layer =
    { "word1","word2","word3","word4","word5","word6","word7","word8","word9", "word10"};

    for (int j = 0; j < layer.Length; j++)
    {
    int temp = layer[j];
    int randomIndex = Random.Range(0, layer.Length);
    layer[j] = layer[randomIndex];
    layer[randomIndex] = temp;
        }

    ・・・
    stringをintの中にほり込むのは無理なことは私にも分かるのですが、かと言ってintをstringにかえても??
    Random自体0~配列の数までチョイスする、intで書かれているし、stringの配列をランダムするのは無理なのでしょうか?

    キャンセル

  • 2017/12/18 20:23

    前提条件の確認なのですが、目的としているのは「配列をランダムに並び替え(シャッフル)」ですか?
    それとも「配列の中からランダムに1つ抜き取り」ですか?

    キャンセル

  • 2017/12/18 20:29

    Sakura_hanaさんお手数かけてすいません。
    「配列をランダムに並び替え」です。
    最初にすべての配列を並び替えたいんです。

    キャンセル

  • 2017/12/18 20:57

    回答に追記しました。

    キャンセル

  • 2017/12/18 21:01

    ちなみに今回はがっつり回答しましたが
    「teratailはサポートセンターではなく、思考するエンジニアの為のQ&Aコミュニティです」。

    思考停止でも質問すれば回答貰えるだろ、という姿勢は閲覧者が悲しくなるので
    次回以降は参考ページ1に則った質問の程、宜しくお願い致します。

    キャンセル

  • 2017/12/19 11:03

    sukura_hanaさん詳しい解説ありがとうございます。
    ランダムが少しは理解できたと思います。
    返事が遅くなったのはコンパイラーは通ったのですが、表示に変化がないので、スクリプトに Debug.Log(layer[j]);を付け加え動きを確かめようとしたのですが、Array index is out of range.
    SoundSystem.Awake () (at Assets/Script/SoundSystem.cs:9)の!がでているためにDebug.Log(layer[j])が表示されていません。
    配列はAudioSource[] audio = GetComponents<AudioSource>();で
    オブジェクトをデストロイする時に1度音を鳴らすのに使っていいますが
    範囲を超えているとは思えないのですが、色々スクリプトを書き換えている最中です。
    !が消え、ランダムが構想どうりに作動出来るようになったらまたコメントします。
    取り急ぎお礼申し上げます。

    キャンセル

  • 2017/12/21 20:08

    Debugを調べたところアトランダムになっていましたが、sakura_hanaさんがご指摘どうり、「Random.Rangeが配列の要素そのものを指すわけではない」と言うことで表示はリストの1~順番どうりで変わりませんでした。そこで方針を変えて、表示するテキスチャーだけをランダムに抽選し表示後そのテキスチャーをnullにしました。
    nullにしたテキスチャーは表示しないために、if文で抽選したテキスチャーがnullだったと時はRundomに戻るようにしたところ構想どうりに動きました。
    ・・・
    void Word()
    {
    i = Random.Range(0, 9);
    if (material[i] == null)
    {
    Invoke("Word", 0);
    }

    d = 5;
    wd = Instantiate(WordPrefab, new Vector3(0, 1, 1), Quaternion.identity) as GameObject;
    string layer = "word" + i.ToString();
    wd.gameObject.layer = LayerMask.NameToLayer("layer");
    Renderer rend = wd.GetComponent<Renderer>();
    rend.material = material[i];
    material[i] = null;
    i += 1;

    Invoke("Deth", d);
    if (wd == true)
    {

    }
    }
    ・・・
    最初の方針、配列を置き換えて表示することも捨てがたく何か方法があればヒントを頂ければ嬉しいです。

    キャンセル

  • 2017/12/21 20:47

    回答に追記しました。

    キャンセル

  • 2017/12/22 19:24

    私が深場にはまったのは、レイヤーを並び換えれればテキスチャーも換えれると思っていた所にあるようですね。
    方針を変えたコードは問題なく動くようでしたので、生徒の算数指導に今日使いました。
    sakura_hanaさんの書いてくださったコードはこれからの生徒指導に役立つので、ゆっくり研究させて頂きます。
    ありがとうございました。

    キャンセル

+1

乱数を生成する

Google というサイトは便利なのでブックマークしておいてください。
ここにアクセスするとテキストボックス(文字の書けるところ)が出てきますので、そこに「C# 乱数」と書いてボタンを押すとたくさんのページへのリンクが表示されます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/17 10:58

    Zuishinさん回答ありがとうございます。
    でも、ここへ投稿する前にGoogleでしらべて、
    ・・・
    public static List<T> Shuffle<T>(this List<T> list){

    for (int i = 0; i < list.Count; i++) {
    T temp = list[i];
    int randomIndex = Random.Range(0, list.Count);
    list[i] = list[randomIndex];
    list[randomIndex] = temp;
    }

    return list;
    }
    ・・・
    このスクリプトをコピーしてそれを改善してみたのですがエラー、エラーで、
    うまくコンパイラー出来るように教えてもらえますか。

    キャンセル

  • 2017/12/17 12:54

    C# List シャッフル

    キャンセル

  • 2017/12/17 12:58

    エラーになるともうそこで思考停止する人がいますが、エラーメッセージはどうしたらうまくいくか教えてくれるメッセージです。

    エラーメッセージを読みましょう。
    エラーメッセージを読みましょう。
    エラーメッセージを読みましょう。

    重要なことなので三回言いました。

    それでもわからない場合はエラーメッセージを添えて聞きましょう。
    それでもわからない場合はエラーメッセージを添えて聞きましょう。
    それでもわからない場合はエラーメッセージを添えて聞きましょう。

    あと、質問するときにプレビュー画面にインデントの消えた汚いソースが表示されたはずです。
    気になりませんか?
    読みやすくインデントをつけてください。

    キャンセル

  • 2017/12/17 22:08

    「エラーになるともうそこで思考停止する人がいます」そう私はそのタイプです。
    だから、ここに投稿しました。
    Zuishinさんに聞いても無駄のようですので、他の方で丁寧に教えていただける方いませんか。

    キャンセル

  • 2017/12/18 00:19 編集

    すでに丁寧に教えました。
    もう一度書きましょう。
    C# List シャッフル

    キャンセル

  • 2017/12/18 00:19

    もう一度書きましょう。
    C# List シャッフル

    キャンセル

  • 2017/12/18 01:26

    あなたには尋ねていませんよ、Zuishinsan.

    キャンセル

  • 2017/12/18 01:35 編集

    もう一度書きましょう。
    C# List シャッフル。

    キャンセル

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

  • ただいまの回答率 91.05%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C#

    5541questions

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

  • Unity

    2800questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。