2

Note: I am somewhat of a beginner to C#.

I'm working on a little game that will have a bunch of different levels. Each level has its own class that contains variables (and other irrelevant code). Since I need to pass these values to the main class (my form) I have made them all into methods that returns the value I want (since I can't come up with a better solution). example:

class Level01
{
    public int Boxes() { return 3; }
    public int MaxPoints() { return 46; }
    public int Health() { return 63; }
    public int[,] SolidBoxes()
    {
        int[,] position = new int[Boxes(), Boxes()];
        position[1, 1] = 1;
        return position;
    }
}

When I access these values from my form class I do

int boxes;
int maxPoints;
int health;
int[,] solidBoxes;

void readLevelData() //Starts each new level
{
    //Reads the correct level
    switch (levelNo)
    {
        case 1: 
        setValues(Lvl01.Boxes(), Lvl01.MaxPoints(), Lvl01.Health(), Lvl01.SolidBoxes()); 
        break;
        //The same case 2:, 3: for Level02,03..
    }
}

void setValues(int getBoxes, int getMaxPoints, int getHealth, int[,] getSolidBoxes)
{
    boxes = getBoxes;
    maxPoints = getMaxPoints;
    health = getHealth;
    solidBoxes = getSolidBoxes;
}

I am aware that there's probably a million things in my code here that can be done better and I gladly listen if you have any suggestions, but the thing I wish to ask is:

How can I get all the values from each class using maybe just one name? Ex. Instead doing as I do now, is there a way so I can do something similar to this:

case 1: 
    setValues(Lvl01.Values); 
    break;

The problem here is in the setValues method, some of the levels has quite a lot of settings that I wish to use, but I doubt the method would want to take like 15 parameters, and I'm not sure what to do when some levels are not using settings that other levels use.

How should I change my code so I do not have to use every single value as a parameter?

2 Answers 2

3

You could use a Dictionary<int, Level> to lookup the object representing each level. Instead of the switch/case, you would do something like

Level level = myLevelDictionary[currentLevel];

That requires you change your classes from having one class per level, to one class that represents any level, e.g.:

class Level
{
    public int Boxes { get; set; }
    public int MaxPoints { get; set; }
    public int Health { get; set; }
    public int[,] SolidBoxes()
    {
        int[,] position = new int[boardSize, boardSize];
        position[1, 1] = 1;
        return position;
    }
}

You would then populate your dictionary like

Dictionary<int, Level> myLevelDictionary = new Dictionary<int, Level>()
{
    { 1, new Level() { Boxes = 3, MaxPoints = 46, Health = 63 } },
    // etc.
};

UPDATE

A note about abstract classes

You mention abstract classes in your comments. They are useful if all of your levels have some behavior in common, but some have specialized behavior too. They will often be used in games for things that can move in the game, e.g. something like

abstract class Character
{
    // Something everyone has
    public int HitPoints { get; set; }
    // Something everyone does, but does differently
    public abstract void Attack(Character target);    
}

public class Fighter : Character
{
    public int SwordDamage { get; set; }

    public void Attack(Character target)
    {
        target.Damage(this.SwordDamage - target.PhysicalDamageResistance);
    }
}

public class Mage : Character
{
    public int MagicFireDamage { get; set; }
    public int MagicColdDamage { get; set; }

    public void Attack(Character target)
    {
        if (UseFireDamage()) // e.g. roll random chance that the mage uses a fire spell
        {
            target.Damage(this.SwordDamage - target.FireDamageResistance);
        }
        else
        {
            target.Damage(this.SwordDamage - target.ColdDamageResistance);
        }

    }
}
Sign up to request clarification or add additional context in comments.

15 Comments

Just to call out a really important difference between this and the original code; the methods have been refactored into auto-properties; which is unquestionably the right way to go, but the change may not be obvious unless you were paying attention.
Thank you for calling that out.
Thank you. I am not sure how Dictionary is used so I'll look that up in a while. I have two question though: 1. Wouldn't that require me to assign every single value in the form class? 2. What if I have a level that doesn't use, let's say MaxPoints for example.
The Dictionary gives you a place to store things that you want to get later (Levels). When you get them, you look them up using a key (the level number).
@Jokuc: Immutable means that the values cannot be changed after the object is initialized. It protects other parts of your program from accidentally changing things that should not be changed. Though it is an important advanced concept, I would not suggest worrying about it too much until you feel confident with less advanced topics.
|
1

one way maybe to use a dictionary.

class Level01
{
Dictionary<string,int> values;

public level01()
{
   values.Add("Boxes",3);
   values.Add("MaxPoints",3);
   values.Add("Health",3);

}
 //indexer
public int this[string s] {get{return values[s];} set {values[s] = value;}}

}

and use like:

Level01 lv = new Level01();
somemethod(lv["Boxes"]); //passes 3 to some method

although really you would want to use Dictionary<string,object> and add some type checking and other things to make it work smoothly but hopefully you can get started with that

5 Comments

Thank you as well! To add a 2D array of ints inside the Dictionary (as in my example up there), do I just put <int[,]> after the Dictionary keyword? How can I add this: int[,] position = new int[boardSize, boardSize]; position[1, 1] = 1; to the Dictionary?
honestly I would leave that by itself and write methods to modify it. unless your levels have more than one gameboard.
How do you mean? (Sorry for being so stupid, I am new to these things.) I use one board (looks like a checker board except that the amount of boxes changes for each level)
methods like int GetCell(int x, int y) or void ChangeCell(int x, int y, int val) for working with the gameboard
@Jokuc opps didn''t @ you on my last comment

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.