Click here to Skip to main content
15,843,145 members
Please Sign up or sign in to vote.
3.00/5 (1 vote)
See more:
I am creating a Hangman game with different modes. The Evil Mode requires words to be grouped according to patterns. (Link to description of Evil Hangman: Evil Hangman[^] )

I think the patterns are generated correctly but I can't get the words to group according to their patterns. The issue is somewhere in the last two functions which are named groupwords and largestlist. Here's my code:

C#
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace HangMan
{
    public partial class Form3 : frmNormal
    {
        protected string[] wordbank;
        private int counter = 0;
        //protected ArrayList patterns = new ArrayList();
        List<string> patterns = new List<string>();
        public Form3()
        {
            InitializeComponent();
        }

        private void Form3_Load(object sender, EventArgs e)
        {
            words();
            chooseword();
            generatelist();
        }

        private void generatelist()
        {
            wordbank = new string[allWords.Length];
            for (int i=0; i<allWords.Length; i++)
            {
                if (allWords[i].Length==currentWord.Length)
                {
                    wordbank[counter] = allWords[i];
                    counter++;
                }
            }
        }

        public override void check(char choice, char[] find, char[] temp)
        {
            allpatterns(choice,find,temp);
            groupwords(choice,find,temp);
        }
        public override void btn_Click(object sender, EventArgs e)
        {
            base.btn_Click(sender, e);
        }

        public string pattern(string word, char choice, char[] find, char[] temp)
        {
            if (word.Contains(choice))
            {
                for (int i = 0; i < find.Length; i++)
                {
                    if (find[i] == choice)
                    {
                        temp[i] = choice;

                    }
                }
                copyWord = new string(temp);
                return copyWord;
            }
            else
            {
                return copyWord;
            }
        }
        
        public void allpatterns(char choice, char[] find, char[] temp)
        {
            for (int i=0; i<counter; i++)
            {
                string p = pattern(wordbank[i], choice, find, temp);
                if (patterns.Contains(p))
                    {
                        //do nothing
                    }
                else
                    {
                    patterns.Add(p);
                    }
            }

        }

        public void groupwords (char choice, char[] find, char[] temp)
        {
            /*ArrayList[] groupedwords = new ArrayList[patterns.Count];
            for (int i=0; i<patterns.Count; i++)
            {
                groupedwords[i] = new ArrayList();
            }*/
            List<List<string>> groupedwords = new List<List<string>>();
            //List<string> subgroup = new List<string>();
            for (int i=0; i<patterns.Count; i++)
            {
                groupedwords.Add(new List<string>());
            }
            for (int i=0; i<counter; i++)
            {
                string word = wordbank[i];
                string p = pattern(word, choice, find, temp);
                int index = patterns.IndexOf(p);
                groupedwords[index].Add(word);
            }
            largestlist(groupedwords,choice,find,temp);
        }

        private void largestlist (List<List<string>> groupedwords, char choice, char[] find, char[] temp)
        {
            for (int i=1; i<patterns.Count; i++)
            {
                int size = groupedwords[0].Count();
                int size2 = groupedwords[i].Count();
                if (size<size2)
                {
                    groupedwords[0] = groupedwords[i];
                }
            }
            /*for (int i=0; i<patterns.Count; i++)
            {
                for (int j=0; j<groupedwords[i].Count; j++)
                {
                    groupedwords[i].RemoveAt(j);
                }
                
            }
            int size = groupedwords[0].Count;
            copyWord = "";
            for (int i=0; i<size; i++)
            {
                copyWord += "_";
            }*/
            copyWord = groupedwords[0].ToString();
            display();
            if(!groupedwords[0].Contains(choice.ToString()))
            {
                wrong++;
            }
            result();
            int random = (new Random()).Next(wordbank.Length);
            currentWord = allWords[random];
            allpatterns(choice,find,temp);
            groupwords(choice, find, temp);
        }
    }
}


What I have tried:

I have tried making nested lists and arraylist though I am not sure my implementation is correct. Please suggest an easy way to do this. I am new to Visual Studio and C# so please explain your solutions in simplest terms. Thank you!
Posted
Updated 22-May-18 11:18am
v3
Comments
Patrice T 20-May-18 13:34pm    
How many words do you have ?
Why to do want nested lists, is you do with them ?
BillWoodruff 21-May-18 0:19am    
If you examine the link to 'Evil Hangman,' you'll see why.
Patrice T 21-May-18 0:47am    
This is what I have done, and I don't see the usage of nested lists.
It looks like a lot of work for not much usage to me.
BillWoodruff 21-May-18 1:19am    
When that document uses the term "associative arrays," that translates in C# to 'Dictionary. Is a Dictionary "nested" ? Not to me, unless the Key or Value Types are other Dictionaries. See code example below.
BillWoodruff 21-May-18 0:20am    
Okay, describe what happens now when you run your code. Errors ? Unexpected results ? Be specific.

