Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8895

【ASP.NET Core MVC】ASP.NET Core MVCであみだくじを作ってみる 6 (Razorを使う あみだを辿る編)

$
0
0

概要

前回:ASP.NET Core MVCであみだくじを作ってみる 5 (Razorを使う)
今回は、Razorを使って選択した番号のあみだを辿る処理を作ります。単なるおまけです。

前回同様、ASP.NET Core の Razor 構文リファレンスを参照しながら作っていきます。

描画したあみだを保持する

あみだを辿るには、ランダムに描画したあみだを保持しておく必要があります。
Kuji\Index.cshtmlの<div class="kuji-line">を以下のように変更します。
追加した行に+の印を付けました。

Kuji\Index.cshtml
<divclass="kuji-line">
            @{
                var rd = new Random();
                var rcount = Math.Max(20, Model.Result.Count * 4);   // グリッドレイアウトの行数

                // 行番号リスト(4行目以降、全行数 - 上下のボタンや結果表示域で使用している行を除く行数)
                var rows = Enumerable.Range(4, rcount - 6).ToList();

+               // 列ごとに横線の行番号を保持する用のリスト
+               var lines = new List<List<int>>();

                <!--人数の分だけループ-->
                for (var i = 1; i <Model.Result.Count+1;i++){<!--選択肢ボタン--><buttonclass="select-btn"style="grid-row:2;grid-column:@i"asp-route-id="@i">@i</button><!--縦線--><divclass="vertical-line"style="grid-row:3 / span @(rcount - 4);grid-column:@i"></div>

+                   var hlines = new List<int>();   // 横線を行番号を保持する用

                    <!--横線-->
                    if (i <Model.NumberOfKuji){varhcount = rd.Next(1,rcount/4);//横線の数for(varj = 0;j<hcount;j++){if(rows.Count<=0)break;//行が足りなくなったら終了intrno = rows[rd.Next(0,rows.Count-1)];//横線を引く行番号rows.Remove(rno);//重複する行番号を使わないようにするため<pclass="horizontal-line"style="grid-row:@rno;grid-column:@i"></p>

+                           hlines.Add(rno);
                        }
                    }
+                   lines.Add(hlines);  // 列ごとに横線の行番号を保持する
+                   
                    <!--結果--><!--横幅を揃えるため、PadRightで5文字分に揃える--><divstyle="grid-row:@(rcount - 1);grid-column:@i">@Model.Result[i - 1].Item.PadRight(5, ' ')</div>
                }

                <!--1行分を余白とする--><divstyle="grid-row:@rcount;grid-column:1 / span @Model.NumberOfKuji"></div>
            }

            <!--あみだを隠すためのマスク領域-->
            @if (Model.SelectId == 0)
            {
                <divclass="mask"></div>
            }
        </div>

番号を選択した後の処理を追加する

Kuji\Index.cshtmlの<div class="kuji-line">の<!--1行分を余白とする-->の前に、以下の処理を追加します。
選択した番号の縦線を辿り、右への横線と左への横線、どちらが上かを判定して上にあるほうの横線を辿ります。
横線を辿って縦線を移動したら、その縦線を辿り、同じように上にあるほうの横線を辿ります。

Kuji\Index.cshtml
                if (Model.SelectId > 0) // 番号を選択した場合
                {
                    // 選択した番号の列から始める
                    var currentCol = Model.SelectId - 1;
                    // 縦線が始まる行から始める
                    var currentRow = 3;

                    while (currentRow <rcount-1){//現在の列の右側に延びる横線のうち、現在の行より下にある横線を取得するvarrightRow = (currentCol==Model.NumberOfKuji)?null:lines[currentCol].Where(c => currentRow<c).ToList();//現在の列の左側に延びる横線のうち、現在の行より下にある横線を取得するvarleftRow = (0==currentCol)?null:lines[currentCol-1].Where(c => currentRow<c).ToList();//右への線のうち、一番上にある横線を取得するvarrightMin = (rightRow!=null&&rightRow.Count> 0) ? rightRow.Min() : 999;
                        // 左への線のうち、一番上にある横線を取得する
                        var leftMin = (leftRow != null && leftRow.Count > 0) ? leftRow.Min() : 999;

                        if (rightMin <leftMin){//右へ進む//現在の行から右へ進む横線までの縦線<divclass="vertical-line follow"style="grid-row:@currentRow / span @Math.Max(1, (rightMin - currentRow));grid-column:@(currentCol + 1)"></div>
                            // 右への横線
                            <pclass="horizontal-line follow"style="grid-row:@rightMin;grid-column:@(currentCol + 1)"></p>

                            currentCol++;   // 右へ進んだ
                            currentRow = (currentRow == rightMin) ? currentRow + 1 : rightMin;
                        }
                        else if (rightMin > leftMin)
                        {
                            // 左へ進む

                            // 現在の行から左へ進む横線までの縦線
                            <divclass="vertical-line follow"style="grid-row:@currentRow / span @Math.Max(1, (leftMin - currentRow));grid-column:@(currentCol + 1)"></div>

                            currentCol--;   // 左へ進んだ

                            // 左への横線
                            <pclass="horizontal-line follow"style="grid-row:@leftMin;grid-column:@(currentCol + 1)"></p>
                            currentRow = (currentRow == leftMin) ? currentRow + 1 : leftMin;
                        }
                        else
                        {
                            <divclass="vertical-line follow"style="grid-row:@currentRow;grid-column:@(currentCol + 1)"></div>
                            currentRow++;
                        }
                    }
                }

いろいろ触ってきたので、Kuji\Index.cshtmlの全体を載せておきます。

Kuji\Index.cshtml
@model Amidakuji.Models.KujiModel

@{
    ViewData["Title"] = "あみだくじ";
}

