Iterate in an int switch statement

Hi everyone, I have this issue :

I have a really big switch statement (and I want eventually to add some cases in the future), it is a simple one looking like that :

        switch (cardNo)
        {
        case 1:
            //Do stuff
            break;
        case 2:
            //Do stuff
            break;
        case 3:
            //Do stuff
            break;
        case 4:
            //Do stuff
            break;


            //AND SO ON......



        }

I would simply like to iterate the int at each case, like that :

        switch (cardNo)
        {
        int k = 0;
        case k:
            //Do stuff
            break;
            k++;
        case k:
            //Do stuff
            break;
            k++;
        case k:
            //Do stuff
            break;
            k++;
        case k:
            //Do stuff
            break;


            //AND SO ON......



        }

So if I add a new case 3, I do not have to push each case from 4 to 100000… :frowning:

(I need to do that because this statement is linked with a txt file…)

Have you a solution ?
Thank you !

It depends on what you are doing in each case. You may be able to use a for loop.

case-labels have to be compile time constants, so this is not possible. You’re also trying to do something after break, which makes no sense.

You’re mixing what’s happening at compile time and runtime here. Your switch-statement are program instructions, not data, and can’t be changed when the code is running.

for (int k = 0; k < 100000; k++) {
     switch(CardNo) {
           case PreDefinedInteger: //Do Something
           break;
     }
}

Put the switch statement inside a for loop, which will increment your control variable for you on each iteration.

EDIT: Also note, the case statements in your switch statement have to be numbers that you know ahead of time. If this is not what you need, then don’t use a switch statement, use this instead:

for (int k = 0; k < 100000; k++) {
     if (EvaluateCondition(k)) {
          //Do Something
     }
}

Where EvaluateCondition is a function that returns a bool (true or false)

Can I ask what you’re doing with this switch statement, specifically? It’s EXTREMELY rare in my experience that a long switch statement like that is a good idea, and even rarer if you’re not using an enum as your switch controller.

The situation is a trading card game, each card have an ID, I switch this ID and I am doing something differetn for each card… (So I can not use a for loop…)

Thank you for your reply

Yeah, this is not a very good design, and it’s going to be a major pain to maintain your code. When you say each card is “doing something different”, I’m picturing something like Magic or Dominion where each card has actions that it carries out. Would that be about accurate?

If so, then a better way to handle this would be scripts with inheritance and/or an interface. I’ll give an example of the former.

public abstract class ActionCard : MonoBehaviour {
public abstract void PlayCard();
}

public class AttackCard : ActionCard {
public float attackPower = 1f;
public override void PlayCard() {
SomeOtherPlayer.Attack(attackPower);
}
}

Based on this, your main script can have a reference to an ActionCard, which may be any of your game’s cards. Individual cards will have different types (AttackCard, DefenseCard, whatever), but they’ll all have a PlayCard function.

ActionCard someCard = someObject.GetComponent<ActionCard>(); //will find any types derived from ActionCard as well
someCard.PlayCard();

The above code doesn’t know what type of card component is attached to someObject, and it doesn’t really care. It just has the card run its own function.

Not knowing much about the way your game is currently structured, I’m not sure how difficult this would be to switch, but I am certain that this is a better approach than a switch statement.

1 Like

If you really want to, you can remember that a switch is just a fancy if; and can do what you’re wanting with those. Using k++ inside the if is horribly abusive, but it’s shorter and this whole idea is dodgy anyway:

int k=0;
if(cardNo==k++) { do stuff; return; }
if(cardNo==k++) …

I assume the intent is to be able to easily insert new items into the middle, and have the compare numbers automatically adjust.

Even this, I’m having trouble seeing the logic behind wanting this in the original design. So you have a card whose ID number is 25, and that card makes you, i dunno, deal 2 damage to something. Then you insert something in between ID’s 10 and 11. Now the card with ID number 25 makes you draw two cards, and it’s card #26 that deals 2 damage. What’s the purpose of wanting to insert something in the middle of the list and shift everything that follows?

If the OP is still looking for this, I wanted to share my opinion that a virtual / abstract method or an interface is a much better idea.
Personally, I love switch statements, but within reason. :slight_smile:

If the card numbers are going to change, they shouldn’t be used as your identifier for this. Add an ‘id’ field to your card data, and base any card-specific behavior off of that:

switch(cardId) {
case "lightning_bolt":
  // Do three damage
  break;
case "five_clubs":
  // Check for straight or flush
  break;
...
}

