Dungeon Crawl Game

I've been working on a simple dungeon crawl game. I've run into an issue moving my player's character among the board. Currently the program has a function that gets and validates the move, then passes by reference into the updateMove function. Here is where the issue lies. I have verified that the move is passed to the updateMove function, but does not seem to work with my if/else statements.
Can anyone tell me what is wrong with them? I'm putting the whole program here. This is my first time posting so if the whole program is too much please let me know and I'll simplify it down.

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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

//global constants
const int MAX_ROW = 8;
const int MAX_COL = 10;
const char SPACE = '.';
const char TRAP = '#';
const char PLAY = '@';
const char CASH = '$';
const char UP = 'U';
const char DOWN = 'D';
const char LEFT = 'L';
const char RIGHT = 'R';

// function declarations
bool repeat();

void displayInstructions(); // display instructions
void initializeDungeon(char dungeon[MAX_ROW][MAX_COL]); // sets up dungeon map
void displayDungeon(char dungeon[MAX_ROW][MAX_COL]); // display current map
void setTraps(char dungeon[MAX_ROW][MAX_COL]); // sets traps
char getMove(char playerMove); // gets move and validates (U,D,L,R)
void updateMove(char & playerMove, char dungeon[MAX_ROW][MAX_COL]); // sees if move is onto checkCode object
void updateDungeon(); // update the dungeon for next move


int main()
{
    // initialize random #
    srand(static_cast<int>(time(NULL)));

    do  // play again loop
    {
        // define variables
        bool win, lose;
        char playerMove;
        char dungeon[MAX_ROW][MAX_COL];
        int cash;

        displayInstructions(); // display instructions
        initializeDungeon(dungeon); // initialize dungeon

        do
        {
            setTraps(dungeon); // set traps
            displayDungeon(dungeon); // display dungeon
            playerMove = getMove(playerMove);

            // check for valid move
            // reassign player to new position
            updateMove(playerMove, dungeon);


            //update map now that move is legit
            if (!win && !lose)
            {
                updateDungeon();
            }

        } while (!win && !lose);

    } while (repeat());
}

// function definitions

void displayInstructions()
{
    cout << "\t----- WELCOME TO THE DUNGEON -----" << endl;
    cout << "\tTo choose your move please enter:" << endl;
    cout << "\tTO MOVE DOWN -------------------- D" << endl;
    cout << "\tTO MOVE UP ---------------------- U" << endl;
    cout << "\tTO MOVE LEFT -------------------- L" << endl;
    cout << "\tTO MOVE RIGHT ------------------- R" << endl;
    cout << "\t--Lowercase or uppercase accepted--" << endl;
    cout << "\tThe object is to reach treasures: $" << endl;
    cout << "\tAnd to avoid the traps: #" << endl << endl << endl;

}

