たくのろじぃのメモ部屋

プログラミング(C#)の基礎やそれを応用した技術情報をメモしておくブログです。

【C#】Minecraft自動化 #7 建築自動化

はじめに

いよいよ建築自動化を行います。この内容が個人的に一番やりたかったことです。

建築は設計図をもとにブロックを配置していきたいと考えていますが、設計図をどうするかが問題ですね。3次元的に表したいので、CADと行きたいところですが、それはちょっとレベルが高いのでEXCELで作りたいと思います。

EXCELシートの行と列はX方向とZ方向、シートの枚数はY方向として、建築自動化プログラムを書いていきます。

1. EXCELファイルを読み込む

Googleで調べていると、COM参照すべきかしないべきかでいろいろ議論されており、やめたほうがいいという記事を見つけました。

qiita.com

そこで、今回はNPOIパッケージを使います。

www.nuget.org

f:id:takunology:20191116225252p:plain

あとはEXCELデータを読み込む処理を書いていきます。

public class ReadExcelFile
{
    public void OpenExcelFile()
    {
        var Path = "../../../Excel/TestBook.xlsx";
        var Book = WorkbookFactory.Create(Path);
        var Sheet = Book.GetSheetAt(0); //1枚目

        GetValue(Sheet, 0, 0); //シート1枚目の1行A列を取得

    }

    private void GetValue(ISheet Sheet, int Column, int Row)
    {
        var row = Sheet.GetRow(Row) ?? Sheet.CreateRow(Row); //例外対策
        var cell = row.GetCell(Column) ?? row.CreateCell(Column);
        string value;

        value = cell.StringCellValue;

        Console.WriteLine(value);
    }
}

動かしてみます。動かすときはExcelを閉じないとアクセス権を得られないので注意しましょう。

f:id:takunology:20191117010237p:plain

さて、文字列はこのままでいいのですが、数値の場合はちょっと工夫が必要です。NumericCellValueメソッドを用います。しかし、これはdouble型の返り値を返すので他の型へ変換する必要があります。文字列にしたいときはこのようにします。

value = cell.NumericCellValue.ToString();

他の型ならParseメソッドを使うと良いかもしれません。

また、シートごとにデータを見るためのメソッドを作ってみました。Valueを3次元配列で宣言してそれぞれシート数、行、列の順にアクセスできるようにしました。

public static void ShowSheet()
{
    for (int y = 0; y < Value.GetLength(0); y++)
    {
        Console.WriteLine($"{y + 1}枚目のシート");
        for (int x = 0; x < Value.GetLength(1); x++)
        {
            for (int z = 0; z < Value.GetLength(2); z++)
            {
                Console.Write(string.Format("{0, 3}", ($"{Value[y, x, z]}")));
            }
            Console.WriteLine();
        }
    }
}

f:id:takunology:20191117035452p:plain

さて、これでExcelファイルの読み込みはOKです。

2. ブロック名の定義

次に、得た値をマイクラのブロックIDに変換します。といっても、switch文で場合分けすればいいと思います。

public static void Convert()
{
    for (int y = 0; y < Value.GetLength(0); y++)
    {
        for (int x = 0; x < Value.GetLength(1); x++)
        {
            for (int z = 0; z < Value.GetLength(2); z++)
            {
                string value = Value[y, x, z];
                switch (value)
                {
                    case "0":
                        Value[y, x, z] = "air";
                        break;

                    case "1":
                        Value[y, x, z] = "stone";
                        break;

                    case "2":
                        Value[y, x, z] = "grass";
                        break;

                    case "3":
                        Value[y, x, z] = "glass";
                        break;

                    case "4":
                        Value[y, x, z] = "planks";
                        break;

                    case "5":
                        Value[x, y, z] = "sandstone";
                        break;
                }
            }
        }
    }
}

これをマイクラのコマンド送信メソッドに投げればいい感じに動きそうです。

3. Excel設計図をもとにした自動建築

Excelに設計図を書きます。例えば上のプログラムに合わせるならば、1は石、2は草ブロックというようにしてセルを埋めていきます。

セルを埋めたらプログラムを動かしていきます。ブロックのIDはWikiで調べるなどして登録しておくと、建築バリエーションが増えます。ちなみに色々改善して動かした結果はこんな感じです。

www.youtube.com

今回作ったコード

参考にどうぞ。

github.com

参考

NPOIの使い方で参考になりました。ありがとうございます。

www.sejuku.net