原代碼 while (!result.All(x => x.Contains("語文課") && ...)) 只檢查三門主科。**在條件中加入 && x.Contains("自修課") 即可**。
using System;
using System.Linq;
namespace ScheduleGenerator {
class Program {
static void Main() {
string[] courses = { "體育課", "體育課", "美術課", "音樂課", "勞動課",
"語文課", "語文課", "語文課", "語文課", "語文課", "語文課", "語文課",
"數學課", "數學課", "數學課", "數學課", "數學課", "數學課", "數學課",
"英語課", "英語課", "英語課", "英語課", "英語課", "英語課", "英語課", "英語課" };
string[][] result;
do {
result = Enumerable.Range(0, 5)
.Select(_ => Enumerable.Range(0, 6).Select(__ => "").ToArray())
.ToArray();
var rndSeq = Enumerable.Range(0, 30)
.OrderBy(_ => Guid.NewGuid())
.Zip(courses, (i, c) => new { Index = i, Course = c })
.ToArray();
for (int day = 0; day < 5; day++) {
int pos = 0;
string[] main = { "語文課", "數學課", "英語課" };
for (int period = 0; period < 6; period++) {
int idx = day * 6 + period;
var match = rndSeq.FirstOrDefault(x => x.Index == idx);
result[day][period] = match?.Course ?? (pos < 3 ? main[pos++] : "自修課");
}
}
} while (!result.All(row =>
row.Contains("語文課") &&
row.Contains("數學課") &&
row.Contains("英語課") &&
row.Contains("自修課") // ★ 新增約束
));
// 打印:列優先(每節課橫向看 5 天)
for (int period = 0; period < 6; period++) {
for (int day = 0; day < 5; day++) {
Console.Write(result[day][period] + "\t");
}
Console.WriteLine();
}
}
}
}
do-while 保證約束滿足才退出,避免死循環(課程池足夠大時極快收斂)。Guid.NewGuid() 作為隨機排序鍵,簡單有效。pos < 3 ? main[pos++] : "自修課" 確保三門主科優先填滿,其餘位置自動變自修課,天然滿足「每天有自修」——**前提是選修課池不超過 3 節/天**;若選修課可能更多,需顯式保留 1 格給自修課。