void initializeDungeon(char dungeon[MAX_ROW][MAX_COL])
{
    // Initializes board
    int col = 0, row = 0;
    for (int i =0; i <8; i++)
    {
        for (int j=0; j<10; j++)
        {
            dungeon[i][j] = SPACE;
        }
    }
    // Places treasures
    while(col+row == 0)
    {
        srand(time(0));
        col = rand() % 10;
        row = rand() % 8;
        dungeon[row][col] = CASH;
    }



    // Start player at 0,0
    dungeon[0][0] = PLAY;

}
void displayDungeon(char dungeon[MAX_ROW][MAX_COL])
{

    for(int row = 0; row<8; row++)
    {
        cout << "\t";
        for (int col = 0; col<10; col++)
        {
            cout << dungeon[row][col];
        }
        cout << "\n";
    }
}
void setTraps(char dungeon[MAX_ROW][MAX_COL])
{
    int col, row;
    bool placeTrap = false;
    while (placeTrap == false)
    {
        col = rand() % 10;
        row = rand () % 8;

        if(dungeon[row][col]== SPACE)
        {
            dungeon[row][col] = TRAP;
            placeTrap = true;
        }
    }
}
char getMove(char playerMove)
{
    cout <<  "\t(U)P, (D)OWN, (L)EFT, (R)IGHT :";
    cin >> playerMove;
    playerMove = tolower(playerMove);
    if(playerMove != 'u' && playerMove != 'd' && playerMove != 'l' && playerMove != 'r')
    {
        do
        {
            cout << "\t TRY AGAIN";
            cin >> playerMove;
        } while   (playerMove != 'u' && playerMove != 'd' && playerMove != 'l' && playerMove != 'r');
    }
    return playerMove;
}
void updateMove(char & playerMove, char dungeon[MAX_ROW][MAX_COL])
{
    int px, py;

    int dx = 0, dy = 0;
    if(playerMove == UP && px != 0)
    {
        dx--;
    }
    else if (playerMove == DOWN && px != 7)
    {
        dx++;
    }
    else if (playerMove == LEFT && py != 0)
    {
        dy--;
    }
    else if (playerMove == RIGHT && py != 8)
    {
        dy++;
    }

    else if(dx != 0 || dy != 0)
    {
    dungeon[px][py] = SPACE;
    px += dx;
    py += dy;
    dungeon[px][py] = PLAY;
    }
}
void updateDungeon()
{
    cout << "Updating dungeon" << endl;
}
bool repeat()
{
    cout << "Checking for play again, return false for debug" << endl;
    return false;
}
Some things that you might want to consider:
- px and py are local variables that only exist inside your updateMove function.
You create these variables, but you don't initialize them. This means that they have a value equal to whatever happened to be in the section of the memory that was chosen for these variables. It seems unlikely that this is what you intended to base you if-statement on.
You will probably be surprised if you cout those two two variables before you use them in the if-statements.
I think we can assume that the playerMode will be one of the available options, but I estimate the chance that px and py do what you want (both point to a position inside your array) is currently ((8*10)/(2*INT_MAX))/(2*INT_MAX). Assuming a 32bit architecture that results in something like (80/(2*2147483647))/(2*2147483647) and approximates 0.

- To find out what is going on I would consider calling dispalyDungeon (for debugging purposes) when you are at the beginning of the updateMove function, halfway the updateMove function and at the end of the updateMove function, so you can see what is happening.
On 177, you use an else if. Maybe you meant just an if?
I'm not sure exactly how your game is supposed to work, but maybe something like this:

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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

const int MaxRow = 8, MaxCol = 10;
const char Space = '.', Trap = '#', Play = '@', Cash = '$';
const char Up = 'U', Down = 'D', Left = 'L', Right = 'R';
const int NumCash = 5, NumTraps = 10;
enum State { Playing, Win, Lose };

struct Player {
    int row, col;
    int cash;
    Player() : row{0}, col{0}, cash{0} {}
};

bool repeat();
void displayInstructions();
void initDungeon(char dungeon[][MaxCol], const Player& player);
void displayDungeon(const char dungeon[][MaxCol]);
void setItems(char dungeon[][MaxCol], char sym, int num);
char getMove();
State updateDungeon(char dungeon[][MaxCol], Player& player, char move);

int main()
{
    srand(time(nullptr));

    do
    {
        displayInstructions();

        char dungeon[MaxRow][MaxCol];
        Player player;
        initDungeon(dungeon, player);

        State state = Playing;
        while (state == Playing)
        {
            displayDungeon(dungeon);
            char move = getMove();
            state = updateDungeon(dungeon, player, move);
        }

        displayDungeon(dungeon);

        if (state == Win)
            cout << "You win.\n";
        else
            cout << "You lose.\n";

    } while (repeat());
}

