LINQの Select
句では、前の行で出力された値 p
とint型 i
をもつ匿名型に変換しています。
ToDictionary
句では、i
を Key
に、p
を Value
とするDictionaryに変換しています。
シンプルな例に置き換えると以下のとおりです。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
public class LinqTest : MonoBehaviour
{
void Start ()
{
var list = new List<string>();
list.Add ( "AAA" );
list.Add ( "BBB" );
list.Add ( "CCC" );
// (1) で、元のリストの値 x と、int型 i を持つ匿名型(のIEnumerable)に変換
// (2) で、i を Key、x を Value とする Dictionary に変換
var dictionary = list.Select((x, i) => new { x, i} ) // (1)
.ToDictionary(d => d.i, d => d.x); // (2)
// 確認用
foreach ( var item in dictionary )
{
Debug.Log ( $"{item.Key}, {item.Value}" );
}
}
}
結果は下図のとおりです。
参考
型推論と匿名型 - C# によるプログラミング入門 | ++C++; // 未確認飛行 C
https://ufcpp.net/study/csharp/sp3_inference.html
なお元のコードにおいては、わざわざ持たせた Key を後工程で特に使用していないようですね。
【追記1】
変数がどのような型なのかは、Visual Studioであればその箇所にマウスカーソルを乗せれば表示されますよ。
LINQのなかでどのように変換されているか、ご自身でたしかめてみるのが早いと思います。
【追記2】
参考として、元のコードをこちらであれこれ書き換えて動かしてみたものを載せておきます。
変数名・メソッド名を含めて弄り回したので読み取りにくいかと思いますが、Dictionaryへの変換を行っていないことだけ確認してください。Listで処理しています。これでも同じように動くと思います。
using UnityEngine;
using System.Collections.Generic;
using System.Linq;
public class MakeDungeon : MonoBehaviour
{
// 設定する値
public int max = 5; //縦横のサイズ ※必ず奇数にすること
public GameObject wall; //壁用オブジェクト
public GameObject floor; //床用オブジェクト
public GameObject start; //スタート地点に配置するオブジェクト
public GameObject goal; //ゴール地点に配置するオブジェクト
// 内部パラメータ
private enum CellType { Wall, Path }; //セルの種類
private CellType[,] cells;
private Vector2Int startPos; //スタートの座標
private Vector2Int goalPos; //ゴールの座標
private void Start ()
{
//マップ状態初期化
cells = new CellType[max, max];
//スタート地点の取得
startPos = GetStartPosition ();
//通路の生成
//初回はゴール地点を設定する
goalPos = MakeMapInfo ( startPos );
//通路生成を繰り返して袋小路を減らす
var tmpStart = goalPos;
for ( int i = 0 ; i < max * 5 ; i++ )
{
MakeMapInfo ( tmpStart );
tmpStart = GetStartPosition ();
}
//マップの状態に応じて壁と通路を生成する
BuildDungeon ();
//スタート地点とゴール地点にオブジェクトを配置する
//初回で取得したスタート地点とゴール地点は必ずつながっているので破綻しない
var startObj = Instantiate(start, new Vector3(startPos.x, 1, startPos.y), Quaternion.identity);
var goalObj = Instantiate(goal, new Vector3(goalPos.x, 1, goalPos.y), Quaternion.identity);
startObj.transform.parent = this.transform;
goalObj.transform.parent = this.transform;
}
// スタート地点の取得
private Vector2Int GetStartPosition ()
{
//ランダムでx,yを設定
int randomX = Random.Range(0, max);
int randomY = Random.Range(0, max);
//x、yが両方共偶数になるまで繰り返す
while ( !( randomX % 2 == 0 && randomY % 2 == 0 ) )
{
randomX = Mathf.RoundToInt ( Random.Range ( 0, max ) );
randomY = Mathf.RoundToInt ( Random.Range ( 0, max ) );
}
return new Vector2Int ( randomX, randomY );
}
// マップ生成
private Vector2Int MakeMapInfo ( Vector2Int _startPos )
{
//スタート位置配列を複製
var tmpStartPos = _startPos;
//移動可能な座標のリストを取得
var movablePositions = GetMovablePositions(tmpStartPos);
//移動可能な座標がなくなるまで探索を繰り返す
while ( movablePositions != null )
{
//移動可能な座標からランダムで1つ取得し通路にする
var tmpPos = movablePositions[Random.Range(0, movablePositions.Count)];
cells[tmpPos.x, tmpPos.y] = CellType.Path;
//元の地点と通路にした座標の間を通路にする
var xPos = tmpPos.x + (tmpStartPos.x - tmpPos.x) / 2;
var yPos = tmpPos.y + (tmpStartPos.y - tmpPos.y) / 2;
cells[xPos, yPos] = CellType.Path;
//移動後の座標を一時変数に格納し、再度移動可能な座標を探索する
tmpStartPos = tmpPos;
movablePositions = GetMovablePositions ( tmpStartPos );
}
//探索終了時の座標を返す
return tmpStartPos;
}
// 移動可能な座標のリストを取得する
// private Dictionary<int, Vector2Int> GetPosition ( Vector2Int _startPos )
private List<Vector2Int> GetMovablePositions ( Vector2Int _startPos )
{
//可読性のため座標を変数に格納
var x = _startPos.x;
var y = _startPos.y;
//移動方向毎に2つ先のx,y座標を仮計算
var positions = new List<Vector2Int> {
new Vector2Int(x, y + 2),
new Vector2Int(x, y - 2),
new Vector2Int(x + 2, y),
new Vector2Int(x - 2, y)
};
//移動方向毎に移動先の座標が範囲内かつ壁であるかを判定する
//真であれば、返却用リストに追加する
var movablePositions = positions.Where(p => !IsOutOfBounds(p.x, p.y) && cells[p.x, p.y] == CellType.Wall);
return movablePositions.Count () != 0 ? movablePositions.ToList () : null;
}
//与えられたx、y座標が範囲外の場合真を返す
private bool IsOutOfBounds ( int x, int y ) => ( x < 0 || y < 0 || x >= max || y >= max );
//パラメータに応じてオブジェクトを生成する
private void BuildDungeon ()
{
//縦横1マスずつ大きくループを回し、外壁とする
for ( int i = -1 ; i <= max ; i++ )
{
for ( int j = -1 ; j <= max ; j++ )
{
//範囲外、または壁の場合に壁オブジェクトを生成する
if ( IsOutOfBounds ( i, j ) || cells[i, j] == CellType.Wall )
{
var wallObj = Instantiate(wall, new Vector3(i, 0, j), Quaternion.identity);
wallObj.transform.parent = this.transform;
}
//全ての場所に床オブジェクトを生成
var floorObj = Instantiate(floor, new Vector3(i, -1, j), Quaternion.identity);
floorObj.transform.parent = this.transform;
}
}
}
}
上の(書き換えたほうの)コードで動かしてみたGIFです。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2019/01/14 15:16
2019/01/14 15:51
2019/01/14 16:05
退会済みユーザー
2019/01/15 17:05