9 Replies - 625 Views - Last Post: 04 March 2013 - 11:28 AM Rate Topic: -----

#1 TommoUK  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 12
  • Joined: 22-February 13

Using a list within Class + Scope issues

Posted 04 March 2013 - 07:48 AM

Alright I have been avoiding this problem for a while now but it's got to the point where I need to sort out the scopes of my code before I can continue, I am quite new to C# programming so any help on bad conventions i've been using would be nice

Here is my current Player class (I know you can use "Name {get; set}" for example, However I was having some problems defining, Below are my 2 classes, My top trumps class (10 top trump cards are later created), and a player class.

          //Top trumps class, layout of top trump card defined in here
        public class TopTrumps 
        {
            public int height;
            public int length;
            public int speed;
            public int CardID;

            public TopTrumps(int a, int b, int c, int d)  
            {
                this.height = a;   
                this.length = b;
                this.speed = c;
            }
        }

        // The player class, Containing player name, Score etc.
        public class Player
        {

            public string Name;
            public int Score;
            public bool Turn;
       //     public List<TopTrumps> PlayerDeck = new List<TopTrumps>();


            public Player(string a, int b, bool c)
            {
                this.Name = a;
                this.Score = b;
                this.Turn = c;
         //       this.PlayerDeck = d;
            }
        }


My aim of the player class is to store the Name, Score, Turn as well as a deck of 5 cards for both the player, Then the computer, In the form of a list. I have no problem doing this outside of the class such as here
                /////////////////////////////
            // Create computer card deck
            /////////////////////////////

            Player Computer = new Player("Computer", 0, true);  //Create new player

            List<TopTrumps> ComputerDeck = new List<TopTrumps>();

            ComputerDeck = Trumps.GetRange(5, 5);

            for (int i = 0; i <ComputerDeck.Count; i++)
                {
                    listBox3.Items.Add("COMP Card [" + i + "] : " + ComputerDeck[i].height);
                 }
            listBox3.Items.Add(Computer.Name);


However when I try to access anything to do with the player outside of the function
"public void DealCards_Click(object sender, EventArgs e)"
Which is what the above code resides in, Then I will always get an error that it cannot be accessed. For example on the button I have posted below I am given the error "Error 1 The name 'Computer' does not exist in the current context"
            private void button1_Click(object sender, EventArgs e)
        {
            Player1.Name = PlayerName.Text;
        }


Any help on how to organise this code properly would help a huge amount can't really continue until I can work out how to break down my program, and get a list working within a class, I have posted below a full source for if you need to get better understanding of my program, Thanks a lot

-Tom

  

    public partial class Game : Form
    {
        

        //Top trumps class, layout of top trump card defined in here
        public class TopTrumps 
        {
            public int height;
            public int length;
            public int speed;
            public int CardID;

            public TopTrumps(int a, int b, int c, int d)  //Pass height length and speed as arguements to class, Example 'TopTrumps(10,10,20);'
            {
                this.height = a;   // Set objects height to the parsed value of a
                this.length = b;
                this.speed = c;
                this.CardID = d;

            }
        }

        // The player class, Containing player name, Score etc.
        public class Player
        {

            public string Name;
            public int Score;
            public bool Turn;
       //     public List<TopTrumps> PlayerDeck = new List<TopTrumps>();


            public Player(string a, int b, bool c)
            {
                this.Name = a;
                this.Score = b;
                this.Turn = c;
         //       this.PlayerDeck = d;
            }
        }

        public Player player1 = new Player("New Player", 0, true);  //Create new player

        public Game()
        {
            InitializeComponent();
        }


        private void Hide_Click(object sender, EventArgs e)
        {
            Form1 MainScreen = new Form1();
            this.Hide();
            MainScreen.ShowDialog();

        }

        public void DealCards_Click(object sender, EventArgs e)
        {

            List<TopTrumps> Trumps = new List<TopTrumps>(); //Create a list of deck of top trumps
            // We can now easily access each top trump card variables, For example 'Trumps[1].height = 5', will modify the 2nd cards height

            Trumps.Add(new TopTrumps(10, 20, 50,1));   //Add each top trump card (10 of them) to the newly created list
            Trumps.Add(new TopTrumps(15, 50, 40,2));      //Format = (height, Length, speed, CardID)
            Trumps.Add(new TopTrumps(6, 4, 20,3));
            Trumps.Add(new TopTrumps(11, 20, 30,4));
            Trumps.Add(new TopTrumps(10, 70, 25,5));
            Trumps.Add(new TopTrumps(10, 14, 35,6));
            Trumps.Add(new TopTrumps(20, 80, 40,7));
            Trumps.Add(new TopTrumps(10, 44, 45,8));
            Trumps.Add(new TopTrumps(13, 67, 30,9));
            Trumps.Add(new TopTrumps(14, 12, 20,10));

            /////////////////////
            //Shuffle routine
            /////////////////////

            Random random = new Random(); //Create new random number
            int n = Trumps.Count;   //Create variable of Trump decks length 
            //    listBox1.Items.Add(n);

            while (n > 1)
            {
                n--;    //n immedietely decreased
                int k = random.Next(n + 1);  //Create a random number between 0 and 9 (The adressable range of the list)
                TopTrumps nth_value = Trumps[k];     //Store random number index contents, in temp storage 
                Trumps[k] = Trumps[n];           //Swap the random number index with the nth index (On 1st loop, Random number index will swap values with 10th card)
                Trumps[n] = nth_value;       //Set the nth card to the random numbers index contents
            }

            for (int i = 0; i < Trumps.Count; i++)
            {
                listBox2.Items.Add("Card [" + i + "] : " + Trumps[i].CardID);
            }


            /////////////////////////////
            // Create player 1 card deck
            /////////////////////////////


            List<TopTrumps> PlayerDeck = new List<TopTrumps>();
            listBox1.Items.Add(PlayerDeck.Count);
            PlayerDeck = Trumps.GetRange(0, 5);
            listBox1.Items.Add(PlayerDeck.Count);

            for (int i = 0; i < PlayerDeck.Count; i++)
            {
                listBox1.Items.Add("PLAYER Card [" + i + "] : " + PlayerDeck[i].height);
            }

            /////////////////////////////
            // Create computer card deck
            /////////////////////////////

            Player Computer = new Player("Computer", 0, true);  //Create new player

            List<TopTrumps> ComputerDeck = new List<TopTrumps>();

            ComputerDeck = Trumps.GetRange(5, 5);

            for (int i = 0; i <ComputerDeck.Count; i++)
                {
                    listBox3.Items.Add("COMP Card [" + i + "] : " + ComputerDeck[i].height);
                 }
            listBox3.Items.Add(Computer.Name);

            /////////////////////////
            //Initial deck set up
            /////////////////////////

            CardID.Text = "Card ID: " + PlayerDeck[0].CardID;
            Height.Text = "Height: " + PlayerDeck[0].height;
            Length.Text = "Length: " + PlayerDeck[0].length;
            Speed.Text = "Speed: " + PlayerDeck[0].speed;

            listBox1.Items.Clear();

            listBox1.Items.Add("Card Number: "+PlayerDeck[0].CardID);
            listBox1.Items.Add("");

            listBox1.Items.Add("Height: " + PlayerDeck[0].height);
            listBox1.Items.Add("length: " + PlayerDeck[0].length);
            listBox1.Items.Add("speed: " + PlayerDeck[0].speed);

            
        }

     


        private void button1_Click(object sender, EventArgs e)
        {
            Computer.Name = PlayerName.Text;
        }

        private void PlayCard_Click(object sender, EventArgs e)
        {

            bool PlayerWon = false;

            if (Height.Checked)
            {
            //    PlayerDe
            }


        }

    }
}



