C# WinForm中基于Dictionary实现索书号与对应描述匹配交互功能的技术问询
Hey there! Let's break down how to fix your code and build the matching feature you want. First, let's go over the issues in your current code, then walk through a clean, working implementation.
First, Let's Fix Your Original Code's Issues
- Redundant Loops: You have 4 identical loops that run 9 times each, but each loop only keeps the last random value (since you overwrite the label's
Textevery iteration). That's why your labels only show one random category instead of unique ones. - Dictionary Key Quirk: Writing
000as a key is actually stored as0(since it's an int) — not a big problem here, but better to write it as0for clarity. - Spelling Errors: Fixed a few typos in your category names (e.g.,
Genral→General,Techynology→Technology) to make things consistent. - No Persistence: You aren't saving which random call numbers you picked, so you can't later verify if the user's choices are correct.
Step-by-Step Implementation
Let's build this properly, starting with clean setup and moving to the UI and validation.
1. Class-Level Fields (Reusable Resources)
First, move your dictionary and random generator to class-level fields so they're initialized once (not every time the form loads). This is more efficient and avoids duplicate work:
// Store Dewey Decimal categories once, reuse throughout the form private readonly Dictionary<int, string> _deweyCategories = new Dictionary<int, string> { { 0, "General Knowledge" }, { 100, "Philosophy & Psychology" }, { 200, "Religion" }, { 300, "Social Sciences" }, { 400, "Languages" }, { 500, "Science" }, { 600, "Technology" }, { 700, "Arts & Recreation" }, { 800, "Literature" }, { 900, "History and Geography" } }; // Reuse the same Random instance to avoid duplicate random numbers private readonly Random _random = new Random(); // Store the 4 randomly selected categories for later validation private List<KeyValuePair<int, string>> _selectedCategories;
2. Helper Method to Get Unique Random Categories
We need a way to pick 4 unique random categories (no repeats). This method will do that by removing items from a temporary list as we select them:
// Get N unique random categories from the dictionary private List<KeyValuePair<int, string>> GetRandomUniqueCategories(int count) { var allCategories = _deweyCategories.ToList(); var selected = new List<KeyValuePair<int, string>>(); // Keep picking until we have the desired count or run out of categories for (int i = 0; i < count && allCategories.Count > 0; i++) { int randomIndex = _random.Next(allCategories.Count); selected.Add(allCategories[randomIndex]); allCategories.RemoveAt(randomIndex); // Remove to avoid repeats } return selected; }
3. Helper Method to Shuffle Options
To make the matching game challenging, we'll shuffle the list of category descriptions so they aren't in order:
// Shuffle any list (Fisher-Yates algorithm) private void ShuffleList<T>(List<T> list) { int n = list.Count; while (n > 1) { n--; int k = _random.Next(n + 1); T temp = list[k]; list[k] = list[n]; list[n] = temp; } }
4. Form Load Event (Populate UI)
Now, update your form load event to show 4 unique call numbers and populate dropdowns with shuffled descriptions. I'm assuming you have:
- 4 Labels (
labelCall1tolabelCall4) to show call numbers - 4 ComboBoxes (
comboDesc1tocomboDesc4) for users to select matching descriptions
private void Dewery_Decimal_System_Load(object sender, EventArgs e) { // Get 4 unique random categories _selectedCategories = GetRandomUniqueCategories(4); // Get all category descriptions and shuffle them var allDescriptions = _deweyCategories.Values.ToList(); ShuffleList(allDescriptions); // Bind each call number to a label and populate its dropdown labelCall1.Text = _selectedCategories[0].Key.ToString(); comboDesc1.DataSource = new List<string>(allDescriptions); labelCall2.Text = _selectedCategories[1].Key.ToString(); comboDesc2.DataSource = new List<string>(allDescriptions); labelCall3.Text = _selectedCategories[2].Key.ToString(); comboDesc3.DataSource = new List<string>(allDescriptions); labelCall4.Text = _selectedCategories[3].Key.ToString(); comboDesc4.DataSource = new List<string>(allDescriptions); }
5. Validate User Choices (Button Click)
Finally, update your button15_Click event to check if the user's selections are correct and show results:
private void button15_Click(object sender, EventArgs e) { int correctAnswers = 0; StringBuilder resultMsg = new StringBuilder(); // Check each matching pair // Pair 1 if (comboDesc1.SelectedItem.ToString() == _selectedCategories[0].Value) { correctAnswers++; resultMsg.AppendLine($"Call Number {_selectedCategories[0].Key}: Correct!"); } else { resultMsg.AppendLine($"Call Number {_selectedCategories[0].Key}: Wrong! Correct answer is \"{_selectedCategories[0].Value}\""); } // Pair 2 if (comboDesc2.SelectedItem.ToString() == _selectedCategories[1].Value) { correctAnswers++; resultMsg.AppendLine($"Call Number {_selectedCategories[1].Key}: Correct!"); } else { resultMsg.AppendLine($"Call Number {_selectedCategories[1].Key}: Wrong! Correct answer is \"{_selectedCategories[1].Value}\""); } // Pair 3 if (comboDesc3.SelectedItem.ToString() == _selectedCategories[2].Value) { correctAnswers++; resultMsg.AppendLine($"Call Number {_selectedCategories[2].Key}: Correct!"); } else { resultMsg.AppendLine($"Call Number {_selectedCategories[2].Key}: Wrong! Correct answer is \"{_selectedCategories[2].Value}\""); } // Pair 4 if (comboDesc4.SelectedItem.ToString() == _selectedCategories[3].Value) { correctAnswers++; resultMsg.AppendLine($"Call Number {_selectedCategories[3].Key}: Correct!"); } else { resultMsg.AppendLine($"Call Number {_selectedCategories[3].Key}: Wrong! Correct answer is \"{_selectedCategories[3].Value}\""); } // Add final score resultMsg.AppendLine($"\nTotal Score: {correctAnswers}/4"); // Show results in a message box MessageBox.Show(resultMsg.ToString(), "Matching Results"); // Optional: Reset the game with new random categories // Dewery_Decimal_System_Load(sender, e); }
Key Takeaways for You
- Reuse Objects: Don't create a new
RandomorDictionaryevery time the form loads — this avoids duplicate random numbers and unnecessary memory usage. - Avoid Redundancy: Use helper methods for repeated tasks (like getting random items or shuffling) instead of copying code.
- Plan for Validation: Always store the correct answers so you can check user input later.
内容的提问来源于stack exchange,提问作者Luke Warren

