31
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【C#】リスト中から毎回違う要素をランダムに取り出すためのクラス【UniqueItemPicker.cs】

Last updated at Posted at 2019-11-19

はじめに

C#でリスト中から重複せずに要素を取り出した場面があったので、いい感じのクラスを書きました。Unityで使ってますが、ログ出力部分以外はC#でも使えます。CC0なのでよかったら活用してください。

Gist: UniqueItemPicker.cs

使い方

test.cs
using UnityEngine;

public class test : MonoBehaviour
{
    void Start()
    {
        // 配列を用意する
        var nameList = new string[]
        {
            "なかじ",
            "リリカちゃん",
            "ゴリラ",
        };

        // 配列を渡して初期化
        var enemyNameGenerator = new UniqueItemPicker<string>(nameList);

        // 要素を取り出す
        Debug.Log(enemyNameGenerator.GetUniqueItem());
        Debug.Log(enemyNameGenerator.GetUniqueItem());
        Debug.Log(enemyNameGenerator.GetUniqueItem());
        Debug.Log(enemyNameGenerator.GetUniqueItem()); // null

        // 履歴を削除
        enemyNameGenerator.ResetUsageHistory();

        // 再び取り出せるようになる
        Debug.Log(enemyNameGenerator.GetUniqueItem());
        Debug.Log(enemyNameGenerator.GetUniqueItem());
    }
}

出力

スクリーンショット 2019-11-19 18.27.02.png

初期化した時の要素を使い終わるとNullが返ってくる点に注意してください。そうなった場合、enemyNameGenerator.ResetUsageHistory()を呼び出すことで再度要素を取得することができます。

ソースコード

Gist: UniqueItemPicker.cs

UniqueItemPicker.cs
using System.Collections.Generic;

/// <summary>
/// リスト中から重複せずに要素を取り出すクラス
/// </summary>
public class UniqueItemPicker<T>
{
    T[] AllItems;
    /// <summary>
    /// コンストラクタ
    /// </summary>
    /// <param name="allItems">取り出したい要素の配列</param>
    public UniqueItemPicker(T[] allItems)
    {
        AllItems = allItems;
        InitIndexList();
    }

    void InitIndexList()
    {
        indexList.Clear();
        for (int i = 0; i < AllItems.Length; i++)
        {
            indexList.Add(i);
        }
    }

    /// <summary>
    ///  リスト中から重複せずに要素を取り出す
    /// </summary>
    public T GetUniqueItem()
    {
        if (indexList.Count == 0)
        {
            UnityEngine.Debug.LogError("要素がありません");
            return default(T);
        }
        return AllItems[GetIndex()];
    }

    List<int> indexList = new List<int>();
    int GetIndex()
    {
        int index = UnityEngine.Random.Range(0, indexList.Count);
        int result = indexList[index];
        indexList.RemoveAt(index);
        return result;
    }

    /// <summary>
    /// 使用履歴を初期化する
    /// </summary>
    public void ResetUsageHistory()
    {
        InitIndexList();
    }
}

ジェネリック型で作っているので構造体やクラスも扱えて便利です。型を限定していないので、要素がない時は default(T)を返しているところがポイントです。

最後に

役に立ったらいいねください!!

31
19
16

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?