-1

Background: I am coding for a puzzle game for my school Assignment. I have a puzzle game saved in a text file. Now I'm loading it to the form by reading from the text file saved. In the text file, the first two lines are total rows and columns of tiles (2d PictureBoxes) and the following lines are row number, column number, and image index of each PictureBox.

Approach: I am using a two-dimensional array of Tile (custom control class that inherits from PictureBox Class) references and using a nested loop to read each tile's (PictureBoxes') information ie. row number, column number, and image index. The tile class has properties named Row, Column, and TileType. I am trying to assign value to the property inside the nested loop.

//Tile Class
public class Tile : PictureBox
{
   private int row;
   private int column;
   private int tileType;
   public int Row{get; set;}
   public int Column { get; set; }
   public int TileType { get; set; }
}
public Tile[,] LoadPictureBoxes(string filename)
{
  Tile[,] tile;
  //Read the file 
  if (System.IO.File.Exists(filename) == true)
  {
    StreamReader load = new StreamReader(filename);
    int nRow = int.Parse(load.ReadLine());
    int nCol = int.Parse(load.ReadLine());
    //declare two dimensional array of Tile Reference
    tile = new Tile[nRow, nCol];
    //using nested loop to read each tile's information
    for(int i=0; i < nRow; i++)
    {
      for(int j=0; j < nCol; j++)
      {
        tile[i, j].Row = int.Parse(load.ReadLine());   //gets an exception here
        tile[i, j].Column = int.Parse(load.ReadLine());  //gets an exception here
        tile[i, j].TileType = int.Parse(load.ReadLine());  //gets an exception here
      }
    }
    load.Close();
    return tile;
  }

  return new Tile[0, 0];
}

private void loadToolStripMenuItem_Click(object sender, EventArgs e)
{
  DialogResult r = dlgLoad.ShowDialog();

  switch (r)
  {
  case DialogResult.Cancel:
    break;
  case DialogResult.OK:
    string fileName = dlgLoad.FileName;
    Tile[,] tile = LoadPictureBoxes(fileName);
    int leftPos = 100;
    int topPos = 0;
    int height = 100;
    int width = 100;
    int rowCount = 0;
    int columnCount = 0;
    //loop after each row of picturebox is generated
    for (int rowNumber = 0; rowNumber < tile.GetLength(0); ++rowNumber)
    {
      ++rowCount;
      for (int colNumber = 0; colNumber < tile.GetLength(1); ++colNumber)
      {
        ++columnCount;
        Tile pic = new Tile();
        pic.Left = leftPos;
        pic.Top = topPos;
        pic.Height = height;
        pic.Width = width;
        pic.BorderStyle = BorderStyle.Fixed3D;
        pic.SizeMode = PictureBoxSizeMode.StretchImage;
        tile[rowCount, columnCount] = pic;
        pnlLoadGame.Controls.Add(pic);
        leftPos += width;
      }
      topPos += height;
    }
    pnlLoadGame.Size = new Size(100 * rowCount, 100 * columnCount);
    pnlGameScore.Left = 100 + 100 * columnCount;
    break;
  }
}

Problem: I get an exception at runtime: System.NullReferenceException: 'Object reference not set to an instance of an object.' Is there an alternative way to assign value to the property of custom PictureBox?

CodeCide
  • 45
  • 10
  • This answers your question: [What is a NullReferenceException, and how do I fix it?](https://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it). Your question has nothing to do with the forms designer; you may remove the tag. You should also use the **[Step Debugger](https://msdn.microsoft.com/en-us/library/y740d9d3.aspx)** to examine the values of `i` and `j` when the exception happens. Compare to `nRow` and `cCol` – Ňɏssa Pøngjǣrdenlarp Nov 02 '19 at 22:40
  • I'm not asking for a fix. I'm asking for an alternative. But thanks for the suggestion. – CodeCide Nov 02 '19 at 22:43
  • The problem (and exception) is from processing the file. Changing how you process properties wont change that. You do not need the array at all - the PB **must** be added to the form's controls collection to be seen/used. Since the PB control has a Row and Col property, you can find them in the collection using those. Create the PBs and add them to the controls collection in that loop – Ňɏssa Pøngjǣrdenlarp Nov 02 '19 at 22:51
  • @ŇɏssaPøngjǣrdenlarp Values of "i and j are 0 at the point as expected. I don't know the fix. Is there an alternative way to assign value to the properties so that I can read them later? – CodeCide Nov 02 '19 at 22:52
  • @ŇɏssaPøngjǣrdenlarp I need an array to iterate through tiles easily. – CodeCide Nov 02 '19 at 23:11

1 Answers1

1

Your problem happens because even if you defined the array as tile = new Tile[nRow, nCol];, you still need to initialize its elements before using them. Like so:

tile[i, j] = new Tile();

After that, then it's safe to do these three lines:

tile[i, j].Row = int.Parse(load.ReadLine());
tile[i, j].Column = int.Parse(load.ReadLine());  
tile[i, j].TileType = int.Parse(load.ReadLine());  
Javier Silva Ortíz
  • 2,864
  • 1
  • 12
  • 21