9: 2016-05-13 (金) 01:56:42 osinko |
現: 2016-08-01 (月) 01:45:01 osinko |
| 有用なデザインパターンをサンプルコードとして羅列したページ | | 有用なデザインパターンをサンプルコードとして羅列したページ |
| | | |
| + | **switch_case文とcontinue;との関係 [#sdc20f7e] |
| + | |
| + | switch_case文の内部でbreak;はよく使われるがcontinue;を利用する場合はちょっと特殊な考え方になる |
| + | switch文の外側にあるネスト内の反復処理、for、while、do 、foreachに対して次のループに移る |
| + | 特殊な検索をかける場合に憶えておくと便利なやり方になる |
| + | |
| + | visualStudioではカーソルをbreak;やcontinue;の上に持っていくと関連している構文をマーカー表示する |
| + | わからなくなったら、まずこれで位置を確認すると良い |
| + | |
| + | #code(csharp){{ |
| + | using UnityEngine; |
| + | using System.Collections; |
| + | |
| + | public class SwitchContinue : MonoBehaviour |
| + | { |
| + | //優先順位の低い文字を検索する |
| + | void Start() |
| + | { |
| + | //括弧で囲まれると優先順位は上がるとする |
| + | string str ="B(AC(1A))CB(57A6)"; |
| + | int pos = 0; |
| + | int nest = 0; |
| + | int priority = 0; |
| + | int lowPriority = 3; |
| + | |
| + | //for文に対してcontinue;はここに来る |
| + | for (int i = 0; i < str.Length; i++) |
| + | { |
| + | switch (str[i]) |
| + | { |
| + | case 'A': priority = 1; break; //switch_case文に対してのbreak; |
| + | case 'B': priority = 2; break; |
| + | case 'C': priority = 3; break; |
| + | case '(': nest++; continue; |
| + | case ')': nest--; continue; |
| + | default: continue; //for文に対してのcontinue; |
| + | } |
| + | |
| + | //switch_case文に対してのbreak;はここに来る |
| + | if (nest==0 && priority <= lowPriority) |
| + | { |
| + | lowPriority = priority; |
| + | pos = i; |
| + | } |
| + | } |
| + | |
| + | print(string.Format("配列位置:{0} の文字:{1}", pos,str[pos])); |
| + | } |
| + | } |
| + | }} |
| + | |
| + | **帰納関数のサンプル(順列の出力) [#m9ded6a9] |
| + | |
| + | 基本的な帰納コードのサンプル |
| + | サンプルとして順列をテキストファイルで出力する |
| + | |
| + | <帰納処理を書くコツ> |
| + | -基底部、帰納部の二段階で関数を作成する(ドミノの一つ目、それに続く無限のドミノ、とふたつに分ける) |
| + | -基底の呼び出しの際は出来るだけ余計なデーターを渡さないように設計する |
| + | -派生した関数(帰納部)で扱う「差が生じるデータ」部が参照渡しの値の場合、希望する動作により呼び出し元が書き換えられると困る場合もあるので値の動きに注意する。必要であれば複製する |
| + | -帰納関数の入口に終了条件を設定する |
| + | |
| + | <このような形式のコードのなにが利点か?> |
| + | 例えば10行目11行目を |
| + | int length = 5; |
| + | char[] set = { 'H', 'T' }; |
| + | と書き換えても動く。forループでよく似た動きをするコードを書いた場合、変更はコード全体に及んでしまうが帰納では、このフォーマットを指定する部分のみで済む |
| + | |
| + | #code(csharp){{ |
| + | using UnityEngine; |
| + | using System.Collections; |
| + | using System.Collections.Generic; |
| + | using System.IO; |
| + | |
| + | public class Perm : MonoBehaviour |
| + | { |
| + | void Start() |
| + | { |
| + | int length = 3; |
| + | char[] set = { 'A', 'B', 'C' }; |
| + | |
| + | List<string> strList = Root(set, length); |
| + | |
| + | string folder = Application.dataPath; //これだけでunityの実行ファイルがあるフォルダがわかる |
| + | SaveText(folder, @"\test6.txt", strList.ToArray()); |
| + | } |
| + | |
| + | //基底部 |
| + | List<string> Root(char[] set, int length) |
| + | { |
| + | List<string> strList = new List<string>(); |
| + | int level = 0; |
| + | |
| + | for (int i = 0; i < set.Length; i++) |
| + | { |
| + | char[] dat = new char[length]; |
| + | dat[0] = set[i]; |
| + | Loop(dat, level, set, strList); |
| + | } |
| + | |
| + | return strList; |
| + | } |
| + | |
| + | //帰納部 |
| + | void Loop(char[] dat, int level, char[] set, List<string> strList) |
| + | { |
| + | level++; |
| + | if (level < dat.Length) //帰納関数の終了条件 |
| + | { |
| + | for (int i = 0; i < set.Length; i++) |
| + | { |
| + | char[] cloneDat = (char[])dat.Clone(); //オブジェクトを複製する |
| + | cloneDat[level] = set[i]; |
| + | Loop(cloneDat, level, set, strList); //帰納関数には複製された参照値が渡される為、呼び出し元側の値が書き換えられることは無い |
| + | } |
| + | } |
| + | else { |
| + | strList.Add(new string(dat)); |
| + | } |
| + | } |
| + | |
| + | //資料:StreamWriter クラス (System.IO) |
| + | //http://msdn.microsoft.com/ja-jp/library/system.io.streamwriter(v=vs.110).aspx |
| + | |
| + | //テキストファイルとしてセーブ |
| + | public void SaveText(string fileFolder, string filename, string[] dataStr) |
| + | { |
| + | using (StreamWriter w = new StreamWriter(fileFolder + filename, false, System.Text.Encoding.GetEncoding("shift_jis"))) |
| + | { |
| + | foreach (var item in dataStr) |
| + | { |
| + | w.WriteLine(item); |
| + | } |
| + | } |
| + | } |
| + | } |
| + | |
| + | }} |
| + | |
| + | ***補足:値渡し、参照渡しとは? [#v46aed99] |
| + | |
| + | 以下のコードの出力は |
| + | |
| + | 123 |
| + | 0 |
| + | 789 |
| + | |
| + | となる |
| + | |
| + | 変数valListの内容が関数内で書き換えられている点に注目。int型は値型だが、int[]型は参照型になるので関数は参照渡しを受け取り、呼び出し元を書き換える |
| + | つまり帰納関数で同様の事をした場合、派生先の関数内の書き換えで呼び出し元を書き変える事になり希望していた効果が得られない事がある |
| + | |
| + | #code(csharp){{ |
| + | using UnityEngine; |
| + | using System.Collections; |
| + | |
| + | public class TestMetho : MonoBehaviour { |
| + | |
| + | void Start () { |
| + | |
| + | int val = 123; |
| + | int[] valList = { 456, 789 }; |
| + | |
| + | Method(val, valList); |
| + | |
| + | print(val); |
| + | print(valList[0]); |
| + | print(valList[1]); |
| + | } |
| + | |
| + | void Method(int val, int[] valList) { |
| + | val = 000; |
| + | valList[0] = 000; |
| + | } |
| + | } |
| + | }} |
| | | |
| **データーをwiki用に変換したりCSVで出力等 [#afbd5d39] | | **データーをwiki用に変換したりCSVで出力等 [#afbd5d39] |