Is This A Good Question/Topic? 0
  • +

Replies To: Using a list within Class + Scope issues

#2 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5535
  • View blog
  • Posts: 11,861
  • Joined: 02-June 10

Re: Using a list within Class + Scope issues

Posted 04 March 2013 - 08:02 AM

Quote

My aim of the player class is to store the Name, Score, Turn as well as a deck of 5 cards for both the player,

Already a bad start. A turn and a deck of cards is not part of a Player. They are parts of a game. What you have here is some related stuff that you are trying to force into being part of the same object: Like saying that a service station gas pump is part of a car just because it is loosely related to a car.There is a tutorial on classes linked in my signature block. I think it would help you better envision how to break down what an object should and should not include.

You have a lot of code here for suddenly realizing you should have planned better. That's part of learning and why we say that building is the best way to learn. I'm sure you've realized tht next time you need to spend a lot more time in front of the white board organizing and planning and designing your classes, before you start typing. If not, read the article in my signature block "I don't know where to start"

Get away from these primitive arrays. Use a List<> or one of the more advanced collections so you can take advantage of the additional capabilities.

Lines 129-131 ... Wow, 1970's C style comments. Read up on #region

Give your controls decent names before using them. listbox1 and button4 sucks.


Some of my common tips (some may apply more than others to your specific style):
  • Take the extra 3 seconds to rename your controls each time you drag them onto a form. The default names of button1, button2... button54 aren't very helpful. If you rename them right away to something like btnOk, btnCancel, btnSend etc. it helps tremendously when you make the methods for them because they are named after the button by the designer.btnSend_Click(object sender, eventargs e) is a lot easier to maintain than button1_click(object sender, eventargs e)

  • You aren't paying for variable names by the byte. So instead of variables names of a, b, c go ahead and use meaningful names like index, timeOut, row, column and so on. You should avoid 'T' for the timer. Amongst other things 'T' is commonly used throughout C# for Type and this will lead to problems. There are naming guidelines you should follow so your code confirms to industry standards. It makes life much easier on everyone around you, including those of us here to help. If you start using the standards from the beginning you don't have to retrain yourself later.
    You might want to look at some of the naming guidelines. Its a lot easier to start with good habits than to break bad habits later and re-learn.



  • Don't use your GUI objects as your variable. In other words don't keep referencing TextBox4.Text everyplace. TextBox4.Text is not a variable or property. The GUI is on its own thread so as soon as you start doing multi-threading you're screwed because your worker thread can't access the GUI elements. Use properties.

  • Try to avoid having work actually take place in GUI control event handlers. It is better to have the GUI handler call other methods so those methods can be reused and make the code more readable. This is also how you can send parameters rather than use excessive global variables. Get in this habit even if you are using WinForms because WPF works a lot under the idea of "commands" and this will get you working towards that. Think of each gester, control click, menu option etc. as a command to do something such as a command to SAVE. It doesn't matter where the command comes from, all sources should point at the same target to do the actual saving.
    Spoiler


  • Don't replace lines of code that don't work. Instead comment them out and put your new attempts below that. This will keep you from re-trying the same ideas over and over. Also, when you come back to us saying "I've tried this 100 different ways and still can't get it", we can actually see what you tried. So often a failed attempt is very very close and just needs a little nudge in the right direction. So if we can say "See what you did in attempt 3... blah blah" it helps a lot

    Spoiler

    If you are using Visual Studio you can select a block of lines and hit control+k control+c (Kode Comment) to comment it out. control+k control+u (Kode Uncomment) to uncomment a selected block.


  • You have to program as if everything breaks, nothing works, the cyberworld is not perfect, the attached hardware is flakey, the network is slow and unreliable, the harddrive is about to fail, every method will return an error and every user will do their best to break your software. Confirm everything. Range check every value. Make no assumptions or presumptions.

