C# Instances share same values

81 Views Asked by At

programming student here, quite new to what i am about to ask but i'm sure you people will know. I have to make a game where several pictureboxes are created using an array. I also have to make a class that has a health variable of 5. When you click on one of the pictureboxes, its health has to go down by 1. I am as far as this, but the problem is that the health variable is shared by all pictureboxes, where in reality I want every picturebox to have it's own health.

This is my code:

public partial class Form1 : Form
{

    Invader monster; // Invader is the name of the class
    Random rand = new Random();
    PictureBox[] pb = new PictureBox[5];

    private void Spawner()
    {
        for (int i = 0; i < 5; i++)
        {
            this.monster = new Invader();
            this.pb[i] = new PictureBox();
            this.pb[i].Name = "pb" + i.ToString();
            this.pb[i].Location = new Point(rand.Next(10, 300), monster.LocY);
            this.pb[i].BackgroundImageLayout = ImageLayout.Stretch;
            this.pb[i].BackgroundImage = Image.FromFile(@"Path");
            this.pb[i].BackColor = Color.Transparent;
            this.pb[i].Size = new System.Drawing.Size(40, 30);
            this.Controls.Add(this.pb[i]);
            this.pb[i].Click += this.Form1_Click;
        }
    }

    private void Form1_Click(object sender, EventArgs e)
    {
        PictureBox currentpicturebox = (PictureBox)sender;

        this.monster.HealthDown();
        if (this.monster.Health == 0)
        {
            currentpicturebox.Dispose();
        }

    }

and my class:

class Invader
{
    // Fields
    private int health;

    // Properties
    public int Health
    {
        get { return this.health; }
    }

    // Constructor
    public Invader()
    {
        this.health = 5;
    }
    // Methods
    public void HealthDown()
    {
            this.health -= 1;
    }

Lets say i click 1 picture box 4 times, and click another one 1 time. With this code the picturebox last clicked on will be disposed. Any ideas on how to fix this?

1

There are 1 best solutions below

1
fruggiero On BEST ANSWER

Your Invader monster is an instance variable of Form1 and in your method Spawner() inside the for loop you are reassigning it again every time: this.monster = new Invader();

Basically when you click on a picturebox (isn't different what) in your Form1_Click method happen that is everytime your last monster istance that get it's health down and not the supposed one.

In order to fix this you can:

  • transform monster in an array of Invader object instead of an Invader object, the number of elements must be the same as the number of pictureboxes
  • foreach picturebox assign as a Tag the index of the corrispondent Invader on the monster array

Here an example:

public partial class Form1 : Form
{
    // EDIT - Become an array
    Invader[] monster = new Invader[5]; // Invader is the name of the class
    Random rand = new Random();
    PictureBox[] pb = new PictureBox[5];

    private void Spawner()
    {
        for (int i = 0; i < 5; i++)
        {
            this.monster[i] = new Invader(); // EDIT
            this.pb[i] = new PictureBox();
            this.pb[i].Name = "pb" + i.ToString();
            this.pb[i].Location = new Point(rand.Next(10, 300), monster.LocY);
            this.pb[i].BackgroundImageLayout = ImageLayout.Stretch;
            this.pb[i].BackgroundImage = Image.FromFile(@"Path");
            this.pb[i].BackColor = Color.Transparent;
            this.pb[i].Size = new System.Drawing.Size(40, 30);
            this.Controls.Add(this.pb[i]);
            this.pb[i].Click += this.Form1_Click;
            this.pb[i].Tag = i; // EDIT - Added tag assignation
        }
    }

    private void Form1_Click(object sender, EventArgs e)
    {
        PictureBox currentpicturebox = (PictureBox)sender;
        this.monster[(int)currentpicturebox.Tag].HealthDown(); // EDIT
        if (this.monster[(int)currentpicturebox.Tag].Health == 0) //EDIT
        {
            currentpicturebox.Dispose();
        }
    }