Update: Please see EDIT 3 at the bottom.
I am very much a beginner with C# and programming in general (so please be gentle!). I’ve followed plenty of tutorials and read through books and thought I understood classes. Until now.
I have a fairly simple single-class project which uses a 2D string array to set a 10×10 grid of letters E (for empty) and F (for full). I use int x and int y to refer to the coordinates of the array and use switch to detect input and add or subtract from x and y to determine if the array cell is empty or full.
class MainGame
{
public MainGame()
{
string[,] mapTerr = new string[10, 10]
{
{ "F", "F", "F", "F", "F", "F", "F", "F", "F", "F" },
{ "F", "E", "E", "E", "E", "E", "E", "E", "E", "F" },
{ "F", "E", "E", "E", "E", "E", "E", "E", "E", "F" },
{ "F", "E", "E", "E", "E", "E", "E", "E", "E", "F" },
{ "F", "E", "E", "E", "E", "E", "E", "E", "E", "F" },
{ "F", "E", "E", "E", "E", "E", "E", "E", "E", "F" },
{ "F", "E", "E", "E", "E", "E", "E", "E", "E", "F" },
{ "F", "E", "E", "E", "E", "E", "E", "E", "E", "F" },
{ "F", "E", "E", "E", "E", "E", "E", "E", "E", "F" },
{ "F", "F", "F", "F", "F", "F", "F", "F", "F", "F" },
}; // long-winded I know, but helps visualise the array
int x, y;
string navDir;
Console.WriteLine("Enter a command:");
navDir = Console.ReadLine();
switch (navDir)
{
case "N":
case "n":
x -= 1;
if (mapTerr[x, y] == "F")
{
Console.WriteLine("You cannot move North, it is blocked!");
x += 1;
}
else
{
Console.WriteLine("You move North.");
}
break;
case "E":
case "e":
y += 1;
if (mapTerr[x, y] == "F")
{
Console.WriteLine("You cannot move East, it is blocked!");
y -= 1;
}
else
{
Console.WriteLine("You move East.");
}
break;
// etc...
This works fine. However, I’ve tried to split it into separate classes: one for creating the array and another for controlling input and output. This is my attempt:
class Program
{
public static void Main(string[] args)
{
Map map = new Map();
UserControl usercontrol = new UserControl();
}
}
class Map
{
string[,] mapTerr = new string[10, 10] {
{ // array contents here
};
}
class UserControl
{
int x, y;
string navDir;
public UserControl()
{
Console.WriteLine("Enter a command:");
navDir = Console.ReadLine();
switch (navDir)
{
case "N":
case "n":
x -= 1;
if (mapTerr[x, y] == "F") // ERROR: The name 'mapTerr' does not exit in the current context"
{
Console.WriteLine("You cannot move North, it is blocked!");
x += 1;
}
else
{
Console.WriteLine("You move North.");
}
break;
// etc...
I can’t for the life of me figure out how to make it work. The errors are primarily when the array is called from within the switch.
I realise this is because the array is associated with the Map class and not the UserControl class, so how do I make it visible / useable?
Despite trawling the array / scope / class sections here and elsewhere online, nothing really explains things entirely in simple terms. I presume it’s a matter of scope and I’m trying to call reference to things in ways that aren’t possible. If anyone can explain what I’m doing wrong and perhaps hint at a way I can go the right way about things, I’d really appreciate it! (Apologies for the long explanation / question)
EDIT 1: added specific error message as a comment beside the line. This occurs on every line the mapTerr is referred to within the switch.
EDIT 2: clarified instantiating and class structure.
EDIT 3: Okay, the string array is set in the Map class publicly, public string[,] elsaNav = new string[10, 10] {{/*contents*/}; and I instantiate the map class in the Program class, but still can’t call the mapTerr array from within UserControl class, despite using map.mapTerr…
I’m not quite sure how your final solution looks like after editing with the suggestions given in this post, but I’ve fixed up the code to give you one way of working with it, hopefully it can help you to pinpoint the error in your code ๐
My apologies if the indention is a bit off, I’m in a hurry and do not have access to a proper C# compiler right now, but the above code should work ๐
It was a good idea to encapsulate and seperate your map and userinput into two classes, by the way! Great head start for a new programmer ๐
Remember to use properties exensively in your classes to control how data members are accessed in your classes. In most cases you do NOT want to make members purely public. Instead, make them private and make a property for them, so you can control how data can be set or accessed.
Of course, I’ve just quickly written some example logic for initializing the array with letters just to showcase the solution, so you will probably want to re-write that to suit your own needs ๐
Also, how you want to work with the map object also depends on your own thought about how the client should work with the code, I simply make a Map object a composition of the UserControl class without letting client code work with it. Another way could of course be letting the client code initialize its own map object and pass it into the constructor of the UserInput class.
Hope it helps you.
[EDIT]
Okay, I haven’t seen your solution code for this but perhaps I still get it… let me have a go at it ๐ Basically you are instantiating the Map class in the Program class, something like:
and then you try to access the “myMap” reference directly in the instance of your UserControl class? In this case, you can’t simply do this. The myMap reference is only in scope within the Program class method that you are calling it from, so when you try to reference it from within your UserControl class it won’t have any knowledge of it whatsoever, it is out of its scope. Instead, you would have to pass a reference into the UserControl class like this:
and then from within the class your constructor would look like this:
Perhaps I misunderstood what you said, but if that is what you meant, then the above solution should fix it right up ๐