I’m trying to make a basic grid based dungeon crawler. When I build&run and the program prints out the board[7][10] char array only one space on the board has a ‘T’ character. But if I go step by step with the debugger it works perfectly and places 3 ‘T’ characters on the board like I want it to. I have no idea how to fix this problem or what is even causing it. I’m getting no errors from the compiler, it’s just strange output:
main.cpp
#include <iostream>
#include "DungeonBoard.h"
#include "Tokens.h"
int main()
{
DungeonBoard dungeonCrawl; // create DungeonBoard object
dungeonCrawl.start(); // call start function
}
DungeonBoard.h
#ifndef DUNGEONBOARD_H
#define DUNGEONBOARD_H
class DungeonBoard
{
public:
DungeonBoard(){} // default constructor
void start(); //gameplay
void printBoard(); // print out the gameboard
private:
};
#endif // DUNGEONBOARD_H
DungeonBoard.cpp
#include <iostream>
#include "DungeonBoard.h"
#include "Tokens.h"
const int ROW = 7;
const int COLUMN = 10;
char board[ROW][COLUMN]= {{'.', '.', '.', '.', '.', '.', '.', '.', '.', '.'}, {'.', '.', '.', '.', '.', '.', '.', '.', '.', '.'},
{'.', '.', '.', '.', '.', '.', '.', '.', '.', '.'}, {'.', '.', '.', '.', '.', '.', '.', '.', '.', '.'},
{'.', '.', '.', '.', '.', '.', '.', '.', '.', '.'}, {'.', '.', '.', '.', '.', '.', '.', '.', '.', '.'}, {'.', '.', '.', '.', '.', '.', '.', '.', '.', '.'}};
bool occupied[ROW][COLUMN] = {{false, false, false, false, false, false, false, false, false, false},
{false, false, false, false, false, false, false, false, false, false}, {false, false, false, false, false, false, false, false, false, false},
{false, false, false, false, false, false, false, false, false, false}, {false, false, false, false, false, false, false, false, false, false},
{false, false, false, false, false, false, false, false, false, false}, {false, false, false, false, false, false, false, false, false, false}};
Tokens hero(0, 0); //creates user starting location at top left corner
Tokens treasure(6, 9); // creates treasure location at bottom left corner
Tokens trap1, trap2, trap3;
void DungeonBoard::start(){
char userDirection; // user input
bool gameOn = true; // sentinel value for while loop
std::cout << "DUNGEON CRAWL 1.0\n";
std::cout << "------------------\n\n";
std::cout << "H is the hero, T are traps, X is the treasure and .'s are open spaces.\n";
std::cout << "The goal is to move around the gameboard and reach the treasure while avoiding \ndtraps.\n\n";
std::cout << "CONTROLS: W - UP, S - DOWN, A - LEFT, D - RIGHT.\n\n";
std::cout << "Enjoy! :)\n\n";
board[hero.get_row()][hero.get_col()] = 'H'; // set user starting position
occupied[hero.get_row()][hero.get_col()] = true; // make space used
board[treasure.get_row()][treasure.get_col()] = 'X'; // set treasure position
occupied[treasure.get_row()][treasure.get_col()] = true; // make space used
trap1.trap_loc(); // randomize location of trap 1
while(occupied[trap1.get_row()][trap1.get_col()] == true){ //check to make sure space is not occupied
trap1.trap_loc(); //if occupied, re-randomize
}
trap2.trap_loc(); //randomize location of trap 2
while(occupied[trap2.get_row()][trap2.get_col()] == true){ //occupy check
trap2.trap_loc(); // re-randomize
}
trap3.trap_loc(); //randomize location of trap 3
while(occupied[trap3.get_row()][trap3.get_col()] == true){ //occupy check
trap3.trap_loc(); //re-randomize
}
//set board spaces for traps to T and mark that space as used
board[trap1.get_row()][trap1.get_col()] = 'T';
occupied[trap1.get_row()][trap1.get_col()] = true;
board[trap2.get_row()][trap2.get_col()] = 'T';
occupied[trap2.get_row()][trap2.get_col()] = true;
board[trap3.get_row()][trap3.get_col()] = 'T';
occupied[trap3.get_row()][trap3.get_col()] = true;
printBoard();
}
void DungeonBoard::printBoard(){
for(int i = 0; i<7; i++){
for(int r = 0; r<10; r++){
if(r == 0)
std::cout << " ";
std::cout << board[i][r] << " ";
}
std::cout << "\n\n";
}
}
Tokens.h
#ifndef TOKENS_H
#define TOKENS_H
class Tokens
{
public:
Tokens(){} //default constructor
Tokens(int row, int col); //constructor with coordinates already known
void set_pos(int new_row, int new_col){ rowLoc = new_row; colLoc = new_col;} // set new row and col values
int get_row(){return rowLoc;} //row getter
int get_col(){return colLoc;} //col getter
void trap_loc(); // randomize trap location
int rand0toN1(int n); //psuedo random number generator
private:
int rowLoc, colLoc; //tokens location by row and column
};
#endif // TOKENS_H
Tokens.cpp
#include <ctime>
#include <cstdlib>
#include "Tokens.h"
#include "DungeonBoard.h"
Tokens::Tokens(int row, int col){ //sets the position of the token
set_pos(row, col);
}
void Tokens::trap_loc(){ //gets random row and col for trap
int trapRow = rand0toN1(6);
int trapCol = rand0toN1(9);
set_pos(trapRow, trapCol); // sets position of trap token to the random numbers created
}
int Tokens::rand0toN1(int n){ //psuedo-random num generator
srand(time(NULL)); // set seed for randomization
return rand()%n;
}
The problem is that you keep re-initialising
srandwith the same seed when you use it insideTokens::rand0toN1. This is becausetime(NULL)has seconds resolution.By stepping through the code, you’re causing
srandto be initialised with different values, hence the expected result.sranddoesn’t need be called before every use ofrand, it is only needed to initialise it, so if you movesrand(time(NULL));to somewhere like the start ofDungeonBoard::start()(basically ensure it’s called once before the first use ofrand), your program should work as expected.