hangman game error. out of range error

Jonny123

Member
Joined
Oct 2, 2015
Messages
13
Programming Experience
Beginner
Hello,
I am getting an error message on the C# hangman program that i'm trying to recreate from a YouTube video at:
https://www.youtube.com/watch?v=E8XQ9x-7yYk
the program seems to run fairly well, but runs into an error once in a while. I'm not sure what code is needed to display the problem that I am having. Below is the section in which the error message shows.

            if (word.Contains(letter))
            {
                char[] letters = word.ToCharArray();
                for (int i = 0; i < letters.Length; i++)
                {
                    if (letters == letter)
                        labels.Text = letter.ToString(); // <-------------------- this creates an out of range error
                }
                foreach (Label l in labels)
                    if (l.Text == "_") return;
                MessageBox.Show("You have won", "Congrats");
                ResetGame();
            }
 

JohnH

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
1,194
Location
Norway
Programming Experience
10+
You loop 'labels', indicating that is a collection - yet you try to set 'labels.Text' as if 'labels' is a single control.
 

Jonny123

Member
Joined
Oct 2, 2015
Messages
13
Programming Experience
Beginner
Ok. Like I said, its not really my code.Any idea how to fix?

I wanted to say, but i'm not sure if this makes a difference, in the beginning of the code he puts this code:

C#:
List<Label> labels = new List<Label>();
 
Last edited:

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,904
Location
Sydney, Australia
Programming Experience
10+
I don't think you've actually posted the code you're running. As JohnH suggests the line that you claim is generating a run time error would actually generate a compile time error. There's another line in there that I doubt would compile either:
C#:
if (letters == letter)
For that to work, `letter` would have to be a char array and I doubt that that is the case.

Think about this logically. Forget that it's a programming problem and ask yourself what you do if it was with pen and paper. You are looping through the letters in the word. Does it make sense to compare every letter in the word to the user's single letter guess? Of course not. You want to compare one letter at a time. If you have a `for` loop to go through an array, how do you get one element at a time from that array?

Secondly, if you have a List of Label controls then it's fairly obvious that, when you match letter, you're going to want to display the letter in the Label at the same position as the letter that matched. That means that you need to get the Label to update from the List in the same way as you got the letter from the array, i.e. by index.
 

Jonny123

Member
Joined
Oct 2, 2015
Messages
13
Programming Experience
Beginner
Well, I ran this program, and it does not have a compile error. Sometimes it fails while its running, but that's it. I'm not sure how credible the programmer is that made this, I just think there's a small error somewhere that needs to be fixed.
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,904
Location
Sydney, Australia
Programming Experience
10+
I don't really see how that code could possibly compile so I reckon that it's actually failing and you're running an old build. Regardless, I told you where the issue are and what they are. Now you need to take that on board and fix them.
 

Jonny123