<formmethod="post"asp-controller="Kuji"asp-action="Index"><divclass="kuji-container"><h1>@Model.Title</h1><p>くじの数は、@Model.NumberOfKuji 本です。</p><!--あみだくじの領域(グリッドレイアウト)--><divclass="kuji-line">
            @{
                var rd = new Random();
                var rcount = Math.Max(20, Model.Result.Count * 4);   // グリッドレイアウトの行数

                // 行番号リスト(4行目以降、全行数 - 上下のボタンや結果表示域で使用している行を除く行数)
                var rows = Enumerable.Range(4, rcount - 6).ToList();

                // 列ごとに横線の行番号を保持する用のリスト
                var lines = new List<List<int>>();

                <!--人数の分だけループ-->
                for (var i = 1; i <Model.Result.Count+1;i++){<!--選択肢ボタン--><buttonclass="select-btn"style="grid-row:2;grid-column:@i"asp-route-id="@i">@i</button><!--縦線--><divclass="vertical-line"style="grid-row:3 / span @(rcount - 4);grid-column:@i"></div>

                    var hlines = new List<int>();   // 横線を行番号を保持する用

                    <!--横線-->
                    if (i <Model.NumberOfKuji){varhcount = rd.Next(1,rcount/4);//横線の数for(varj = 0;j<hcount;j++){if(rows.Count<=0)break;//行が足りなくなったら終了intrno = rows[rd.Next(0,rows.Count-1)];//横線を引く行番号rows.Remove(rno);//重複する行番号を使わないようにするため<pclass="horizontal-line"style="grid-row:@rno;grid-column:@i"></p>

                            hlines.Add(rno);
                        }
                    }
                    lines.Add(hlines);  // 列ごとに横線の行番号を保持する

                    <!--結果--><!--横幅を揃えるため、PadRightで5文字分に揃える--><divstyle="grid-row:@(rcount - 1);grid-column:@i">@Model.Result[i - 1].Item.PadRight(5, ' ')</div>
                }

                <!--1行分を余白とする--><divstyle="grid-row:@rcount;grid-column:1 / span @Model.NumberOfKuji"></div>

                if (Model.SelectId > 0) // 番号を選択した場合
                {
                    // 選択した番号の列から始める
                    var currentCol = Model.SelectId - 1;
                    // 縦線が始まる行から始める
                    var currentRow = 3;

                    while (currentRow <rcount-1){//現在の列の右側に延びる横線のうち、現在の行より下にある横線を取得するvarrightRow = (currentCol==Model.NumberOfKuji)?null:lines[currentCol].Where(c => currentRow<c).ToList();//現在の列の左側に延びる横線のうち、現在の行より下にある横線を取得するvarleftRow = (0==currentCol)?null:lines[currentCol-1].Where(c => currentRow<c).ToList();//右への線のうち、一番上にある横線を取得するvarrightMin = (rightRow!=null&&rightRow.Count> 0) ? rightRow.Min() : 999;
                        // 左への線のうち、一番上にある横線を取得する
                        var leftMin = (leftRow != null && leftRow.Count > 0) ? leftRow.Min() : 999;

                        if (rightMin <leftMin){//右へ進む//現在の行から右へ進む横線までの縦線<divclass="vertical-line follow"style="grid-row:@currentRow / span @Math.Max(1, (rightMin - currentRow));grid-column:@(currentCol + 1)"></div>
                            // 右への横線
                            <pclass="horizontal-line follow"style="grid-row:@rightMin;grid-column:@(currentCol + 1)"></p>

                            currentCol++;   // 右へ進んだ
                            currentRow = (currentRow == rightMin) ? currentRow + 1 : rightMin;
                        }
                        else if (rightMin > leftMin)
                        {
                            // 左へ進む

                            // 現在の行から左へ進む横線までの縦線
                            <divclass="vertical-line follow"style="grid-row:@currentRow / span @Math.Max(1, (leftMin - currentRow));grid-column:@(currentCol + 1)"></div>

                            currentCol--;   // 左へ進んだ

                            // 左への横線
                            <pclass="horizontal-line follow"style="grid-row:@leftMin;grid-column:@(currentCol + 1)"></p>
                            currentRow = (currentRow == leftMin) ? currentRow + 1 : leftMin;
                        }
                        else
                        {
                            <divclass="vertical-line follow"style="grid-row:@currentRow;grid-column:@(currentCol + 1)"></div>
                            currentRow++;
                        }
                    }
                }
            }

            <!--あみだを隠すためのマスク領域-->
            @if (Model.SelectId == 0)
            {
                <divclass="mask"></div>
            }
        </div></div><!--モデルをコントローラーへ通知--><inputtype="hidden"asp-for="Title"value="@Model.Title"/><inputtype="hidden"asp-for="NumberOfKuji"value="@Model.NumberOfKuji"/>
    @for (var i = 0; i <Model.Result.Count;i++){<inputtype="hidden"asp-for="Result[i].Item"value="@Model.Result[i].Item"/>
    }
    <inputtype="hidden"asp-for="SelectId"value="@Model.SelectId"/></form>

実行してみる

6番を選択してみた結果、晩御飯はぶり大根になったようです。
キャプチャ.PNG

ちなみに、くじの数が多くなると、行数が足りなくなって横線が入らない場合があります。
そのうち、気が向いたら改善する・・・かもしれません。

まとめ

今回は、Razorを使って選択した番号のあみだを辿る処理を作成しました。
駆け足ですが、ASP.NET Core MVCの学習(入門)は果たせたかな、と思いますので、今回で終わりにします!
GitHubの使い方を勉強したら、ソース全体をUPしようと思います。


Viewing all articles
Browse latest Browse all 8895

Trending Articles