C#で 1〜10 をシャッフル表示 — “まず動かす” から “メソッド化・テスト” まで段階的に学ぶ
目次
1. はじめに
プログラミング学習の初期は 「とにかく動くコードを書く → 後で整理する」 というサイクルが効果的です。本記事では 1〜10 の整数をシャッフルして表示する という小さな課題を使い、
- Main メソッドだけ で書く “動けば OK” 版
- 同じ処理を メソッド化 して読みやすくした版
- Fisher–Yates シャッフル に置き換えて精度・効率を上げる版
- NUnit + Assert.That で自動テストを書く版
と、少しずつリファクタリングを進める過程を体験します。
2. ステップ 1 — Main メソッドだけで動かす
using System;
using System.Linq;
namespace ShuffleSample
{
internal class Program
{
static void Main(string[] args)
{
// 1〜10 を配列にする
int[] numbers = Enumerable.Range(1, 10).ToArray();
// 超ざっくりシャッフル(効率は二の次)
Random rnd = new Random();
for (int i = 0; i < numbers.Length; i++)
{
int j = rnd.Next(numbers.Length); // 0〜9 の乱数
int temp = numbers[i];
numbers[i] = numbers[j];
numbers[j] = temp;
}
// 結果を表示
Console.WriteLine(string.Join(", ", numbers));
}
}
}
視点 | 学び |
---|---|
流れ | プログラムは上から順に実行される |
配列 | Enumerable.Range で連番の配列を簡単に作れる |
乱数 | Random.Next(int max) は 0〜max-1 の整数を返す |
デバッグ | Console.WriteLine で動きを即確認できる |
3. ステップ 2 — シャッフルをメソッド化
using System;
using System.Linq;
namespace ShuffleSample
{
internal class Program
{
static void Main(string[] args)
{
int[] numbers = Enumerable.Range(1, 10).ToArray();
int[] shuffled = Shuffle(numbers); // メソッド呼び出し
Console.WriteLine(string.Join(", ", shuffled));
}
/// <summary>
/// 配列を “とりあえず” シャッフルして新しい配列を返す
/// </summary>
static int[] Shuffle(int[] source)
{
int[] result = source.ToArray(); // 元配列を壊さない
Random rnd = new Random();
for (int i = 0; i < result.Length; i++)
{
int j = rnd.Next(result.Length);
(result[i], result[j]) = (result[j], result[i]); // タプルで交換
}
return result;
}
}
}
メリット | 説明 |
---|---|
再利用性 | Shuffle() を他の場面でも呼べる |
可読性 | Main が “何をしているか” にフォーカスできる |
保守性 | 改善やバグ修正はメソッドだけ直せば良い |
4. ステップ 3 — Fisher–Yates で “正しい” シャッフルに
static int[] ShuffleFY(int[] source)
{
int[] result = source.ToArray();
Random rnd = new Random();
for (int i = result.Length - 1; i > 0; i--)
{
int j = rnd.Next(i + 1); // 0〜i の乱数
(result[i], result[j]) = (result[j], result[i]);
}
return result;
}
Fisher–Yates シャッフル は「各並べ替え結果が等確率になる」ことが数学的に保証され、かつ O(n) と高速です。実務用途ではこちらを採用しましょう。
5. ステップ 4 — NUnit + Assert.That でテストを書く
5-1. テスト プロジェクトを用意
- .NET CLI なら
dotnet new nunit -n ShuffleSample.Tests
dotnet add ShuffleSample.Tests reference ShuffleSample
- Visual Studio なら「テストプロジェクトの追加」→「NUnit テストプロジェクト」を選択。
5-2. Constraint ベース構文(Assert.That)を使ったテスト
using NUnit.Framework;
using System.Linq;
namespace ShuffleSample.Tests
{
public class ShuffleTests
{
[Test]
public void ShuffleFY_UniquenessAndRange()
{
int[] source = Enumerable.Range(1, 10).ToArray();
int[] shuffled = Program.ShuffleFY(source);
// 要素数は 10
Assert.That(shuffled, Has.Exactly(10).Items);
// 重複なし & 1〜10 と同等
Assert.That(shuffled, Is.Unique.And.EquivalentTo(source));
}
}
}
なぜ Assert.That が推奨されるか
観点 | Assert.AreEqual | Assert.That(Constraint 構文) |
---|---|---|
可読性 | expected / actual の順が混乱しがち | actual → 条件 の順で自然 |
柔軟性 | Equal, True, Null… とメソッド乱立 | Is.*, Has.* を 組み合わせて表現 |
失敗メッセージ | シンプルで差分表示は限定的 | Constraint に応じて詳細・差分を表示 |
拡張性 | 独自 Assert を足しにくい | 独自 Constraint を実装しやすい |
実務・中規模以上のテストでは Assert.That のほうが保守性・表現力ともに優位です。
6. まとめ
- Main に全部書く → 動作を確認
- メソッド化 して読みやすさ・再利用性を高める
- アルゴリズムを改善(Fisher–Yates)して精度・性能を向上
- NUnit + Assert.That で自動テストを追加し、品質を継続的に守る
「まず動かす → 少しずつ整理 → テストを足す」という小さなリファクタリングの積み重ねが、後の拡張やバグ修正を格段に楽にしてくれます。まずは手を動かし、この 4 ステップを体験してみてください。
訪問数 8 回, 今日の訪問数 8回
ディスカッション
コメント一覧
まだ、コメントがありません