Member
Joined
Oct 2, 2015
Messages
13
Programming Experience
Beginner
I changed some stuff around, but i'm not entirely sure its correct
I am still getting an out o range error
C#:
if(word.Contains(letter))[COLOR=#333333][FONT=Consolas]{[/FONT][/COLOR]
[COLOR=#333333][FONT=Consolas]    char[] letters = word.ToCharArray();[/FONT][/COLOR]
[COLOR=#333333][FONT=Consolas]    for (int i = 0; i < letters.Length; i++)[/FONT][/COLOR]
[COLOR=#333333][FONT=Consolas]    {[/FONT][/COLOR]
[COLOR=#333333][FONT=Consolas]        if (letters[i] == letter)[/FONT][/COLOR]
[COLOR=#333333][FONT=Consolas]            labels[i].Text = letter.ToString(); // <-------------------- this creates an out of range error[/FONT][/COLOR]
[COLOR=#333333][FONT=Consolas]    }[/FONT][/COLOR]
[COLOR=#333333][FONT=Consolas]    foreach (Label l in labels)[/FONT][/COLOR]
[COLOR=#333333][FONT=Consolas]        if (l.Text == "_") return;[/FONT][/COLOR]
[COLOR=#333333][FONT=Consolas]    MessageBox.Show("You have won", "Congrats");[/FONT][/COLOR]
[COLOR=#333333][FONT=Consolas]    ResetGame();[/FONT][/COLOR]
[COLOR=#333333][FONT=Consolas]}
[/FONT][/COLOR]
 
Last edited:

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,904
Location
Sydney, Australia
Programming Experience
10+
I changed some stuff around, but i'm not entirely sure its correct
I am still getting an out o range error
C#:
if(word.Contains(letter))[COLOR=#333333][FONT=Consolas]{[/FONT][/COLOR]
[COLOR=#333333][FONT=Consolas]    char[] letters = word.ToCharArray();[/FONT][/COLOR]
[COLOR=#333333][FONT=Consolas]    for (int i = 0; i < letters.Length; i++)[/FONT][/COLOR]
[COLOR=#333333][FONT=Consolas]    {[/FONT][/COLOR]
[COLOR=#333333][FONT=Consolas]        if (letters[i] == letter)[/FONT][/COLOR]
[COLOR=#333333][FONT=Consolas]            labels[i].Text = letter.ToString(); // <-------------------- this creates an out of range error[/FONT][/COLOR]
[COLOR=#333333][FONT=Consolas]    }[/FONT][/COLOR]
[COLOR=#333333][FONT=Consolas]    foreach (Label l in labels)[/FONT][/COLOR]
[COLOR=#333333][FONT=Consolas]        if (l.Text == "_") return;[/FONT][/COLOR]
[COLOR=#333333][FONT=Consolas]    MessageBox.Show("You have won", "Congrats");[/FONT][/COLOR]
[COLOR=#333333][FONT=Consolas]    ResetGame();[/FONT][/COLOR]
[COLOR=#333333][FONT=Consolas]}
[/FONT][/COLOR]

That would indicate that your `labels` array/collection has fewer items in it than your `letters` array. Presumably they are supposed to be the same size.
 

Jonny123

Member
Joined
Oct 2, 2015
Messages
13
Programming Experience
Beginner
Maybe the problem is is that it is set to 0. the error says it has to be a no negative number

C#:
[/COLOR][COLOR=#000000]button1_Click[/COLOR][COLOR=#000000]([/COLOR][COLOR=#00008B]object[/COLOR][COLOR=#000000] sender[/COLOR][COLOR=#000000],[/COLOR][COLOR=#2B91AF]EventArgs[/COLOR][COLOR=#000000] e[/COLOR][COLOR=#000000])[/COLOR][COLOR=#000000]
    [/COLOR][COLOR=#000000]{[/COLOR][COLOR=#000000]
        [/COLOR][COLOR=#00008B]char[/COLOR][COLOR=#000000] letter [/COLOR][COLOR=#000000]=[/COLOR][COLOR=#000000] textBox1[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2B91AF]Text[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2B91AF]ToLower[/COLOR][COLOR=#000000]().[/COLOR][COLOR=#2B91AF]ToCharArray[/COLOR][COLOR=#000000]()[[/COLOR][COLOR=#800000]0[/COLOR][COLOR=#000000]];    //could this be the problem being set to 0?[/COLOR][COLOR=#000000]
        [/COLOR][COLOR=#00008B]if[/COLOR][COLOR=#000000](![/COLOR][COLOR=#00008B]char[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2B91AF]IsLetter[/COLOR][COLOR=#000000]([/COLOR][COLOR=#000000]letter[/COLOR][COLOR=#000000]))[/COLOR][COLOR=#000000]
        [/COLOR][COLOR=#000000]{[/COLOR][COLOR=#000000]
            [/COLOR][COLOR=#2B91AF]MessageBox[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2B91AF]Show[/COLOR][COLOR=#000000]([/COLOR][COLOR=#800000]"You can only submit letters."[/COLOR][COLOR=#000000],[/COLOR][COLOR=#800000]"Error"[/COLOR][COLOR=#000000],[/COLOR][COLOR=#2B91AF]MessageBoxButtons[/COLOR][COLOR=#000000].[/COLOR][COLOR=#000000]OK[/COLOR][COLOR=#000000],[/COLOR][COLOR=#2B91AF]MessageBoxIcon[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2B91AF]Error[/COLOR][COLOR=#000000]);[/COLOR][COLOR=#000000]
            [/COLOR][COLOR=#00008B]return[/COLOR][COLOR=#000000];[/COLOR][COLOR=#000000]
        [/COLOR][COLOR=#000000]}[/COLOR][COLOR=#000000]
        [/COLOR][COLOR=#00008B]if[/COLOR][COLOR=#000000]([/COLOR][COLOR=#000000]word[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2B91AF]Contains[/COLOR][COLOR=#000000]([/COLOR][COLOR=#000000]letter[/COLOR][COLOR=#000000]))[/COLOR][COLOR=#000000]
        [/COLOR][COLOR=#000000]{[/COLOR][COLOR=#000000]
            [/COLOR][COLOR=#00008B]char[/COLOR][COLOR=#000000][][/COLOR][COLOR=#000000] letters [/COLOR][COLOR=#000000]=[/COLOR][COLOR=#000000] word[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2B91AF]ToCharArray[/COLOR][COLOR=#000000]();[/COLOR][COLOR=#000000]
            [/COLOR][COLOR=#00008B]for[/COLOR][COLOR=#000000]([/COLOR][COLOR=#2B91AF]int[/COLOR][COLOR=#000000] i [/COLOR][COLOR=#000000]=[/COLOR][COLOR=#800000]0[/COLOR][COLOR=#000000];[/COLOR][COLOR=#000000] i [/COLOR][COLOR=#000000]<[/COLOR][COLOR=#000000] letters[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2B91AF]Length[/COLOR][COLOR=#000000];[/COLOR][COLOR=#000000] i[/COLOR][COLOR=#000000]++)[/COLOR][COLOR=#000000]
            [/COLOR][COLOR=#000000]{[/COLOR][COLOR=#000000]
                [/COLOR][COLOR=#00008B]if[/COLOR][COLOR=#000000]([/COLOR][COLOR=#000000]letters[/COLOR][COLOR=#000000][[/COLOR][COLOR=#000000]i[/COLOR][COLOR=#000000]][/COLOR][COLOR=#000000]==[/COLOR][COLOR=#000000] letter[/COLOR][COLOR=#000000])[/COLOR][COLOR=#000000]
                    labels[/COLOR][COLOR=#000000][[/COLOR][COLOR=#000000]i[/COLOR][COLOR=#000000]].[/COLOR][COLOR=#2B91AF]Text[/COLOR][COLOR=#000000]=[/COLOR][COLOR=#000000] letter[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2B91AF]ToString[/COLOR][COLOR=#000000]();[/COLOR][COLOR=#808080]//Line gives out of rage error [/COLOR][COLOR=#000000]
            [/COLOR][COLOR=#000000]}[/COLOR][COLOR=#000000]
            [/COLOR][COLOR=#00008B]foreach[/COLOR][COLOR=#000000]([/COLOR][COLOR=#2B91AF]Label[/COLOR][COLOR=#000000] l [/COLOR][COLOR=#00008B]in[/COLOR][COLOR=#000000] labels[/COLOR][COLOR=#000000])[/COLOR][COLOR=#000000]
            [/COLOR][COLOR=#00008B]if[/COLOR][COLOR=#000000]([/COLOR][COLOR=#000000]l[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2B91AF]Text[/COLOR][COLOR=#000000]==[/COLOR][COLOR=#800000]"_"[/COLOR][COLOR=#000000])[/COLOR][COLOR=#00008B]return[/COLOR][COLOR=#000000];[/COLOR][COLOR=#000000]
            [/COLOR][COLOR=#2B91AF]MessageBox[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2B91AF]Show[/COLOR][COLOR=#000000]([/COLOR][COLOR=#800000]"You have won"[/COLOR][COLOR=#000000],[/COLOR][COLOR=#800000]"Congrats"[/COLOR][COLOR=#000000]);[/COLOR][COLOR=#000000]
            [/COLOR][COLOR=#2B91AF]ResetGame[/COLOR][COLOR=#000000]();[/COLOR][COLOR=#000000]
        [/COLOR][COLOR=#000000]}
[/COLOR]
 
Last edited:

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,904
Location
Sydney, Australia
Programming Experience
10+
Zero is a non-negative number. .NET arrays and collections are zero-based so the first element or item is at index zero. If there is no element or item at index zero then that means that your array or collection is empty. If your `labels` array or collection is empty then clearly you didn't create and populate it properly because it is being used as though it is the same size as your `letters` array, which makes sense because each Label is supposed to display a letter.
 

Jonny123

Member
Joined
Oct 2, 2015
Messages
13
Programming Experience
Beginner
I realize Letters and Labels should be equal. Its just that Labels is creating the proper amount of labels for the word. Ive tried differrent variations with math symbols in the loop, and it just results in an improper amount of labels being made. So the question is is how do set letters to the same value?
 
Last edited:

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,904
Location
Sydney, Australia
Programming Experience
10+
Its just that Labels is creating the proper amount of labels for the word.

No, it's not that at all. The issue is that your array does not contain any elements. Whether or not you created the correct number of Label controls isn't really relevant. What matters is whether you put the correct number of Label controls into that array, which you clearly haven't. I could have a dozen eggs but if I don't put any of them into my egg carton then I still have an empty egg carton.
 

Jonny123

Member
Joined
Oct 2, 2015
Messages
13
Programming Experience
Beginner
I have a few questions. what number do I have to put into the array? where do i put it?
I need to know how to do it, as apposed to what i have to do.
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,904
Location
Sydney, Australia
Programming Experience
10+
It's not a case of putting a number into the array. It's a case of creating the array properly in the first place. I've told you more than once that the problem is that you're not creating the array properly and we're now 14 posts into this thread and you are yet to bother showing us where you're trying to do it. We can't read your mind.
 

Jonny123

Member
Joined
Oct 2, 2015
Messages
13
Programming Experience
Beginner
This is the complete code of what i have. Any help would be appriciated
C#:
using System;
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;
using System.Net;


namespace WindowsFormsApplication1
{
    public partial class Form3 : Form
    {
        public Form3()
        {
            InitializeComponent();
        }
        string word = "";
        List<Label> labels = new List<Label>();
        int amount = 0;
        
        enum BodyParts
        {
            Head,
            Left_Eye,
            Right_Eye,
            Mouth,
            Right_Arm,
            Left_Arm,
            Body,
            Left_Leg,
            Right_Leg,


        }
        void drawhangpost()
        {
            Graphics g = panel1.CreateGraphics();
            Pen p = new Pen(Color.Brown, 10);
            g.DrawLine(p, new Point(130, 218), new Point(130, 5));
            g.DrawLine(p, new Point(135, 5), new Point(65, 5));
            g.DrawLine(p, new Point(60, 0), new Point(60, 50));
            //DrawBodyPart(BodyParts.Head);//just for show
            //DrawBodyPart(BodyParts.Left_Eye);
            //DrawBodyPart(BodyParts.Right_Eye);
            //DrawBodyPart(BodyParts.Mouth);
            //DrawBodyPart(BodyParts.Right_Arm);
            //DrawBodyPart(BodyParts.Left_Arm);
            //DrawBodyPart(BodyParts.Body);
            //DrawBodyPart(BodyParts.Left_Leg);
            //DrawBodyPart(BodyParts.Right_Leg);
            //MessageBox.Show(GetRandomWord());
        }
        void DrawBodyPart(BodyParts bp)
        {
            Graphics g = panel1.CreateGraphics();
            Pen p = new Pen(Color.Blue, 2);
            if (bp == BodyParts.Head)
                g.DrawEllipse(p, 40, 50, 40, 40);
            else if (bp == BodyParts.Left_Eye)
            {
                SolidBrush s = new SolidBrush(Color.Black);
                g.FillEllipse(s, 50, 60, 5, 5);
            }
            else if (bp == BodyParts.Right_Eye)
            {
                SolidBrush s = new SolidBrush(Color.Black);
                g.FillEllipse(s, 63, 60, 5, 5);
            }
            else if (bp == BodyParts.Mouth)
            {
                g.DrawArc(p, 50, 60, 20, 20, 45, 90);
            }
            else if (bp == BodyParts.Body)
                g.DrawLine(p, new Point(60, 90), new Point(60, 170));
            else if (bp == BodyParts.Left_Arm)
                g.DrawLine(p, new Point(60, 100), new Point(30, 85));
            else if (bp == BodyParts.Right_Arm)
                g.DrawLine(p, new Point(60, 100), new Point(90, 85));
            else if (bp == BodyParts.Left_Leg)
                g.DrawLine(p, new Point(60, 170), new Point(30, 190));
            else if (bp == BodyParts.Right_Leg)
                g.DrawLine(p, new Point(60, 170), new Point(90, 190));
        }
        void MakeLables()
        {
            word = GetRandomWord();
            char[] chars = word.ToCharArray();
            int between = 330 / chars.Length - 1;
            for (int i = 0; i < chars.Length - 1; i++)//for(int i = 0; i < chars.Length - 1; i++)
            {
                labels.Add(new Label());
                labels[i].Location = new Point((i * between) + 10, 80);
                labels[i].Text = "_";
                labels[i].Parent = groupBox2;
                labels[i].BringToFront();
                labels[i].CreateControl();
            }
            label1.Text = "Word Length: " + (chars.Length - 1).ToString();
        }
        string GetRandomWord()
        {
            WebClient wc = new WebClient();
            string wordList = wc.DownloadString("https://raw.githubusercontent.com/Tom25/Hangman/master/wordlist.txt");
            string[] words = wordList.Split('\n');
            Random ran = new Random();
            return words[ran.Next(0, words.Length - 1)];
        }
        private void form3_shown(object sender, EventArgs e)
        {
            drawhangpost();
            MakeLables();
        }


        private void button1_Click(object sender, EventArgs e)
        {
            char letter = textBox1.Text.ToLower().ToCharArray()[0];
            if (!char.IsLetter(letter))
            {
                MessageBox.Show("You can only submit letters.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (word.Contains(letter))
            {
                char[] letters = word.ToCharArray();
                for (int i = 0; i < letters.Length; i++)//for (int i = 0; i < letters.Length; i++)
                {
                    if (letters[i] == letter)
                        //labels.Add(letter.ToString());//edit
                        labels[i].Text = letter.ToString();
                }
                foreach (Label l in labels)
                if (l.Text == "_") return;
                MessageBox.Show("You have won", "Congrats");
                ResetGame();
            }
            else
            {
                //MessageBox.Show("The letter you guessed is wrong", "Sorry");
                label2.Text += " " + letter.ToString() + ",";
                DrawBodyPart((BodyParts)amount);
                amount++;
                if (amount == 9)
                {
                    MessageBox.Show("Sorry but you lost, the word was " + word);
                    ResetGame();
                }
            }
        }
        void ResetGame()
        {
            amount = 0;// testing not sure
            Graphics g = panel1.CreateGraphics();
            g.Clear(panel1.BackColor);
            GetRandomWord();
            MakeLables();
            drawhangpost();
            label2.Text = "Missed: ";
            textBox1.Text = "";
        }


        private void button2_Click(object sender, EventArgs e)
        {
            if (textBox2.Text == word)
            {
                MessageBox.Show("You Have won", "Congrats");
                ResetGame();
            }
            else
            {
                MessageBox.Show("The word you guest was wrong", "Sorry");
                DrawBodyPart((BodyParts)amount);
                amount++;
                if (amount == 9)
                {
                    MessageBox.Show("Sorry but you lost, the word was " + word);
                    ResetGame();
                }
            }
        }
    }
 }
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,904
Location
Sydney, Australia
Programming Experience
10+
Noone wants to see all the code. What we want to see is the relevant code. I've told you numerous times that the issue is that you're not creating and populating the array of Labels properly. Obviously, where you are creating and populating the array of Labels is the relevant code.
 

Jonny123

Member
Joined
Oct 2, 2015
Messages
13
Programming Experience
Beginner
Here is the MakeLables function.

C#:
void MakeLables()
        {
            word = GetRandomWord();
            char[] chars = word.ToCharArray();
            int between = 330 / chars.Length - 1;
            for (int i = 0; i < chars.Length - 1; i++)
            {
                labels.Add(new Label());
                labels[i].Location = new Point((i * between) + 10, 80);
                labels[i].Text = "_";
                labels[i].Parent = groupBox2;
                labels[i].BringToFront();
                labels[i].CreateControl();
            }
            label1.Text = "Word Length: " + (chars.Length - 1).ToString();
        }
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,904
Location
Sydney, Australia
Programming Experience
10+
On the face of it, that looks OK. I suggest that you debug your code. Step through that method and make sure that `labels` is populated the way you expect and then debug the section that's generating the exception and make sure that `labels` is still populated the way you expect. I can't see anything obvious just by reading the code, which is exactly why it's important to debug and actually watch the code in action.
 

Jonny123

Member
Joined
Oct 2, 2015
Messages
13
Programming Experience
Beginner
One thing i notice is that "MakeLabels" is misspelled. When the module is called it is misspelled also. I'm not sure if that effect anything.

C#:
void MakeLables()
 
Top Bottom