C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

ツリー一括表示

行ごとに乱数で0、1を指定して二次配列を作る方法について(続 /サイカク (20/08/02(Sun) 04:54) #95443
Re[1]: 行ごとに乱数で0、1を指定して二次配列を作る方法につ.. /サイカク (20/08/02(Sun) 05:05) #95444
  ├ Re[2]: 行ごとに乱数で0、1を指定して二次配列を作る方法につ.. /WebSurfer (20/08/02(Sun) 10:13) #95446
  │└ Re[3]: 行ごとに乱数で0、1を指定して二次配列を作る方法につ.. /WebSurfer (20/08/02(Sun) 10:15) #95447
  └ Re[2]: 行ごとに乱数で0、1を指定して二次配列を作る方法につ.. /キングダム (20/08/02(Sun) 13:11) #95450
    ├ Re[3]: 行ごとに乱数で0、1を指定して二次配列を作る方法につ.. /Hongliang (20/08/02(Sun) 14:34) #95452
    │└ Re[4]: 行ごとに乱数で0、1を指定して二次配列を作る方法につ.. /サイカク (20/08/02(Sun) 16:50) #95455
    └ Re[3]: 行ごとに乱数で0、1を指定して二次配列を作る方法につ.. /サイカク (20/08/02(Sun) 16:45) #95454 解決済み
      └ Re[4]: 行ごとに乱数で0、1を指定して二次配列を作る方法につ.. /サイカク (20/08/02(Sun) 16:53) #95456 解決済み
        └ Re[5]: 行ごとに乱数で0、1を指定して二次配列を作る方法につ.. /shu (20/08/03(Mon) 07:52) #95457 解決済み


親記事 / ▼[ 95444 ]
■95443 / 親階層)  行ごとに乱数で0、1を指定して二次配列を作る方法について(続
□投稿者/ サイカク (5回)-(2020/08/02(Sun) 04:54:52)

分類:[.NET 全般] 

お世話になっております。
C#初心者のサイカクです。
VisualStudioCodeで開発を行っており、versionは1.47です。

昨日、同タイトルで以下のご質問をしました。

===================================
現在、「0」と「1」で構成された6×6の二次配列を作ろうとしています。
その際、行ごとに「0」を4つ、「1」を2つランダムで格納させたいです。
(列ごとの「0」と「1」の構成はどんな形であれ構わないです)
つまり、36個の要素の構成は最終的に「0」が24個、「1」が12個になります。

具体的には

000110
100100
001010
110000
101000
001001

このような二次配列を完成させたいと思っています。
二次配列の作り方や、1次配列の乱数指定方法は存じているのですが、
組み合わせて運用する方法を理解できなかったので、ご質問させていただきました。
====================================

この質問に対して、「Fisher-Yates」アルゴリズムを使ってはどうか?とアドバイスをいただき、
以下のコードを作成しました。

====================================

public class TestScpirt : MonoBehaviour
{
int[,] StageData = new int[6,6];

void Start()
{
LoadStageData();
DebugTable();
}

void LoadStageData()
{
int[] conbination = new int[6]{1, 1, 0, 0, 0, 0};
System.Random rnd = new System.Random();

for(int n = conbination.Length - 1; n >= 0; n--)
{
int k = rnd.Next(n + 1);
int tmp = conbination[k];
conbination[k] = conbination[n];
conbination[n] = tmp;
for(int l = StageData.GetLength(0) - 1; l >= 0; l--)
{
StageData[l, n] = conbination[l];
}
}
}

void DebugTable()
{
for(int y = 0; y < 6; y++)
{
string debugtext = "";
for(int x = 0; x < 6; x++)
{
debugtext += StageData[x, y] + ", ";
}
Debug.Log(debugtext);
}
}
}

====================================

しかし、実際にコンソール画面に表示されるデバッグは

000101
000101
000101
000101
100001
100001

あるいは

101000
101000
010100
010100
110000
110000

といった規則的な二次配列が表示されます。
おそらく、一次配列ごとの「0」と「1」のランダム格納はできているのですが、
出来上がった一次配列を二次配列の行に格納する段階、すなわち

for(int l = StageData.GetLength(0) - 1; l >= 0; l--)
{
StageData[l, n] = conbination[l];
}

この部分でコードが間違っているのだと思います。

数時間考えてみたのですが、原因が分からず困っています。
長文になってしまい、申し訳ございません。
原因がわかる方がいらっしゃいましたら、ご指導のほどよろしくお願い申し上げます。
[ □ Tree ] 返信 編集キー/

▲[ 95443 ] / ▼[ 95446 ] ▼[ 95450 ]
■95444 / 1階層)  Re[1]: 行ごとに乱数で0、1を指定して二次配列を作る方法について(続
□投稿者/ サイカク (6回)-(2020/08/02(Sun) 05:05:19)
申し訳ございません。
添付したコードの「イチ(1)」と「エル(l)」の違いが非常にわかりづらいため、
コードを書き直しました。以下に改訂後のコードを添付します。

===================
public class TestScpirt : MonoBehaviour
{
int[,] StageData = new int[6,6];

void Start()
{
LoadStageData();
DebugTable();
}

void LoadStageData()
{
int[] conbination = new int[6]{1, 1, 0, 0, 0, 0};
System.Random rnd = new System.Random();

for(int n = conbination.Length - 1; n >= 0; n--)
{
int k = rnd.Next(n + 1);
int tmp = conbination[k];
conbination[k] = conbination[n];
conbination[n] = tmp;
for(int L = StageData.GetLength(0) - 1; L >= 0; L--)
{
StageData[L, n] = conbination[L];
}
}
}

void DebugTable()
{
for(int y = 0; y < 6; y++)
{
string debugtext = "";
for(int x = 0; x < 6; x++)
{
debugtext += StageData[x, y] + ", ";
}
Debug.Log(debugtext);
}
}
}

===================
[ 親 95443 / □ Tree ] 返信 編集キー/

▲[ 95444 ] / ▼[ 95447 ]
■95446 / 2階層)  Re[2]: 行ごとに乱数で0、1を指定して二次配列を作る方法について(続
□投稿者/ WebSurfer (2090回)-(2020/08/02(Sun) 10:13:22)
No95444 (サイカク さん) に返信
> 申し訳ございません。
> 添付したコードの「イチ(1)」と「エル(l)」の違いが非常にわかりづらいため、
> コードを書き直しました。以下に改訂後のコードを添付します。
>
> ===================
> public class TestScpirt : MonoBehaviour
> {
> int[,] StageData = new int[6,6];
>
> void Start()
> {
> LoadStageData();
> DebugTable();
> }
>
> void LoadStageData()
> {
> int[] conbination = new int[6]{1, 1, 0, 0, 0, 0};
> System.Random rnd = new System.Random();
>
> for(int n = conbination.Length - 1; n >= 0; n--)
> {
> int k = rnd.Next(n + 1);
> int tmp = conbination[k];
> conbination[k] = conbination[n];
> conbination[n] = tmp;
> for(int L = StageData.GetLength(0) - 1; L >= 0; L--)
> {
> StageData[L, n] = conbination[L];
> }
> }
> }
>
> void DebugTable()
> {
> for(int y = 0; y < 6; y++)
> {
> string debugtext = "";
> for(int x = 0; x < 6; x++)
> {
> debugtext += StageData[x, y] + ", ";
> }
> Debug.Log(debugtext);
> }
> }
> }
>
> ===================
[ 親 95443 / □ Tree ] 返信 編集キー/

▲[ 95446 ] / 返信無し
■95447 / 3階層)  Re[3]: 行ごとに乱数で0、1を指定して二次配列を作る方法について(続
□投稿者/ WebSurfer (2091回)-(2020/08/02(Sun) 10:15:06)
すみません No95446 は操作ミスで投稿されてしまいました。無視してください。
[ 親 95443 / □ Tree ] 返信 編集キー/

▲[ 95444 ] / ▼[ 95452 ] ▼[ 95454 ]
■95450 / 2階層)  Re[2]: 行ごとに乱数で0、1を指定して二次配列を作る方法について(続
□投稿者/ キングダム (62回)-(2020/08/02(Sun) 13:11:15)
No95444 (サイカク さん) に返信

シャッフルするところのループが一個足りないです
https://paiza.io/projects/yFBtpj8zmiklmEaCuk4ugg

[ 親 95443 / □ Tree ] 返信 編集キー/

▲[ 95450 ] / ▼[ 95455 ]
■95452 / 3階層)  Re[3]: 行ごとに乱数で0、1を指定して二次配列を作る方法について(続
□投稿者/ Hongliang (1073回)-(2020/08/02(Sun) 14:34:52)
// 本題とは直接関係ないですが
処理を一つの関数に詰め込むと見通しが悪くなります。
例えば、「配列を引数にとって、その配列の内容をシャッフルする」というShuffleメソッドを作れば、LoadStageDataメソッドもすっきりするようになるかと思います。
// その場合、RandomオブジェクトをShuffleメソッド内で毎回newするわけにはいかないので、フィールドに置くなど対応が必要ですが。
[ 親 95443 / □ Tree ] 返信 編集キー/

▲[ 95452 ] / 返信無し
■95455 / 4階層)  Re[4]: 行ごとに乱数で0、1を指定して二次配列を作る方法について(続
□投稿者/ サイカク (9回)-(2020/08/02(Sun) 16:50:44)
No95452 (Hongliang さん) に返信

ご返信ありがとうございます。

> 処理を一つの関数に詰め込むと見通しが悪くなります。
> 例えば、「配列を引数にとって、その配列の内容をシャッフルする」というShuffleメソッドを作れば、LoadStageDataメソッドもすっきりするようになるかと思います。

おっしゃる通り1つのメソッドが大きくなりすぎていたので、複数のメソッドに分解して処理を実行してみました!
コード自体かなりシンプルかつ綺麗な内容になり、また一つ成長できたと感じています。
アドバイスいただき、ありがとうございました。
[ 親 95443 / □ Tree ] 返信 編集キー/

▲[ 95450 ] / ▼[ 95456 ]
■95454 / 3階層)  Re[3]: 行ごとに乱数で0、1を指定して二次配列を作る方法について(続
□投稿者/ サイカク (8回)-(2020/08/02(Sun) 16:45:16)
No95450 (キングダム さん) に返信

ご返信ありがとうございます。

> シャッフルするところのループが一個足りないです
> https://paiza.io/projects/yFBtpj8zmiklmEaCuk4ugg

いただいたコードを参考にしてアルゴリズムを作ってみたところ、
6×6の求めていた不規則な2次元配列が出来上がりました!
メソッドで分けていく思考も学べたので、非常に勉強になりました。
ありがとうございました。
解決済み
[ 親 95443 / □ Tree ] 返信 編集キー/

▲[ 95454 ] / ▼[ 95457 ]
■95456 / 4階層)  Re[4]: 行ごとに乱数で0、1を指定して二次配列を作る方法について(続
□投稿者/ サイカク (10回)-(2020/08/02(Sun) 16:53:50)
解決済みとしておきます。
皆さんご協力ありがとうございました!
解決済み
[ 親 95443 / □ Tree ] 返信 編集キー/

▲[ 95456 ] / 返信無し
■95457 / 5階層)  Re[5]: 行ごとに乱数で0、1を指定して二次配列を作る方法について(続
□投稿者/ shu (1227回)-(2020/08/03(Mon) 07:52:02)
No95456 (サイカク さん) に返信
> 解決済みとしておきます。
> 皆さんご協力ありがとうございました!

解決済のようですがLINQを利用した方法として
VBで結果がジャグ配列ですが以下のように書くことも出来ます。

Dim ary = {0, 1, 0, 1, 0, 0}
Dim rnd As New Random()

Dim ary2 = (From i In Enumerable.Range(0, 6)
        Select (From r In ary Order By rnd.Next(100)).ToArray()).ToArray()

解決済み
[ 親 95443 / □ Tree ] 返信 編集キー/


管理者用

- Child Tree -