Resolved How to draw maze from .CSV file?

reddec85

New member
Joined
Oct 28, 2021
Messages
4
Programming Experience
3-5
Keep in mind I'm still relatively new to both Visual Studio, and C#, but I'm stuck on that seemed like a pretty simple project at first.
I'm trying to read specific characters from a .CSV file, and turn it into a maze done with simple rectangles. I've gotten completely stuck, and after a few hours of headscratching, I'm not even sure I know where I'm at anymore. Any help is appreciated. I've attached the needed code. If you need any more information or some files
The main .cs file:
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.IO;



namespace Drawing
{
    public partial class Form1 : Form
    {
        private string[,] maze = { { "X", "X", "X", "X" }, { "X", " ", " ", "X" }, { "X", "X", "X", "X" } };
        private Graphics canvas;
        private StreamReader file;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            canvas = lblDraw1.CreateGraphics();

        }
        private void readFile(string fileName = "maze.csv")
        {
            int X = 0, Y = 0;
            int width = 0, height = 0, temp=0;
            string[] array;
            string theLine;


            //stupid read just to find the Width and Height
            file = new StreamReader(fileName);
            readFile("maze.csv");
            while ((theLine = file.ReadLine())!=null)
            {
                height++;
                temp= theLine.Split(',').Length;
                if (temp > width)
                    width = temp;
            }


            maze = new string[width, height]; //the whole point of the pre read


            //Transfer Data
            file = new StreamReader(fileName);
            while ((theLine = file.ReadLine()) != null)
            {
                array = theLine.Split(',');//grab data

                //
                for (X = 0; X < width; X++)
                {
                    //Transfer Part
                    maze[X, Y] = array[X];
                }


                Y++;

            }

        }

        private void draw()
        {
            int size = 30;

            for (int Y = 0; Y < 999; Y++)
            {
                for (int X = 0; X < 999; X++)
                {
                    if (file.ReadLine() == "X")
                    {
                        canvas.FillRectangle(Brushes.Black, new Rectangle(Y * size, X * size, size, size));
                    }
                    else
                    {
                        canvas.FillRectangle(Brushes.White, new Rectangle(Y * size, X * size, size, size));
                    }

                }
            }
        }

        private void btnDraw_Click(object sender, EventArgs e)
        {
            

            
      
 

            canvas.Clear(Color.White);
            draw();
            /*

            for (int Y = 0; Y < 999; Y++)
            {
                for (int X = 0; X < 999; X++)
                {
                    if (file.ReadLine() == "x")
                    {
                        canvas.FillRectangle(Brushes.Black, new Rectangle(Y * size, X * size, size, size));
                    }
                    else
                    {
                        canvas.FillRectangle(Brushes.White, new Rectangle(Y * size, X * size, size, size));
                    }

                }
            }
            */
        
        }
    }
}
, I'll try to provide.
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
4,445
Location
Chesapeake, VA
Programming Experience
10+
It would help dramatically if you posted the contents or a sample contents of your "maze.csv".

Right now, with the way your code reads, it doesn't look like you truly have CSV file since the first line contains the dimensions, while the succeeding lines contain the actual maze fill/no fill values. As per the non-RFC 4180 description of a CSV file:
RFC 4180 proposes a specification for the CSV format; however, actual practice often does not follow the RFC and the term "CSV" might refer to any file that:[2][5]

  1. is plain text using a character set such as ASCII, various Unicode character sets (e.g. UTF-8), EBCDIC, or Shift JIS,
  2. consists of records (typically one record per line),
  3. with the records divided into fields separated by delimiters (typically a single reserved character such as comma, semicolon, or tab; sometimes the delimiter may include optional spaces),
  4. where every record has the same sequence of fields.
 

reddec85

New member
Joined
Oct 28, 2021
Messages
4
Programming Experience
3-5
It would help dramatically if you posted the contents or a sample contents of your "maze.csv".

Right now, with the way your code reads, it doesn't look like you truly have CSV file since the first line contains the dimensions, while the succeeding lines contain the actual maze fill/no fill values. As per the non-RFC 4180 description of a CSV file:
mazetemp.PNG

I haven't finished the main outline of the maze, I was going to see if I could get it to convert first, but the main idea is that "x" will be drawn as a black square while if there's nothing it'll be drawn as white square. Hope that helps. Thanks for taking a look!
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
4,445
Location
Chesapeake, VA
Programming Experience
10+
You would probably just have an easier time creating a text file instead of a CSV. It would be visually easier to parse, and there wouldn't be any need for you to split the line and waste memory allocating strings in the process of splitting a line.

maze.txt:
7,5
XXX X X
X X X X
XXX XXX
X X X X
X X X X
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
4,445
Location
Chesapeake, VA
Programming Experience
10+
Actually, with further thought, you might not even need the first line to declare how many lines you have or how many blocks wide you need. You could simply figure this out after you've loaded the entire file.

Some pseudo code:
C#:
class Maze
{
    List<Row> _rows;

    public int Width { get; private set; }
    public int Height => _rows.Count;
    public Row this[int i] => _rows[i];

    IEnumerable<BitArray> LoadMazeBits(string filename)
        => File.ReadLines(filename)).Select(line => ParseRow(line));

    BitArray ParseRow(string line)
    {
        var bits = new BitArray(line.Length);
        for(int i = 0; i < line.Length; i++)
            bits[i] = line[i] == 'X';
        return bits;
    }

    public void LoadMaze(string filename)
    {
        // load all the lines from the file into a list of bit arrays of various lenghts
        var tempRows = LoadMazeBits(filename).ToList();

        // get the width of the widest row
        Width = tempRows.Max(row => row.Count);

        // make our permanent rows as wide as the widest row
        _rows = tempRows.Select(row => new Row(Width, row));
    }

    public class Row
    {
         BitArray _row;

         public bool this[int i] => _row[i];

         public Row(int width, BitArray row)
         {
             _row = new BitArray(width);
             Debug.Assert(row.Count <= width);
             for(int i = 0; i < row.Count; i++)
                 _row[i] = row[i];
         }
    }
}

In load event of form:
_maze = new Maze();
_maze.Load("maze.txt");

In paint event of form, label, or custom control:
for(int row = 0; row < _maze.Height; row++)
{
    for(int col = 0; col < _maze.Width; col++)
    {
        if (_maze[row][col])
        {
            // draw a filled rectangle for row, col on screen
        }
    }
}
 
Top Bottom