Was This Post Helpful? 2
  • +
  • -

#3 TommoUK  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 12
  • Joined: 22-February 13

Re: Using a list within Class + Scope issues

Posted 04 March 2013 - 08:12 AM

Wow some really useful help there thank you, I come from a background of pascal so excuse my commenting style aha. and the poor button / lists labelling convention is not permanent, they are all tests as I am still learning.

One thing I don't understand is you wrote 'Get away from these primitive arrays. Use a List<> or one of the more advanced collections so you can take advantage of the additional capabilities. ' From what I understand I am making good use of lists, my entire program works and compiles and the main logic is made from lists.. however I am now having problems implementing a list into my class.

From what I read would I be right in saying to split my creation of the computer and player deck into a function, lets say InitialDeal() for example, Then I should be able to use reference to the list from any other button, scrapping the idea of storing a players card within the player class?
Was This Post Helpful? 0
  • +
  • -

#4 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5535
  • View blog
  • Posts: 11,861
  • Joined: 02-June 10

Re: Using a list within Class + Scope issues

Posted 04 March 2013 - 08:45 AM

061            List<TopTrumps> Trumps = new List<TopTrumps>(); //Create a list of deck of top trumps

Yep, my mistake. You are using a List<>. But you're using it like an array. There were just so many places you're doing trump[i] that I though you were using an array and not a List<>