... edit ...

Using the dictionary named 'words shown below, and this function:
public List<string> GetExcludedLetterMatches(List<string> words, char ch)
{
    return words.Where(wrd => ! wrd.Contains(ch)).ToList();
}
Look how easy it is to keep shrinking the working list by removing words containing the user's guessed letter:
List<string> workingList = words[8];

var noA = GetExcludedLetterMatches(workingList, 'a');
if (noA.Count > 0) workingList = noA;

var noE = GetExcludedLetterMatches(noA, 'e');
if (noE.Count > 0) workingList = noE;
This started with a list of the words whose length was #8 characters; then a list of words with no letter 'a was created, and that list was then filtered to exclude the letter 'e. Not shown here is the required code specific to the 'Hangman game, where, at the point there were no more "evil" options, you'd have to let the user see a match.

Note: the performance of this could be improved by using IEnumerables and deferred de-referencing.

... end edit ...

I can give you some ideas on how to organize the data you are working with for maximum re-use:

0. take the 'WordList file, put a comma at the end of each line; then strip out all the white-space and line endings.

1. create a Resource of Type 'String in your VS project, and paste in the edited 'WordList file content: title the new Resource: 'WordList

2. Organizing the data in the Resource"
// required
// using System.Collections.Generic;
// using System.Linq;

private const int minChars = 5;
private const int maxChars = 12;

private Dictionary<int, List<string>> WordsByLength;

private void Form1_Load(object sender, EventArgs e)
{
   WordsByLength = Resources.WordList.Split(new char[] {','})
        .Where(wrd => wrd.Length >= minChars && wrd.Length <= maxChars)
        .GroupBy(w => w.Length)
        .ToDictionary(w => w.Key, w => w.ToList());
}
You end up with each Key in the dictionary representing the number of characters of the filtered lengths; the Value of each entry as a List of all the words of that length.
 
Share this answer
 
v5
Comments
Maciej Los 22-May-18 16:27pm    
Interesting idea, Bill!
BillWoodruff 22-May-18 18:34pm    
thank you, Maciej
Member 13835659 23-May-18 13:14pm    
I'm not familiar with the Dictionaries (as I said I'm new to C#), but I will definitely look into it since it does appear in all the evil hangman codes I have seen.
BillWoodruff 25-May-18 22:24pm    
You have chosen an advanced problem to work with; the source describes it as suitable for those who have already had a basic course on programming. I suggest, based on my experience teaching programming with C#, that you will progress more rapidly if you get a good book, and intensely study the "basics" before taking this kind of problem on.
Member 13835659 26-May-18 12:59pm    
Will do. Thanks for all your help!
Quote:
I need help grouping words from a list into sublists in C#

There is more than 1 way to program an "Evil Hangman", And I would not use sublists because it would be a waste of time.
Step 1: words of given length
- Having prepared the words file, one can read directly words of given length to a list.
Step 2: keep words that don't have a letter
- Just filter the list, by moving all words to keep to front of list.
...

Every time you build a set of sublists, only 1 sublist will be useful. It takes less work to just pick what is needed.
 
Share this answer
 
Comments
Member 13835659 22-May-18 16:45pm    
Removing words from the string array would make the code a lot simpler! Thank you
BillWoodruff 23-May-18 20:56pm    
I have deleted your comment on the wrong post: "I'm glad to see my code has some impact on you."
Honestly, no impact. I like to read others solution, it is always interesting, but I didn't on this case.
In my solution, I use no sublist and no dictionary, I think I would be more efficient. Note that I didn't entered in details in my solution."

Responses should be posted on the the thread the response is written in reply to.
Patrice T 23-May-18 21:06pm    
Hi Bill,
It was impossible to answer your comment because it is deleted, but still visible :)
BillWoodruff 24-May-18 1:56am    
Well I could ask why you would respond to a deleted comment, but, I won't :) A better question is why deleted comments are not deleted, and I will raise an issue on that in the buggz forum.

cheers, Bill

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900