Skip to content

Instantly share code, notes, and snippets.

@Nia-TN1012
Last active August 29, 2015 14:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Nia-TN1012/022d3b9b788b17fe85fb to your computer and use it in GitHub Desktop.
Save Nia-TN1012/022d3b9b788b17fe85fb to your computer and use it in GitHub Desktop.
UnityのuGUIを使った俳句プログラミングです。言語はC#で、LINQ用ライブラリに室星亮太氏のUniLinqを使用しています。

このGistに上がっているC#ソースファイルの概要

  • Haiku-with-UniLinq-on-Unity.cs :
    • UnityのuGUIでInputFieldに入力した俳句を、Textオブジェクトに縦書きで表示するスクリプトです。
  • UniLinq-Additional.cs :
    • Haiku-with-UniLinq-on-Unity.csで呼び出しているZipメソッドにおいて.NET Framework 4.0以降に対応しているEnumerable.Zip<TFirst, TSecond, TResult> メソッドと同等の処理を実現するために、プロジェクトにインポートしたUniLinqのEnumerableクラスに追加したメソッドです。
// Auther : Nia Tomonaka
// Twitter : https://twitter.com/nia_tn1012
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
// このC#スクリプトは 室星亮太氏( @RyotaMurohoshi )のUniLinqを使用しています。
using UniLinq;
public class Haiku : MonoBehaviour {
void Start () {
// 俳句作成ボタンオブジェクトを取得します。
Button button = GameObject.Find( "Button" ).GetComponent<Button>();
// そのボタンのクリックイベントハンドラに
// InputFieldに入力した俳句を表示する処理を登録します。
// 俳句を入力するInputFieldと俳句を表示するTextオブジェクトを取得します。
InputField infld = GameObject.Find( "haikuInput" ).GetComponent<InputField>();
Text phrase = GameObject.Find( "phrase" ).GetComponent<Text>();
// 俳句をカンマで分割します。
List<string> hHaiku = infld.text.Split( ',' ).ToList();
// 要素数が各句の中で最大の文字数の空文字列リストを作成します。
List<string> vHaiku = Enumerable.Repeat( "\n", hHaiku.Max( ( hPhrase ) => hPhrase.Length ) ).ToList();
// 各句において、文字数がvHaiku.Count()になるように不足分を全角スペースでパディングした文字列を
// char型配列にばらし、クエリ式でchar型文字をそれぞれ文字列に変換して、string型の文字リストを
// 生成します。そのリストをZipメソッドでそれぞれの要素において、文字を逆順で結合します。
hHaiku.ForEach( ( hPhrase ) =>
vHaiku = vHaiku.Zip(
hPhrase.PadRight( vHaiku.Count(), ' ' ).ToCharArray().Select( hpChar => hpChar.ToString() ),
( first, second ) => second + first // ← ここ重要
).ToList()
);
// Textに文字列を出力します(Aggregateメソッドで各要素の文字列を結合します)。
phrase.text = vHaiku.Aggregate( ( ccvHaiku, vPhrase ) => ccvHaiku += vPhrase );
Debug.Log( "俳句を作成しました。" );
} );
}
void Update () {}
}
// Haiku-with-UniLinq-on-Unity.cs
// Copyright (c) 2014-2015 Myoga-TN.net All Rights Reserved.
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php
// これはHaiku-with-UniLinq-on-Unity.csで呼び出しているZipメソッドにおいて、.NET Framework 4.0以降に対応している
// Enumerable.Zip<TFirst, TSecond, TResult> メソッドと同等の処理を実現するために、
// プロジェクトにインポートしたUniLinqのEnumerableクラスに追加したメソッドです。
#region Zip
//
// 概要:
// 指定された述語関数を使用して 2 つのシーケンスをマージします。
//
// パラメーター:
// first:
// マージする 1 番目のシーケンス。
//
// second:
// マージする 2 番目のシーケンス。
//
// resultSelector:
// 2 つのシーケンスの要素をマージする方法を指定する関数。
//
// 型パラメーター:
// TFirst:
// 1 番目の入力シーケンスの要素の型。
//
// TSecond:
// 2 番目の入力シーケンスの要素の型。
//
// TResult:
// 結果のシーケンスの要素の型。
//
// 戻り値:
// 2 つの入力シーケンスのマージされた要素が格納されている System.Collections.Generic.IEnumerable<T>。
//
// 例外:
// System.ArgumentNullException:
// first または second が null です。
public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>( this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector )
{
// 2つのリストとマージする方法を指定した関数がnullでないかをチェックします。
// このメソッドはあらかじめUniLinqのcheck.csのCheckクラスに定義しておきます。
Check.ZipSelector( first, second, resultSelector );
// firstとsecondの列挙子を取得し、それぞれを列挙します。
// MoveNextの戻り値がともにtrueの時、resultSelectorに設定した、
// メソッドを実行し、要素をマージします。
using( var first_seq = first.GetEnumerator() )
using( var second_seq = second.GetEnumerator() )
while( first_seq.MoveNext() && second_seq.MoveNext() ) {
yield return resultSelector( first_seq.Current, second_seq.Current );
}
}
#endregion
// こちらは上で実装したUniLinq.Enumerable.Zipメソッドから呼び出すZipSelectorメソッドの定義です。
// UniLinqのCheck.csのCheckクラスへ追加します。
public static void ZipSelector( object first, object second, object resultSelector ) {
if( first == null )
throw new ArgumentNullException( "first" );
if( second == null )
throw new ArgumentNullException( "second" );
if( resultSelector == null )
throw new ArgumentNullException( "resultSelector" );
}
// UniLinq-Additional.csの旧コードです。
public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>( this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector )
{
// funcのnullチェックを忘れていました・・・
Check.FirstAndSecond( first, second );
// インデックスをキーに同じインデックス同士の要素に対し、
// マージする方法を指定した関数によって関連付けます。
// ※UniLinq.nEumerableのJoinメソッドを呼び出します。
// しかし、Joinメソッドではfirstの要素を先頭から順にsecondのすべての要素と比較する
// 仕様のため、secondはすべての要素を読み込む必要があります(Non-Stream)。
// それに対し、Zipメソッドはfirst、secondともに必要な分だけ読み込む動作が要求されます(Stream)。
return Enumerable.Join(
first.Select( ( v, i ) => new { v, i } ),
second.Select( ( v, i ) => new { v, i } ),
x => x.i,
y => y.i,
( x, y ) => resultSelector( x.v, y.v )
);
}
#endregion
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment