Problem with enum

closed account (jwC5fSEw)
From what I've read, an enum's value can be implicitly casted to its type. I'm trying to complete the Dungeon Crawl exercise, and the implicit casting doesn't seem to be working:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include <iostream>
using namespace std;

enum moveDir { UP = 'w', LEFT = 'a', DOWN = 's', RIGHT = 'd' };

int main() {
    const int boardSize = 100;
    char board[boardSize];
    bool hasWon = false;
    bool hasLost = false;
    char dir;
    for (int i = 0; i < boardSize; ++i)
        board[i] = '.';
    board[36] = board[52] = board[67] = 'X'; // Traps, currently predefined
    board[11] = '@'; // Player, currently predefined
    int player = 11; // The player's last spot on the board

    while (!hasWon || !hasLost) {
        cout << string(100, '\n');
        for (int i = 0; i < boardSize; ++i) {
            cout << board [i] << ' ';
            if (i && ((i+1) % 10 == 0))
                cout << endl;
        }
        while (dir != UP || dir != LEFT || dir != DOWN || dir != RIGHT)
            cin >> dir;
        if (dir == UP) {
            player -= 10;
            if (board[player] == 'X') {
                hasLost = true;
                continue;
            }
            else if (board[player] == 'T') {
                hasWon = true;
                continue;
            }
            else board[player + 10] = '.';
        }
        else if (dir == LEFT) {
            player -= 1;
            if (board[player] == 'X') {
                hasLost = true;
                continue;
            }
            else if (board[player] == 'T') {
                hasWon = true;
                continue;
            }
            else board[player + 1] = '.';
        }
        else if (dir == DOWN) {
            player += 10;
            if (board[player] == 'X') {
                hasLost = true;
                continue;
            }
            else if (board[player] == 'T') {
                hasWon = true;
                continue;
            }
            else board[player - 10] = '.';
        }
        else if (dir == RIGHT) {
            player += 1;
            if (board[player] == 'X') {
                hasLost = true;
                continue;
            }
            else if (board[player] == 'T') {
                hasWon = true;
                continue;
            }
            else board[player - 1] = '.';
        }
        board[player] = '@';
    }
}


It just displays the board and keeps asking for input. What's going wrong in this code?
The first problem is that dir is an uninitialized variable. Therefore the while loop might not even work correctly. You should have an enum with some kind of default value that can be used to initialize. Also the enum is really an integral type so comparing those directly with a char might not work. Did you step through the program with the debugger and analyze the value of dir after the assignments to determine if it is being set correctly? Please tell us what you have done to debug this program. It should be fairly simple to solve with a debugger.

Do you get this warning when you compile?

"src\hello.cc", line 26: warning #549-D: variable "dir" is used before its
value is set
while (dir != UP || dir != LEFT || dir != DOWN || dir != RIGHT)
Last edited on
Here is a suggestion. This has nothing to do with the problem but is just something else that I noticed. It is a good idea to consider using std algorithms when possible instead of hand written loops.

1
2
3
4
5
6
7
8
9
// include the algorithm header
#include <algorithm>

//This,
for (int i = 0; i < boardSize; ++i)
        board[i] = '.';

//can be replaced with
std::fill(board, board + boardSize, '.');
My guess is that the enum is an integral type which is probably 4 bytes and you are comparing a char which is 1 byte to it. if I compare 'w' with 119 the result is true since 119 is the decimal value of the character. This is why implicit casting is generally bad. You are comparing completely different kinds of types therefore you have to ensure that you perform an explicit cast or find another way to accomplish this.

You could just create an array of characters using a c-array, or a sequence container (vector, deque) and fill it with the acceptable values. Then you can use std::find to determine whether an input is valid simply be searching the container with the value stored in dir. If the value is found then the value is valid. If not, continue looping and require the user to enter something valid.

Also what happens when the stream extraction fails? You need to handle that error and ensure that the user enters a character otherwise stale data will be left in dir and you will end up in a continuous loop.
http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.3
closed account (jwC5fSEw)
I don't get a warning, though I do compile with -Wall -pedantic.

Thanks, I wasn't aware of that algorithm, I'll use that instead!

That seems reasonable but I'm pretty sure the problem isn't actually with the enum at this point. I tried replacing the while loop with while (dir != 'w' || ...) and so on but that resulted in the same problem, no enum involved.
while( a != x || a != y )

is always true unless a == x == y, since a cannot hold both x and y simultaneously.
Dang it! that's right. It needs to be && not ||. That is like a trick test question! Nevertheless I would still not use enum types in that way. Implicit type conversion may not happen the way that you expect. It is better to compare types that are the same or explicitly cast one or the other.
closed account (jwC5fSEw)
Ohhh, of course! I had the logic backwards in my head. Changing all the ORs to ANDs made it work wonderfully.

Thanks for all of the help everybody!
Topic archived. No new replies allowed.