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

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

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

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

UI

UIはUser Interfaceの略であり、人間がコンピュータとやりとりをするためのシステムです。

Unity

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

Q&A

解決済

4回答

1804閲覧

switch文、if文、for文の羅列による長文化を解消したい

wata3

総合スコア16

C#

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

UI

UIはUser Interfaceの略であり、人間がコンピュータとやりとりをするためのシステムです。

Unity

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

0グッド

0クリップ

投稿2020/06/10 09:37

前提・実現したいこと

Unityでカードゲームを作ろうとしています。
現在、デッキエディット画面を作ろうとしていて、カード検索部分のプログラムを書いています。
イメージ説明
この画像がエディット画面の一部です。
3つのドロップダウンと4つのテキストボックスで構成しています。
現状、まず1つ目のドロップダウンでカード種(画像のKindの部分)でswitch文で分岐させ、
Lv、Textのテキストボックスの入力の有無をif文、Typeのドロップダウンで更にswitch文、
最終的にfor文でカードを表示させています。
下記がそのスプリクトの一部です。

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using UnityEngine.UI; 5using System; 6public class CardSearch : MonoBehaviour 7{ 8 public InputField Level; 9 public InputField ATK; 10 public InputField DEF; 11 public InputField Text; 12 public Dropdown kindDD1; 13 public Dropdown kindDD2; 14 public Dropdown Type; 15 int Lv, atk, def,i; 16 public GameObject SearchArea; 17 public GameObject CardData; 18 public GameObject CardID_; 19 GameObject Obj; 20 [SerializeField] private unit unit; 21 [SerializeField] private item item; 22 [SerializeField] private spel spel; 23 public void UnitSearch(int x) 24 { 25 CardData.GetComponent<CardD>().ShowDataU(x); 26 Obj = Instantiate(CardData, this.transform.position, Quaternion.identity); 27 Obj.GetComponent<CardID>().cardID =unit.Sheet1[x].id; 28 Obj.transform.parent = SearchArea.transform; 29 } 30 public void SpelSearch(int x) 31 { 32 CardData.GetComponent<CardD>().ShowDataS(x); 33 Obj = Instantiate(CardData, this.transform.position, Quaternion.identity); 34 Obj.GetComponent<CardID>().cardID = spel.Sheet1[x].id; 35 Obj.transform.parent = SearchArea.transform; 36 } 37 public void ItemSearch(int x) 38 { 39 CardData.GetComponent<CardD>().ShowDataI(x); 40 Obj = Instantiate(CardData, this.transform.position, Quaternion.identity); 41 Obj.GetComponent<CardID>().cardID = item.Sheet1[x].id; 42 Obj.transform.parent = SearchArea.transform; 43 } 44 void Start() 45 { 46 Int32.TryParse(Level.text, out Lv); 47 Int32.TryParse(ATK.text, out atk); 48 Int32.TryParse(DEF.text, out def); 49 foreach (Transform child in SearchArea.transform) 50 { 51 Destroy(child.gameObject); 52 } 53 54 int UD = unit.Sheet1.Count; 55 int ID = item.Sheet1.Count; 56 int SD = spel.Sheet1.Count; 57 for (i = 0; i < UD; i++) 58 { 59 UnitSearch(i); 60 } 61 for (i = 0; i < SD; i++) 62 { 63 SpelSearch(i); 64 } 65 for (i = 0; i < ID; i++) 66 { 67 ItemSearch(i); 68 } 69 } 70public void CardSEARCH() 71 { 72 Int32.TryParse(Level.text, out Lv); 73 Int32.TryParse(ATK.text, out atk); 74 Int32.TryParse(DEF.text, out def); 75 foreach (Transform child in SearchArea.transform) 76 { 77 Destroy(child.gameObject); 78 } 79 int UD = unit.Sheet1.Count; 80 int SD = spel.Sheet1.Count; 81 int ID = item.Sheet1.Count; 82 83 switch (kindDD1.value) 84 { 85 case 0: 86 if (String.IsNullOrEmpty(Text.text) && 87 String.IsNullOrEmpty(Level.text)) 88 { 89 switch (Type.value) 90 { 91 case 0: 92 for (i = 0; i < UD; i++) 93 { 94 UnitSearch(i); 95 } 96 for (i = 0; i < SD; i++) 97 { 98 SpelSearch(i); 99 } 100 for (i = 0; i < ID; i++) 101 { 102 ItemSearch(i); 103 } 104 break; 105 case 1: 106 for (i = 0; i < UD; i++) 107 { 108 if (String.IsNullOrEmpty(unit.Sheet1[i].type)) 109 { 110 UnitSearch(i); 111 } 112 } 113 for (i = 0; i < SD; i++) 114 { 115 if (String.IsNullOrEmpty(spel.Sheet1[i].type)) 116 { 117 SpelSearch(i); 118 } 119 } 120 for (i = 0; i < ID; i++) 121 { 122 if (String.IsNullOrEmpty(item.Sheet1[i].type)) 123 { 124 ItemSearch(i); 125 } 126 } 127 break; 128 case 2: 129--------------------中文略-------------- 130             case 40: 131 for (i = 0; i < UD; i++) 132 { 133 if (unit.Sheet1[i].type.Contains("盾")) 134 { 135 UnitSearch(i); 136 } 137 } 138 for (i = 0; i < SD; i++) 139 { 140 if (spel.Sheet1[i].type.Contains("盾")) 141 { 142 SpelSearch(i); 143 } 144 } 145 for (i = 0; i < ID; i++) 146 { 147 if (item.Sheet1[i].type.Contains("盾")) 148 { 149 ItemSearch(i); 150 } 151 } 152 break; 153 } 154 } 155 else if (String.IsNullOrEmpty(Level.text) == false && 156 String.IsNullOrEmpty(Text.text) == false) 157 { 158 switch (Type.value) 159 { 160 case 0: 161 for (i = 0; i < UD; i++) 162 { 163 if (Lv == unit.Sheet1[i].level) 164 { 165 if (unit.Sheet1[i].name1.Contains(Text.text) || 166 unit.Sheet1[i].name2.Contains(Text.text) || 167 unit.Sheet1[i].effect1.Contains(Text.text) || 168 unit.Sheet1[i].effect2.Contains(Text.text) || 169 unit.Sheet1[i].effect3.Contains(Text.text)) 170 { 171 UnitSearch(i); 172 } 173 } 174 } 175 for (i = 0; i < SD; i++) 176 { 177 if (Lv == spel.Sheet1[i].level) 178 { 179 if (spel.Sheet1[i].name1.Contains(Text.text) || 180 spel.Sheet1[i].name2.Contains(Text.text) || 181 spel.Sheet1[i].effect1.Contains(Text.text) || 182 spel.Sheet1[i].effect2.Contains(Text.text) || 183 spel.Sheet1[i].effect3.Contains(Text.text) || 184 spel.Sheet1[i].effect4.Contains(Text.text)) 185 { 186 SpelSearch(i); 187 } 188 } 189 } 190 for (i = 0; i < ID; i++) 191 { 192 if (Lv == item.Sheet1[i].level) 193 { 194 if (item.Sheet1[i].name1.Contains(Text.text) || 195 item.Sheet1[i].name2.Contains(Text.text) || 196 item.Sheet1[i].effect1.Contains(Text.text) || 197 item.Sheet1[i].effect2.Contains(Text.text) || 198 item.Sheet1[i].effect3.Contains(Text.text) || 199 item.Sheet1[i].effect4.Contains(Text.text)) 200 { 201 ItemSearch(i); 202 } 203 } 204 } 205 break; 206 case 1:

現在記入途中ですが14550行にもなってしまっています。
まだトグルによる検索も実装しようとしています。
どうにか圧縮して書く方法はありますか?
また、検索実行したときに2分ほど時間がかかるのですが短縮する方法はあるでしょうか?

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

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

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

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

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

guest

回答4

0

ベストアンサー

前の質問でも言ったんですが、カードのデータクラスを作りましょう。
あとLinqを使うと大分スムーズになります。

C#

1//【カードのデータクラス】 2public class CardModel { 3 public int id; 4 public string name; 5 public CardKind kind; //enumを使用する 6 public int level; 7 public string type; //試しに文字列で持たせる 8} 9//【カードの種別】 10public enum CardKind { 11 Unit, Spell, Item 12} 13 14 15//【検索クラス】 16using System.Linq; //Linq使用に必要 17public class CardSearch : MonoBehaviour { 18 // クラス変数として全カード一覧を持っておく(どこかでロードしておくものとする) 19 List<CardModel> allCardList; 20 21 // 検索 22 public void CardSEARCH() { 23 foreach (Transform child in SearchArea.transform) { 24 Destroy(child.gameObject); 25 } 26 27 // Kindで検索(Enumは数字でもあるので、Dropdownと並びを合わせておくとこう書ける) 28 IEnumerable<CardModel> result = allCardList.Where (s => s.kind == kindDD1.value); 29 30 // Typeで検索(whereの前がresultである点に注意。先に検索した結果の中から更に検索する) 31 //(Dropdownの選択中のキャプションは dropdown.captionText.text で取れる) 32 if (Type.value != 0) { 33 result = result.Where (s => s.type == Type.captionText.text); 34 } 35 36 // レベルで検索 37 if (Level.text != "") { 38 result = result.Where (s => s.level.ToString() == Level.text); 39 } 40 41 // 結果を表示 42 foreach (CardModel model in result) Show(model); 43 } 44 45 // 検索結果表示 46 public void Show(CardModel model) 47 { 48 CardData.GetComponent<CardD>().Show(model); 49 Obj = Instantiate(CardData, this.transform.position, Quaternion.identity); 50 Obj.GetComponent<CardID>().cardID = model.id; //この辺のIDの取り回しは要確認 51 Obj.transform.parent = SearchArea.transform; 52 } 53} 54 55 56//【表示クラス】 57public class CardD : MonoBehaviour { 58 // Text等の変数表記省略 59 60 // 表示 61 public void Show(CardModel model) 62 { 63 // 全カードで共通の処理 64 nameText.text = model.name; 65 levelText.text = model.level.ToString(); 66 67 if (kind == CardKind.Unit) { 68 //このカードがユニットの場合にやりたい処理 69 } 70 if (kind == CardKind.Spell) { 71 //このカードがスペルの場合にやりたい処理 72 } 73 } 74}

投稿2020/06/11 00:53

sakura_hana

総合スコア11427

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

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

wata3

2020/06/11 03:43

カードデータはエクセルで管理してるのですがそのデータは使えますか?
sakura_hana

2020/06/11 04:39 編集

使えます。エクセルのデータからデータクラスを作ればいいだけです。 CardModel model = new CardModel(); model.name = unit.Sheet1[x].name; などと愚直にやってもいいですし、CardModelクラスにコンストラクタを作ってエクセルデータを渡してもよいかと。
wata3

2020/06/11 08:21

書いていると、 IEnumerable<CardModel> result = allCardList.Where(s => s.kind == kindDD1.value);の部分で CS0019 演算子 '==' を 'CardKind' と 'int' 型のオペランドに適用することはできません と出てきました。どこを直せばいいのでしょうか?
sakura_hana

2020/06/11 08:29

そういえば直接比較出来ませんでしたね。 エラーに書いてある通り、型を合わせればいいのでCardKindをint型に変換してください。 IEnumerable<CardModel> result = allCardList.Where(s => (int)s.kind == kindDD1.value);
wata3

2020/06/11 13:58 編集

for文じゃないのでどこからunit.Sheet1[x]のxの値を持ってくればよいのかわかりません。どこから持ってくればいいですか?
sakura_hana

2020/06/11 23:54

何を言っているのかよく分かりません。 1.エクセルのデータからカードデータクラスを作る。 2.作ったカードデータクラスをallCardListに入れる。 3.allCardListを検索に使う。 という流れです。エクセルのデータは手順2以降は使用しません。
wata3

2020/06/12 22:47

カードデータクラスの作り方がわかりません。
wata3

2020/06/14 12:31

多分解決しました。ありがとうございました。
guest

0

Unityというのをさわったことないし,
そんなことになっている状況もよくわかりませんけども……

例えば,掛け算九九の表を作る際に,

switch( 1つ目の値 ) { //1の段 case 1: swich( 2つ目の値 ) { case 1: return 1; case 2: return 2: ... case 9: return 9; } //2の段 case 2: swich( 2つ目の値 ) { ... } ... //9の段 case 9: swich( 2つ目の値 ) { ... } }

って,81パターンに分岐するコードを書きますか? っていう話とほぼ同様な雰囲気に見えます.
こんなものは return (1つ目の値)*(2つ目の値); で済みますよね.

そんな感じに,現在switchで使っている値で分岐せずに済むロジックを考えればよいでしょう.
例えば,

  • 「Nパターンの値を取り得る値から,Nパターンの対応する文字列を決める必要がある(何かの値が40のときには"盾"とかそういう)」ならば,「数値→文字列 の変換表を用意しとけば,その表を引く処理を書けば済む」とか,
  • 「0~50のいずれかを取り得る値があって,0のときと50のときはそれぞれ特殊ケースなんだけども,他はまぁ同じような処理をする」とかであれば,馬鹿正直に51パターンに分岐するswitchを書かずとも「ifで{0のとき,50のとき,それ以外}の3パターンに分岐させれば,"それ以外"のところはまぁまとめて書けるよな」とか…

そういうことを考えてみてはどうでしょう.

投稿2020/06/10 10:28

編集2020/06/10 10:37
fana

総合スコア11652

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

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

0

例えば、

C#

1Dictionaly<int, Act> SearchMethodByKind = new ... 2{ 3 { 0, SeachByUnit }, 4 ... 5}; 6 7void SearchByUnit() 8{ 9 // Kind が ユニット の場合の検索 10} 11 12public void CardSEARCH() 13{ 14 Int32.TryParse(Level.text, out Lv); 15 Int32.TryParse(ATK.text, out atk); 16 Int32.TryParse(DEF.text, out def); 17 foreach (Transform child in SearchArea.transform) 18 { 19 Destroy(child.gameObject); 20 } 21 int UD = unit.Sheet1.Count; 22 int SD = spel.Sheet1.Count; 23 int ID = item.Sheet1.Count; 24 25 SearchMethodByKind[kindDD1.value](); 26}

の様にすれば、case文の中がメソッドに分割できるので、かなり見やすくなります。

あなたのプログラムは、「どの様にして実現するか」がわかりやすく書かれています。
最近の傾向は、「ここでは何が実現されるか」をわかりやすく書きます。
CardSEARCHでは、「kindDD1.valueが0の時は、typeによってユニットを検索して、スペルを検索して・・・」ではなく、CardSEARCHでは「ユーザーの選択によってカードを検索する」ことがわかれば十分です。カードの検索の仕方については、他のメソッドへ任せます。

投稿2020/06/10 13:19

Q71

総合スコア995

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

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

wata3

2020/06/10 13:36 編集

簡潔に言えば1つ目の回答者と同じで切り出して関数化するってことですかね? とりあえずDictionaryの使い方調べてみます。
guest

0

それぞれ切り出して関数にしてしまいましょうよ

投稿2020/06/10 09:43

y_waiwai

総合スコア87747

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問