void displayInstructions()
{
    cout << "\t----- WELCOME TO THE DUNGEON -----\n";
    cout << "\tTo choose your move please enter:\n";
    cout << "\tTO MOVE DOWN -------------------- " << Down  << '\n';
    cout << "\tTO MOVE UP ---------------------- " << Up    << '\n';
    cout << "\tTO MOVE LEFT -------------------- " << Left  << '\n';
    cout << "\tTO MOVE RIGHT ------------------- " << Right << '\n';
    cout << "\t--Lowercase or uppercase accepted--\n";
    cout << "\tThe object is to reach treasures: " << Cash << '\n';
    cout << "\tAnd to avoid the traps: "           << Trap << "\n\n\n";
}

void initDungeon(char dungeon[][MaxCol], const Player& player)
{
    for (int row = 0; row < MaxRow; row++)
        for (int col = 0; col < MaxCol; col++)
            dungeon[row][col] = Space;

    setItems(dungeon, Trap, NumTraps);
    setItems(dungeon, Cash, NumCash);

    dungeon[player.row][player.col] = Play;
}

void displayDungeon(const char dungeon[][MaxCol])
{
    cout << '\n';
    for (int row = 0; row < MaxRow; ++row)
    {
        cout << '\t';
        for (int col = 0; col < MaxCol; ++col)
            cout << dungeon[row][col] << ' ';
        cout << '\n';
    }
}

void setItems(char dungeon[][MaxCol], char sym, int num)
{
    for (int i = 0; i < num; )
    {
        int row = rand() % MaxRow, col = rand() % MaxCol;
        if (dungeon[row][col] == Space)
        {
            dungeon[row][col] = sym;
            ++i;
        }
    }
}

char getMove()
{
    char move;
    while (true)
    {
        cout <<  "\t(U)p, (D)own, (L)eft, (R)ight: ";
        cin >> move;
        move = toupper(move);
        if (move == Up || move == Down || move == Left || move == Right)
            break;
        cout << "\tTry again.";
    }
    return move;
}

State updateDungeon(char dungeon[][MaxCol], Player& player, char move)
{
    int drow = 0, dcol = 0;
    if      (move == Up    && player.row != 0)          --drow;
    else if (move == Down  && player.row != MaxRow - 1) ++drow;
    else if (move == Left  && player.col != 0)          --dcol;
    else if (move == Right && player.col != MaxCol - 1) ++dcol;

    State state = Playing;

    if (drow != 0 || dcol != 0)
    {
        dungeon[player.row][player.col] = Space;
        player.row += drow;
        player.col += dcol;
        if (dungeon[player.row][player.col] == Cash)
        {
            if (++player.cash == NumCash)
                state = Win;
        }
        else if (dungeon[player.row][player.col] == Trap)
            state = Lose;
        dungeon[player.row][player.col] = Play;
    }

    return state;
}

bool repeat()
{
    cout << "Checking for play again, return false for debug\n";
    return false;
}

Last edited on
I would put the updateMove() logic inside getMove(). So getMove() keeps looping until the user gives a valid move.

Lines 89, 91, 100, 101, 114, 117, 130, 131: change 8 and 10 to MAX_ROW and MAX_COL.
Lines 97-103: This will place only 1 treasure. You probably need two nested loops here:
1
2
3
4
5
6
for (i=1 to number of traps) {
    do {
          pick random cell in dungeon
    } while chosen cell is not a space
    place treasure in closen cell
}


setTraps() has the same problem as above: it only places one trap.

Why is setTraps() called before each move? Aren't traps stationary? In that case the setTraps logic should be inside initializeDungeon()

In updateMove(), it looks like your intention is for px,py to be the previous player location and dx,dy to be the new location. You'll need to lookup the current position by finding the cell whose value is play, or store the player's location as you go.

Consider creating a Dungeon class. Then all the functions become members and you don't have to pass the array as a parameter.
Line 99: Do not call srand() multiple times. srand() sets the RNG to a particular starting point. Calling srand() repeatedly (in a loop) will cause the RNG to return the same random numbers.
srand() should be called ONCE at the beginning of main().
http://www.cplusplus.com/reference/cstdlib/srand/
Topic archived. No new replies allowed.