That’s still pretty hard-coded; it may be better to generalize this and have a ‘function’ or ‘type’ field for behavior that’s shared between several cards, using custom code per card only when actually needed.

You could also do this via an interface / factory rather than a switch statement, but whether that’s better depends on what you’re doing.

Ok StarManta, if you can help me it would be awesome, this is what I have to do :

First a txt file like this : (you can change it if you like)

cost of the card (to play it)|Text to show on the card
0|This card do this action
0|This card do this other action
1|…
3|…

Then I need to be able to create a “deck”, like a list of the card one player can draw.
After that I also need to instantiate a prefab (randomly one card of the deck), to asign it the cost of the card and the text to show and to add it to a list (or else) to keep positions of cards in hand of player.
And finally, when the player click on it, I need to trigger the card effect, it can be many things like drawing card, add attack or armor or life, destroy opponent attack, attack 2 times at the end of the turn… so I need to trigger it and send result to a server (just a string with stats of both players, and witch card in hand had been played.

Thank you verry much for your help !

OK, so what you’ve got here is a design where you have part of the card’s data (cost & text) in one place, and part of the data (functionality) somewhere else.

The design I described in my first comment will definitely work much better for you - all of your card’s data and functionality will be attached to the same prefab, and you can instantiate that prefab into your deck. The prefab will already have the card cost, description text, name, a reference to its graphics, etc. And, through the power of inheritance, you’ll also be able to make it have the functionality of the card on the same object.

If you put all these prefabs into a folder in Resources, you can use Resoures.LoadAll to find all the cards you have (and creating a new card will take you literally 10 seconds). Instantiate one of those and, boom, you have that card in your hand.

Anytime you need to convey a reference to a card (say, telling the server what card you played), use the card’s name. The server will be able to find out anything else it needs to know about the card from its own copy of the cards.

Ok, so I make a script like this one :

using UnityEngine;
using System.Collections;

public class Card : MonoBehaviour
{
    public int cardID; // <- do I still need it ?

    public string cardDescription;
    public int cardCost;

}

And I make many prefabs (one for each card) and I set up those public var in unity.

But… there is something I do not really understand : How I call different specific function(s) for each card? Is this simple ?

Thank you again and sorry if I don’t get it…

Probably not, especially if you identify cards by their prefab name.

It’s pretty simple, but it does require a basic understanding of what inheritance is. What we’re going to do is make a function on your base class, and then override that function to do different things.

You’ll add something like this to your base Card class:

public virtual void PlayCard() {
Debug.Log("This card does nothing.");
}

That “virtual” is important - it tells the compiler, “in classes derived from this class, we might replace this function. If so, call the replacement function instead of me.”

So then make a new script. We’ll go with AttackCard:

public class AttackCard : Card {
public float damage = 4f;
public override void PlayCard() {
Debug.Log("This card deals "+damage+" damage.");
}
}

It’ll be helpful to make these functions somewhat generalized as much as it makes sense to. If one card deals 4 damage and another card deals 6 damage, use AttackCard for both, and add a variable to control that amount, as shown.

Because AttackCard is a Card, you can do all sorts of cool stuff, especially if you have collections of Cards (say, your hand). For example, if you do this (which will “play” every card in your hand):

Card[] handOfCards = GetComponentsInChildren<Card>(); //this also finds derived classes, like AttackCard
for (int c=0;c<handOfCards.Length;c++) {
Card thisCard = handOfCards[c];
thisCard.PlayCard();
}

Even though thisCard points to the Card script, the third card in the hand is an AttackCard, and so when you call .PlayCard() on that one, it’ll execute that code, and output “This card deals 4 damage.”. Every derived class will use its own PlayCard() function if you’ve overridden it.

The best part about this is, no matter how many new and exciting card types you add an no matter what they do when you play them, you never have to change that block of code that plays them - only the overridden functions. This keeps code nice and organized, and you will never have to wade through a long list of switch statements to find that one that does that thing you want.

Ok, thank you I understand !

Some other questions :roll_eyes: :
I have to create this kind of script for every kind of stuff I want to do ? And then I attach it to the specific card prefab ? (And eventually I set up a public var like the damage example in unity ?

    public class AttackCard : Card {
    public float damage = 4f;
    public override void PlayCard() {
    Debug.Log("This card deals "+damage+" damage.");
    }
    }

Last Question : Can I call many of them ?
For example I have a class named DrawCard, wich makes me draw a card, and another attack like your example, can I call both at same time ? Or it is more simple to create a new one ?

Thank you again ! So helpfull !