I'm not sure you're aware of the foreach{} type of loop that is commonly used for collections. I think loops like this one
123            for (int i = 0; i <ComputerDeck.Count; i++)
124                {
125                    listBox3.Items.Add("COMP Card [" + i + "] : " + ComputerDeck[i].height);
126                 }


probably come from your Pascal background. I see the same stuff from my assembly language era boss. Its just habit and being used to micromanaging things. Its habit to think you have to refer to each index specifically. The entire "objects" way of looking at things takes a while to sink in.

Normally we would do something like
foreach (Card c in ComputerDeck)
{
    myListbox.Items.Add(c);
}

Yes its simplier than your R&D method. I realize that your list is to confirm all the data of that card including the index in the array. So my example may not suite your exact need, but I thought you might want to see how we can do things without having to reference the exact index.

Quote

Then I should be able to use reference to the list from any other button

This sentence worries me. Are you saying you want to pass around pointers? We tend to avoid pointers in C#. They are not commonly used. This is not C or C++. We usually pass objects. Which technically are reference types and technically is a form of passing a pointer but all that is under the hood. If you want to pass a List<> as a parameter to a method then just pass the List<>: Don't make a pointer to the List<>

Yes make methods. We love methods. Lots of methods that have a single purpose in life with no side affects. By that I mean...
A LoadSettings() method should just load the settings to an object. It should NOT also change the view, update the GUI and make a fun beeping noise. A Beep() method should do a beep. An UpdateGUI() method should update the GUI. At most you would have one method that just calls the others. Notice how this controlling method is concise, easy to read and more importantly easy to alter the sequence of events.
void Start()
{
   if (LoadSettings() == true)
   {
       UpdateGUI();
       PlayFunnyNoise();
       StatusBarText = "Ready";
   }
   else
   {
       PlayBadNoise();
       StatusBarText = "Failed";
   }
}



What's with this .Height and .Length properties in your Card class?
That's not for displaying the card is it? You're not explicitly setting the size of the card as displayed on screen this way, are you?
Was This Post Helpful? 0
  • +
  • -

#5 TommoUK  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 12
  • Joined: 22-February 13

Re: Using a list within Class + Scope issues

Posted 04 March 2013 - 09:07 AM

The list structure is new to me, I assumed working with it the same way as arrays was the propper way, Is my understanding correct that a list is just an array except with the ability to hold multiple data types, I am handling it the same way I would a 'RECORD' in pascal, perhaps this is a misunderstanding on my behalf.

Also I have used that for each method before but didn't realise I could also use it to iterate through a deck without the need to count, thanks for that code snippet.

I think I may have used the term reference too broadly but your information was useful. My aim is too create a top trump deck (a card, with for example 5 characteristics per card), The height + length are just example variable names until I have my proper trump deck sorted out, It could be weight or colour, am I doing this correctly?

