1

I'm currently learning and playing arround with C++ and I wanted to find how come my switch statement only responds to a half of the cases? It only responds when substracting from the integers. Note, that I am as much as a beginner as it is possible to be, so any advice would be really helpful.

#include <fstream>
#include <iostream>
#include <windows.h>
#include <conio.h>
using namespace std;

#define KEY_UP 72
#define KEY_DOWN 80
#define KEY_LEFT 75
#define KEY_RIGHT 77
#define SPACE_BAR 32

void startingCoord (int & x, int & y)
{
    cout << "Starting coord" <<endl;
    cin >> x >> y;
}
void printGrid(int x, int y)
{
    for (int a = 0; a < 10; a++)
    {
        for (int b = 0; b < 10; b++)
        {
            if (a + 1 == x && b + 1 == y)
            {
                cout<<" 0 ";
            }
            else
            {
                cout<<" - ";
            }
        }
        cout<<endl;
    }
}
int main ()
{
    int c = 0, x = 0, y = 0;
    startingCoord(x, y);
    while (true)
    {
        printGrid(x, y);
        switch (c = getch()){
        case SPACE_BAR:
            return 0;
        case KEY_DOWN:
            x++;
        case KEY_RIGHT:
            y++;
        case KEY_UP:
            x--;
        case KEY_LEFT:
            y--;
        default:
            return 0;
        }
        cout<<x<<" "<<y;

    }
}
  • 6
    for starters you should have `break;` after each `case` that doesn't `return` – M.M Apr 28 '18 at 15:03
  • 2
    [Get a good beginners book (or two)](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list/388282#388282) and start over. – Some programmer dude Apr 28 '18 at 15:05
  • 2
    And [learn how to debug your programs](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/). If ytou stepped through the code line by line in a debugger you would have seen the problem immediately. Then you should go to your books to read and understand why it behaves like it does. – Some programmer dude Apr 28 '18 at 15:06
  • I meant that it only responds to the cases which contain a substraction (in this case the ones, where the user inputs the up arrow key or the left one) – Ignas Šimkūnas Apr 28 '18 at 15:06
  • And as @Someprogrammerdude explained, 30 seconds in the debugger stepping through the code would tell you *exactly* why that's what's happening. Literally 30 seconds. It's never too early to learn how to use a debugger, which is one of the best tools a coder has available to them. – Ken White Apr 28 '18 at 15:58

2 Answers2

7

Change this:

case KEY_DOWN:
    x++;

to this:

case KEY_DOWN:
   x++;
   break;

and do the same for every case that doesn't have a return statement.

Without the break statement, the control flow continues to the cases after the case that its condition was just satisfied.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
2

Like @gsamaras said, you need to include a break statement at the end of each case unless your case returns something or you want the control flow to keep going.

Let me give you an example.

In your case, if you select KEY_DOWN, it will do the following:

switch (c = getch()) { // assume c = KEY_DOWN
    case SPACE_BAR: // is the value of c SPACE_BAR? no
        return 0;
    case KEY_DOWN: // is the value of c KEY_DOWN? yes
        x++; // do this
    case KEY_RIGHT: // no break, keep going
        y++; // do this
    case KEY_UP: // no break, keep going
        x--; // do this
    case KEY_LEFT: // no break, keep going
        y--; // do this
    default: // no break, keep going
        return 0; // returns 0
}

Similarly, if you'd press KEY_RIGHT:

switch (c = getch()) { // assume c = KEY_RIGHT
    case SPACE_BAR: // is the value of c SPACE_BAR? no
        return 0;
    case KEY_DOWN: // is the value of c KEY_DOWN? no
        x++; 
    case KEY_RIGHT: // is the value of c KEY_RIGHT? yes
        y++; // do this
    case KEY_UP: // no break, keep going
        x--; // do this
    case KEY_LEFT: // no break, keep going
        y--; // do this
    default: // no break, keep going
        return 0; // returns 0
}

For the two cases above, the result was the same: it returns 0 because the very last case (default) is return 0;

What you should be doing

switch (c = getch()) { // assume c = KEY_DOWN
    case SPACE_BAR: // is the value of c SPACE_BAR? no
        return 0;
    case KEY_DOWN: // is the value of c KEY_DOWN? yes
        x++; // do this
        break; // there's a break, stop here.
    case KEY_RIGHT: 
        y++; 
        break; 
    case KEY_UP:
        x--; 
        break;
    case KEY_LEFT:
        y--;
        break;
    default: 
        return 0; 
}

Implementing what you just learned

Now that we know that unless there's a break, the flow will keep going, we can use that to our advantage by moving case SPACE_BAR: above default: because we know that they both return 0 anyways:

switch (c = getch()) { 
    case KEY_DOWN: 
        x++;
        break;
    case KEY_RIGHT: 
        y++; 
        break; 
    case KEY_UP:
        x--; 
        break;
    case KEY_LEFT:
        y--;
        break;
    case SPACE_BAR: 
    default: 
        return 0; 
}

Note: While adding case SPACE_BAR: on top of the default is indeed a better idea than leaving them both separately, you can also just not put case SPACE_BAR at all, since even if you don't include it, it will fall into the default anyways.

Good luck!

TwiN
  • 3,554
  • 1
  • 20
  • 31