I need to randomly populate this 2d array with 5 different items. The amount of each item is passed as a percentage, along with the dimension of the 2d array, at runtime.
This is what I tried but I got a segmentation fault error in the terminal. When I tried to run the debugger I got this error:
EXC_BAD_ACCESS (code=2, address=0x16f603fe8)
.h file
#ifndef LEVEL_H
#define LEVEL_H
#include <cmath>
#include <iostream>
#include <time.h>
#include <stdio.h>
#include "Mario.h"
using namespace std;
//Class for level
class Level{
public:
//Constructor for level, which takes in the array dimensions
//Also takes in the percentages chosen by the file, for how many coins, nothing spaces, goomba and koopa's
//are present in the array (world)
Level(int dimension, int coinPrct, int nothingPrct, int goombaPcrt, int koopaPrct, int mushPcrt);
//Default destructor
~Level();
void populate();
char nextItem();
//Private member variables
private:
char *m_levelAry;
int m_coins;
int m_nothing;
int m_goombas;
int m_koopas;
int m_mushrooms;
int m_dimension;
};
#endif
.cpp file
#include "Level.h"
//Constructor handles dimensions of the array and odds of how frequent coins, enemies and nothing spawn
Level::Level(int dimension, int coinPrct, int nothingPrct, int goombaPcrt, int koopaPrct, int mushPcrt){
m_dimension = dimension;
m_levelAry = new char [dimension * dimension];
m_coins = round((coinPrct/100.0) * (dimension * dimension));
m_nothing = round((nothingPrct/100.0) * (dimension * dimension));
m_goombas = round((goombaPcrt/100.0) * (dimension * dimension));
m_koopas = round((koopaPrct/100.0) * (dimension * dimension));
m_mushrooms = round((mushPcrt/100.0) * (dimension * dimension));
/*
srand(time(NULL));
for (int i = 0; i < dimension; i ){
for (int j = 0; j < dimension; j ){
m_levelAry[i * dimension j] = nextItem();
}
}
for (int i = 0; i < dimension; i ){
for (int j = 0; j < dimension; i ){
cout << m_levelAry[i * dimension j] << " ";
}
cout << endl;
}
*/
}
Level::~Level(){
delete[] m_levelAry;
}
void Level::populate(){
srand(time(NULL));
for (int i = 0; i < m_dimension; i ){
for (int j = 0; j < m_dimension; j ){
m_levelAry[i * m_dimension j] = nextItem();
}
}
for (int i = 0; i < m_dimension; i ){
for (int j = 0; j < m_dimension; i ){
cout << m_levelAry[i * m_dimension j] << " ";
}
cout << endl;
}
}
char Level::nextItem(){
int randItemNum = (rand() % 4) 1;
switch (randItemNum){
case 1:
if (m_coins != 0){
m_coins -= 1;
return 'c';
} else {
return nextItem();
}
break;
case 2:
if (m_nothing != 0){
m_nothing -= 1;
return 'x';
} else {
return nextItem();
}
break;
case 3:
if (m_goombas != 0){
m_goombas -= 1;
return 'g';
} else {
return nextItem();
}
break;
case 4:
if (m_koopas != 0){
m_koopas -= 1;
return 'k';
} else {
return nextItem();
}
break;
case 5:
if (m_mushrooms != 0){
m_mushrooms -= 1;
return 'm';
} else {
return nextItem();
}
break;
default:
return NULL;
break;
}
}
int main(int argc, char const *argv[])
{
Level level1(5, 25, 47, 8, 8, 12);
level1.populate();
return 0;
}
CodePudding user response:
The switch case in Level::nextItem()
never go into case 5.
The range of int randItemNum = (rand() % 4) 1;
is 1~4.
When the m_coins, m_nothing, m_goobas, m_koopas all consumed, Level::nextItem()
will be infinite loop, which will cause segmentation fault in the end.
Note: gdb is helpful for dealing with this kind of problem.
CodePudding user response:
Simpler, safer population:
void Level::populate(){
char *locp = m_levelAry;
memset(locp, m_coins, 'c');
locp = m_coins;
memset(locp, m_goombas, 'g');
locp = m_goombas;
memset(locp, m_koopas, 'k');
locp = m_coins;
memset(locp, m_mushrooms, 'm');
locp = m_coins;
memset(locp, m_nothing, 'x');
locp = m_nothing;
std::random_device rd;
std::mt19937 engine(rd());
std::shuffle(m_levelAry, locp, engine);
}
The code fills up the array with the required number of each tile and then shuffles the array to get a good distribution of tiles.
Side note: I'd compute the number of coins, koopas, goombas, and mushrooms. Nothing would be the remaining space in the array. This prevents problems where the math doesn't round out to exactly fill the array.