Also may I just add I have been reading through your tutorials and they are honestly a life line for beginner programmers and advanced alike, nice to have some good information on some of the c# programming foundations to build upon. Particularly liked your debugging one, As you said in it it's the kind of stuff you don't get taught (In my case i'm at uni, having also took computing in 6th form) but is essential if you don't want to be looking at that once line of code for hours like I find myself doing right now.
Was This Post Helpful? 0
  • +
  • -

#6 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5535
  • View blog
  • Posts: 11,861
  • Joined: 02-June 10

Re: Using a list within Class + Scope issues

Posted 04 March 2013 - 10:11 AM

A List<> has several other features. It is IEnumerable compliant so you can do the foreach{} block as I mentioned. You can do many other things with it that an array cannot do such as .AddRange, .InsertAt, .RemoveAt and so on.

Glad the tutorials are helping. Right now the site is undergoing some updates so there is no image uploading available. As you may have noticed I like my screen shots! <laugh> So until that is resolved I won't be doing any more.

You seem to be doing the card class kinda right and kinda not.
02 public class TopTrumps
03 {
04     public int height;
05     public int length;
06     public int speed;
07     public int CardID;
08 
09     public TopTrumps(int a, int b, int c, int d) 
10     {
11         this.height = a;  
12         this.length = b;
13         this.speed = c;
14     }
15 }


You have made fields (variables) of height, length, speed - and made them public. What you want to do is make properties that are public. Properties are like advanced variables that have a get and set method inside them. But they are treated differently under the hood. You said you were reading my tutorials, so the one on properties has more details.
Was This Post Helpful? 0
  • +
  • -

#7 AdamSpeight2008  Icon User is offline

  • MrCupOfT
  • member icon


Reputation: 2264
  • View blog
  • Posts: 9,469
  • Joined: 29-May 08

Re: Using a list within Class + Scope issues

Posted 04 March 2013 - 10:49 AM

Sorry I thought you one about .ForEach which isn't on IEnumerable< T > but List<T>.
Was This Post Helpful? 0
  • +
  • -

#8 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5535
  • View blog
  • Posts: 11,861
  • Joined: 02-June 10

Re: Using a list within Class + Scope issues

Posted 04 March 2013 - 10:56 AM

View PostAdamSpeight2008, on 04 March 2013 - 11:49 AM, said:

Sorry I thought you one about .ForEach which isn't on IEnumerable< T > but List<T>.


IEnumerable is an interface, not a class. List<> impliments the IEnumerable interface. That's how it gets the ability to do foreach. Yes, .foreach is a method in List<T> - but the ability to work through the list in that manner comes IEnumerable.

MSDN PAGE said:

[SerializableAttribute]
public class List<T> : IList<T>, ICollection<T>, 
	IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, 
	IEnumerable

This post has been edited by tlhIn`toq: 04 March 2013 - 10:58 AM

Was This Post Helpful? 0
  • +
  • -

#9 AdamSpeight2008  Icon User is offline

  • MrCupOfT
  • member icon


Reputation: 2264
  • View blog
  • Posts: 9,469
  • Joined: 29-May 08

Re: Using a list within Class + Scope issues

Posted 04 March 2013 - 11:08 AM

I know that! Eg the method .Select is an extension method (which comes via the static class System.Linq.Enumerable) on the interface IEnumerable<T>.
Was This Post Helpful? 0
  • +
  • -

#10 AdamSpeight2008  Icon User is offline

  • MrCupOfT
  • member icon


Reputation: 2264
  • View blog
  • Posts: 9,469
  • Joined: 29-May 08

Re: Using a list within Class + Scope issues

Posted 04 March 2013 - 11:28 AM

To further that you don't even need to implement IEnumerable<T> to get the LINQ extension methods.
All that is required is a of the method signatures. Current MoveNext
Even the name of the methods can be different.

vb.net
Spoiler

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1