简体   繁体   中英

How to serialize/deserialize an object matrix to/from xml in C#?

I have an assignment to save and load a Minesweeper board. I'm having issues saving the board matrix. These are my Minesweeper properties:

[XmlIgnore]
public Tile[,] Grid { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public int NumberOfMines { get; set; }

Tile properties:

public int X { get; set; }
public int Y { get; set; }
public int NeighbourMines { get; set; }
public bool IsMine { get; set; }
public bool IsRevealed { get; set; }
public bool IsFlagged { get; set; }

I tried something like this:

public List<Tile> ListFromMatrix
{
    get
    {
        List<Tile> temp = new List<Tile>(Height * Width);
        for (int i = 0; i < Height; i++)
            for (int j = 0; j < Width; j++)
                temp.Add(Grid[i, j]);
        return temp;
    }
    set
    {
        //Grid = new Tile[Height, Width];
        int it = 0;
        for (int i = 0; i < Height; i++)
            for (int j = 0; j < Width; j++)
                Grid[i, j] = value[it++];
    }
}

Saving into the file works fine, but loading from it causes an exception. And I really don't know how to debug it since the exception is thrown at:

//this.Game is the Minesweeper reference in the main form
this.Game = (Game)xs.Deserialize(fileStream);

Any help is appreciated!

EDIT: This is the exception

System.InvalidOperationException: 'There is an error in XML document (7, 4). Inner Exception 1: NullReferenceException: Object reference not set to an instance of an object.

EDIT2: Save code

SaveFileDialog sfd = new SaveFileDialog();
            if (sfd.ShowDialog() == DialogResult.OK)
            {
                using (FileStream fs = new FileStream(sfd.FileName, FileMode.Create))
                {
                    XmlSerializer xs = new XmlSerializer(typeof(Game));
                    xs.Serialize(fs, this.Game);
                }
            }

EDIT3: Here are the xml contents https://pastebin.com/0vkxQC5A

EDIT4: Thank you for trying but nothing works with this so I will just rewrite the code to use a list instead of the matrix.

You might try changing your set like so:

set
{
    var height = value.Max(t=>t.Y);
    var width = value.Max(t=>t.X);
    Grid = new Tile[height, width];
    foreach(var tile in value)
    {
      Grid[tile.Y,tile.X]=tile;
    }
}

You probably don't want to use the height and width properties from the game object, because then you would need to assume those get set prior to this property. Might as well just calculate them yourself. And while you are at it, might as well just change get as well, and then throw away Height/Width, or change them to actually pull the current width/height of the Grid:

get
{
    var temp = new List<Tile>(Grid.Length);
    for (int i = 0; i < Grid.GetLength(0); i++)
        for (int j = 0; j < Grid.GetLength(1); j++)
            temp.Add(Grid[i, j]);
    return temp;
}

It appears the error is in deserializing your property ListFromMatrix.

public List<Tile> ListFromMatrix {get; set;}


// when it comes time to serialize
ListFromMatrix = CreateList();
using (FileStream fs = new FileStream(sfd.FileName, FileMode.Create))
{
    XmlSerializer xs = new XmlSerializer(typeof(Game));
    xs.Serialize(fs, this.Game);
}

private List<Tile> CreateList()
{
    var temp = new List<Tile>(Height * Width);
    for (int i = 0; i < Height; i++)
        for (int j = 0; j < Width; j++)
            temp.Add(Grid[i, j]);
    return temp;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM