using System.Text; namespace RosterSnap { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void textBox1_TextChanged(object sender, EventArgs e) { OnTextChanged(); } private void textBox2_TextChanged(object sender, EventArgs e) { OnTextChanged(); } private void OnTextChanged() { // 1. 左侧名单 var roster = SplitLines(textBox1.Text); // 2. 右侧接龙:去掉行首序号、点号、空格等,只保留名字 var dragonRaw = SplitLines(textBox2.Text); var dragon = new List(); foreach (var line in dragonRaw) { // 去掉行首的 #接龙、例 姓名 等无用行 if (line.StartsWith("#") || line.StartsWith("例")) continue; // 用正则把 “数字. 姓名 备注” 中的姓名提取出来 var match = System.Text.RegularExpressions.Regex.Match(line, @"^\s*\d+\.\s*([^\s]+)"); if (match.Success) dragon.Add(match.Groups[1].Value); } // 3. 比对 var missing = roster .Where(n => !dragon.Contains(n, StringComparer.OrdinalIgnoreCase)) .ToList(); var sb = new StringBuilder(); sb.AppendLine($"名单共 {roster.Count} 人,接龙中已出现 {roster.Count - missing.Count} 人。"); if (missing.Count == 0) { sb.AppendLine("✅ 所有人已接龙。"); } else { sb.AppendLine($"❌ 以下 {missing.Count} 人缺席:"); missing.ForEach(n => sb.AppendLine(n)); } textBox3.Text = sb.ToString(); } private static List SplitLines(string text) => text.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries) .Select(s => s.Trim()) .Where(s => !string.IsNullOrWhiteSpace(s)) .ToList(); private void linkLabel1_Click(object sender, EventArgs e) { System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo { FileName = linkLabel1.Text, UseShellExecute = true }); } } }