• Hey, guest user. Hope you're enjoying NeoGAF! Have you considered registering for an account? Come join us and add your take to the daily discourse.

C++ Help?

Status
Not open for further replies.

Ecrofirt

Member
This is a repost from the GAF Devs thread, which appears to have died :-( This thread seems to still have legs, so I thought I might post it here.

Any professional programmers here willing to do a little bit of off-the-main-forum chatting with me regarding class design for the game I'm working on? I'm kind of paranoid about things, so I don't like the idea of discussing my issues too much in the thread.

If you've got experience with game development and would be willing to look through the layout of my classes and give me some guidance on how I should (or if I should) tackle a small problem I've got, please let me know. It's nothing big, but throwing my ideas off of someone else would be great.

Note that the game is in C# using XNA, but since I only want to really talk about class layout it shouldn't be a problem.
 

Ecrofirt

Member
usea said:
Can you explain the problem at all without getting into specifics? What is the small problem?


It's kind of hard to explain. I just want to see whether or not I've got my classes set up in a logical fashion.

I *was* doing things one way, which made sense at the time. As I thought more about it, I thought that I should change around how some things worked in order to keep things in what seems to be a more logical manner. I *think* I did the right thing, as I've now got a class that now manages a item in a much more streamlined manner, but this raises some other potential issues.

Clearer version:
I had a bunch of functions that manipulated a specific class inside of my GameScreen class. As I thought about it, I wasn't sure that I should be doing such heavy manipulation of another class from within my GameScreen, so I created what I'm calling a WidgetManager that will basically have a Widget and do the actual Widget manipulation. This seems to have cleaned up the code in my GameScreen, but it has introduced a new potential problem. I can work around the problem, but I'm not sure if I'm just creating too much shit by doing it this way.

It's hard to really describe what's going on without getting too detailed. And like I said, I'm a bit paranoid about my concept leaking, so I don't want to go blabbing it to the world (especially with the new TOS in place).
 
Once again templates continue to inspire a deep fear within my soul (Playing too much Dark Souls :p).

If I have a templated class and let's say I typedef some members like

Code:
template <class T> class Vec
{
public:

        ...

	typedef T* iterator;

        ...

	iterator erase(iterator);

        ...

};

If I want to define what erase does, do I have to do that inside the class declaration? Right now I'm trying to define it outside but I'm getting all sort of compiler errors in VS10.

warning C4346: 'Vec<T>::iterator' : dependent name is not a type

The way I have the function defined is as follows:

Code:
template <class T> Vec<T>::iterator Vec<T>::erase(Vec::iterator position)
{
	// check for out of bounds
	if (position < data || position >= avail)
	{
		throw std::out_of_range("Iterator out of bounds.");
	}

	if (data)
	{
		for (iterator it = position; it != avail; ++it)
		{
			*it = *(it + 1);
			alloc.destroy(--avail);
		}
	}

	return position;
}

Is this allowed?
 

maharg

idspispopd
You probably just need to do this:

Code:
template <class T> 
[b]typename[/b] Vec<T>::iterator Vec<T>::erase([b]iterator[/b] position)

The reason is that the parser, at the point where it's parsing that line, can't tell that Vec<T>::iterator is a type as opposed to a member or something. So without the typename it looks like you're declaring a function with an implicit return value called Vec<T>::iterator, which isn't your intent at all. This is one area where C++'s parsing gets really stupid, and a lot of it has to do with backward compatibility.

And you don't need the Vec:: on the position type at all because at that point the typing is in the class scope. You had it wrong anyways, as you'd need to specify the template parameter there as well if you did fully qualify it.
 

Leetness

Neo Member
I'm in need of a little help here.
First of all, it's in C, not C++ I hope that's not a problem.

I got an assignment to make a very simple database in a .txt file using structs.
Example of the .txt file:

Smith,John,123456,Baker Street
Smith,John,123456,Baker Street
Smith,John,123456,Baker Street

The numbers representing a student ID.
This ofcourse for let's say 10 students.

Now I want to let the user search for a last name and remove the entire record for that last name.
I did some research and the only option here is to open the "database" file and a temp file, read all the data and write it to the temp file except for the line starting with the user specified name.
Then delete the database file and rename/move the temp file.
I'm a beginner at (C) programming and need some help putting this in code.

I found such a code in C++, but can't seem to find it in C.

----

Code:
#include <cstdio>
#include <fstream>
#include <string>
#include <iostream>
using namespace std;

int main()
{
    string line;
    // open input file
    ifstream in("infile.txt");
    if( !in.is_open())
    {
          cout << "Input file failed to open\n";
          return 1;
    }
    // now open temp output file
    ofstream out("outfile.txt");
    // loop to read/write the file.  Note that you need to add code here to check
    // if you want to write the line
    while( getline(in,line) )
    {
        if(line != "I want to delete this line")
            out << line << "\n";
    }
    in.close();
    out.close();    
    // delete the original file
    remove("infile.txt");
    // rename old to new
    rename("outfile.txt","infile.txt");

    // all done!
    return 0;
}
 
Leetness said:
I'm in need of a little help here.
First of all, it's in C, not C++ I hope that's not a problem.

I got an assignment to make a very simple database in a .txt file using structs.
Example of the .txt file:

Smith,John,123456,Baker Street
Smith,John,123456,Baker Street
Smith,John,123456,Baker Street

The numbers representing a student ID.
This ofcourse for let's say 10 students.

Now I want to let the user search for a last name and remove the entire record for that last name.
I did some research and the only option here is to open the "database" file and a temp file, read all the data and write it to the temp file except for the line starting with the user specified name.
Then delete the database file and rename/move the temp file.
I'm a beginner at (C) programming and need some help putting this in code.

I found such a code in C++, but can't seem to find it in C.

----

Code:
...

First of all, you need to break down the problem into smaller parts. That is what programming is all about. You need to open a file, that is one sub-problem so code something that just opens and reads from a file. Then figure out how to read a full student, and that is a second sub-problem. Focus on reading it first, and then you can store it in a struct. You can create an array of structs that can handle multiple students and that is stored in the program. Once you have that info you can compute which students you don't want and write them to the file. Code this up first and then show us your code so we can help you.

Here is a review of which functions you can use to read from a file:
http://mrx.net/c/readfunctions.html
 
maharg said:
You probably just need to do this:

Code:
template <class T> 
[b]typename[/b] Vec<T>::iterator Vec<T>::erase([b]iterator[/b] position)

The reason is that the parser, at the point where it's parsing that line, can't tell that Vec<T>::iterator is a type as opposed to a member or something. So without the typename it looks like you're declaring a function with an implicit return value called Vec<T>::iterator, which isn't your intent at all. This is one area where C++'s parsing gets really stupid, and a lot of it has to do with backward compatibility.

And you don't need the Vec:: on the position type at all because at that point the typing is in the class scope. You had it wrong anyways, as you'd need to specify the template parameter there as well if you did fully qualify it.

I should also point out that it looks suspiciously like this is a definition of a templated function in a .cpp source file. If so, this will need to be moved directly into the class's .h file
 

Exuro

Member
Probably a long shot but does anyone know why this would be displaying a memory map?

Code:
void convolution::convflip(char *argv[])
{
outFile.open(argv[3], ios::out);	
    int k,b;
    for (b = 0; b < sizeH+sizeX-1 ; b++)
    {   Y[b] = 0;
        for (k = 0; k <= b; k++)
        {     if(k >= sizeX)
              {
                 X[k] = 0; 
              }   
              if(sizeH-1-b+k < 0)
              { 
                 invH[sizeH-1-b+k] = 0;      
              }
            Y[b]= Y[b]+invH[sizeH-1-b+k]*X[k]; 
        }
                
    }    
      outFile << "\n\nOutput Array Y[] = ";
    for (i = 0; i < sizeX+sizeH-1 ; i++)
    {
       outFile << "\t" << Y[i];
    }
outFile.close();
}

This was a function taken out of another program that I inserted into mine(part of the assignment) but for some reason when I use it it's posting a memory map type thing in terminal.
 

Slavik81

Member
cpp_is_king said:
What does "posting a memory map" mean? I'm not sure I understand what you're saying this program is doing.
Core dump perhaps? I think his program is crashing. An access to X or Y is probably going out of bounds.

Maybe run it in A debugger. The debugger should stop the program when it crashes so you can see where it went wrong.
 

charsace

Member
Exuro said:
Probably a long shot but does anyone know why this would be displaying a memory map?

Code:
void convolution::convflip(char *argv[])
{
outFile.open(argv[3], ios::out);	
    int k,b;
    for (b = 0; b < sizeH+sizeX-1 ; b++)
    {   Y[b] = 0;
        for (k = 0; k <= b; k++)
        {     if(k >= sizeX)
              {
                 X[k] = 0; 
              }   
              if(sizeH-1-b+k < 0)
              { 
                 invH[sizeH-1-b+k] = 0;      
              }
            Y[b]= Y[b]+invH[sizeH-1-b+k]*X[k]; 
        }
                
    }    
      outFile << "\n\nOutput Array Y[] = ";
    for (i = 0; i < sizeX+sizeH-1 ; i++)
    {
       outFile << "\t" << Y[i];
    }
outFile.close();
}

This was a function taken out of another program that I inserted into mine(part of the assignment) but for some reason when I use it it's posting a memory map type thing in terminal.
You're combining the sizes of two arrays and looping until that combination?
 

barnone

Member
Stuck on the Qt parent thing still. I can't get an instance of my NameController created:

here is my interface in the .h
Code:
NameController(QObject* parent = 0, NameModel* model);

Here is my definition in the .cpp
Code:
NameController::NameController(QObject* parent = 0, NameModel* model)
:m_model(model), m_parent(parent){}

In my main .cpp, I do this:

Code:
NameModel model(0);
NameController controller(0, &model);

Where the first parameter of both is the QObject parent, but I think it's supposed to be 0 since there is no real parent? I'm not sure how to write the declarations for this in main.cpp.

I'm probably making a simple mistake here, but it doesn't work with or without the zeros in my declarations above. I get an error like this:

/namecontroller.h:8: error: default argument missing for parameter 2 of âNameController::NameController(QObject*, NameModel*)â


Thanks for any help provided =)

EDIT: this is the requirement I am trying to fulfill (provided in the project requirements):
Make sure that the constructor takes an QObject* argument to indicate parent-child relationship that will be passed to the base class constructor
 
barnone said:
Stuck on the Qt parent thing still. I can't get an instance of my NameController created:

here is my interface in the .h
Code:
NameController(QObject* parent = 0, NameModel* model);

Here is my definition in the .cpp
Code:
NameController::NameController(QObject* parent = 0, NameModel* model)
:m_model(model), m_parent(parent){}

In my main .cpp, I do this:

Code:
NameModel model(0);
NameController controller(0, &model);

Where the first parameter of both is the QObject parent, but I think it's supposed to be 0 since there is no real parent? I'm not sure how to write the declarations for this in main.cpp.

I'm probably making a simple mistake here, but it doesn't work with or without the zeros in my declarations above. I get an error like this:

/namecontroller.h:8: error: default argument missing for parameter 2 of âNameController::NameController(QObject*, NameModel*)â


Thanks for any help provided =)

EDIT: this is the requirement I am trying to fulfill (provided in the project requirements):

The particular issue here is not specific to QT, but is actually just a C++ thing. In fact, there are two issues:

1) When you are creating a function that accepts one or more default parameters, the parameters that have default values must come last.

In your example, you have QObject* parent=0 first, but NameModel* model second. If the 'model' parameter also had a default value you'd be fine, but the rule is that no parameters that do not have default values may appear in a parameter list after any other parameter with a default value.

2) Also having to do with default parameters, you specify the default value only in the declaration of the function (i.e. in the .h file).

3) I assume NameController is itself derived from QObject, and the parent you are specifying is actually the parent of the NameController. If that is the case, you do not set the m_parent member directly. This is a member of the base QObject class which is provided for you. It may not even be called m_parent for all you know. All you do is pass the parameter down to the base class's constructor and let it do what it wants with it.

So ultimately, your .h you should look like this:

Code:
NameController(NameModel* model, QObject* parent = 0);

and your .cpp should look like this:

Code:
NameController::NameController(NameModel* model, QObject* parent)
   : QObject(parent)      //Pass the parent down to the base class
   , m_model(model)
{
}
 

jokkir

Member
I have a question that's not really about C++ but I think you guys can help. This is in Perl.

When creating a Poker game, how would I design the check for the Poker hands? I've been thinking about it for a while and the only thing I could come up with is making a ton if/else statements to find it. That wouldn't really be too efficient so I didn't end up doing it.

I'm a bit stumped >__<
 

Wichu

Member
jokkir said:
I have a question that's not really about C++ but I think you guys can help. This is in Perl.

When creating a Poker game, how would I design the check for the Poker hands? I've been thinking about it for a while and the only thing I could come up with is making a ton if/else statements to find it. That wouldn't really be too efficient so I didn't end up doing it.

I'm a bit stumped >__<
First, make sure the hand is sorted so you don't need to worry about ordering. Then, you could use a case statement (or the Perl equivalent)? Or store the hands and point values in a text file, load the file into a hashmap, and index the map with the sorted hand?
 

Exuro

Member
AcciDante said:
What are X and Y arrays of? It's only outputting Y, so it has to be a problem there. Is Y an array of pointers?
It's suppose to be a function for convolution of array X and array H(or in this case invH as its flipped). Y would be the convolution of the two arrays. The program is working in an example where the arrays are not allocated and I was told to just make some arguments to take in to do a file input/output along with allocating memory space with "new". For some reason it's displaying a memory map in the terminal but the convolution itself is working fine.
 

Chris R

Member
Wichu said:
First, make sure the hand is sorted so you don't need to worry about ordering. Then, you could use a case statement (or the Perl equivalent)? Or store the hands and point values in a text file, load the file into a hashmap, and index the map with the sorted hand?

You have to be careful with sorting though, because a straight flush beats a straight. Just have to make sure your grading method can detect that. Also, I'm assuming Texas Hold'em?
 

Wichu

Member
rhfb said:
You have to be careful with sorting though, because a straight flush beats a straight. Just have to make sure your grading method can detect that. Also, I'm assuming Texas Hold'em?
I'm not familiar with poker - could you just do the check for a straight flush before sorting and checking everything else?
 

Slavik81

Member
jokkir said:
I have a question that's not really about C++ but I think you guys can help. This is in Perl.

When creating a Poker game, how would I design the check for the Poker hands? I've been thinking about it for a while and the only thing I could come up with is making a ton if/else statements to find it. That wouldn't really be too efficient so I didn't end up doing it.

I'm a bit stumped >__<
I would create a list of rules that define hands, sorted in order from most valuable to least valuable. Each rule can take a set of cards and return true if the given cards fulfil the rule.

Go through the rules until you find the first rule that matches the hand.
 

Chris R

Member
Wichu said:
I'm not familiar with poker - could you just do the check for a straight flush before sorting and checking everything else?
I wouldn't check for a straight flush every time, just see if the hand has a straight AND a flush if at least 5 of the cards in each set overlap. If there is either a straight or a flush then you can't have a full house or quads (both hands beat a flush) so you are done with grading the hand. If the hand doesn't have a straight or a flush then it might have quads/full house/3 of a kind/two pair/one pair and if none of those hit, you always have your high card.

Again, assuming Texas Hold'em/
 

Margalis

Banned
jokkir said:
I have a question that's not really about C++ but I think you guys can help. This is in Perl.

When creating a Poker game, how would I design the check for the Poker hands? I've been thinking about it for a while and the only thing I could come up with is making a ton if/else statements to find it. That wouldn't really be too efficient so I didn't end up doing it.

I'm a bit stumped >__<

What exactly are you trying to do? See what sort of hand they have and compare it to another hand?

Sounds like you want a lexicographical ordering. Which is a fancy way of saying you have multiple categories for weighting and you compare by comparing each category in order.

So for example let's have two categories: "Hand Type" and "Hand Strength". Hand Type is what type of hand it is - pair, two pair, flush, etc. Hand strength is the the strength of that hand, for example is the pair a pair of twos or a pair of tens?

If a hand is better based on hand type then it wins. If it's the same hand type you have to push on and compare hand strength.

Now if you are talking about just figuring out what type of hand they have I would probably just create one function that checked for each type of hand and returned some info about the hand if it found it. (Like the lexicographical key).

So my code would look something like: (this is NOT perl synax!)

handKey = checkForStraightFlush(hand)
if (!handKey){
handKey = checkForFourKind(hand)
}
if (!handKey){
handKey = checkForFullHouse(hand)
}
etc etc.

If you create functions that can find straights, pairs, etc, you can re-use a lot of code.
 

mackattk

Member
I barely know anything about C++ or programming in general. Unfortunately. as part of my mechanical engineering major, I need to take a C++ class. I haven't had too much trouble until now. I even had the college professor sit down with me for like 20 minutes and he couldn't figure it out either. What the problem is is that i am not getting any errors compiling the code, but when I try to run it it crashes out on me.


Code:
#include <iostream>
#include <string>
using namespace std;
int main()
{
	string firstname[100], scorez[100], tempfirstname, tempscorez;
	int x, y, numtesttaker, loop1, num;
	cout << "Name and Test score sorting program" << endl;
	cout << "This program will sort first names and test scores" << endl;
	cout << "Enter number of test taker" << endl;
	cin >> numtesttaker;
	cout << endl;
	for (num = 0; num < numtesttaker; num++)
	{
	cout << "Enter first name of test takers" << endl;
	cin >> firstname[num];
	cout << "Enter test score" << endl;
	cin >> scorez[num];
	}
	cout << "Here are the people that have taken the test" << endl;
	for (y=0; y < numtesttaker; y++)
	{
		cout << firstname[y] << " " << scorez[y] << endl;
	}
	
	for(y = 0; y < numtesttaker; y++)
	{
		for(x = 0; x < numtesttaker-1; x++)
		{
			if (tempfirstname[x] > tempfirstname[x + 1])
			{
			tempfirstname = firstname[x];
			tempscorez = scorez[x];
			firstname[x] = firstname[x + 1];
			scorez[x] = scorez[x + 1];
			firstname[x+1] = tempfirstname;
			scorez[x+1] = tempscorez;
			}
		}
	}
	cout << "Alphabetically sorted by first name" << endl;
	for(y = 0; y < numtesttaker; y++)
	{
		cout << firstname[y] << " " << scorez[y] << endl;
	}
	cout << "Alphabetically sorted by test score" << endl;

	for(y=0; y < num; y++)
	{
		for(x=0; x < num-1; x++)
		{
			if (tempscorez[x] > tempscorez[x + 1])
			{
			tempscorez = scorez[x];
			tempfirstname = firstname[x];
			scorez[x] = scorez[x + 1];
			firstname[x] = firstname[x + 1];
			scorez[x+1] = tempscorez;
			firstname[x+1] = tempfirstname;
			}
		}
	}
	for (y=0; y < numtesttaker; y++)
	{
		cout << firstname[y] << " " << scorez[y] << endl;
	}

	return EXIT_SUCCESS;
}
 

Margalis

Banned
1. Open Visual Studio
2. Press F5
3. Press "Retry"
4. Look at call stack
5. if (tempfirstname[x] > tempfirstname[x + 1])

What?

More hints in spoilers

You are trying to compare your array of names but are comparing characters in tempfirstname instead. That "tempfirstname" above should be "firstname"

You did the same thing with scorez in the next loop.

You are also storing scorez as strings, which means a score of 11 is lower than a score of 5. You really need to score them as ints of floats or something that will sort arithmetically.

Also you named a variables "scorez." I would deduct points just for that lol.
 

mackattk

Member
Margalis said:
1. Open Visual Studio
2. Press F5
3. Press "Retry"
4. Look at call stack
5. if (tempfirstname[x] > tempfirstname[x + 1])

What?

More hints in spoilers

You are trying to compare your array of names but are comparing characters in tempfirstname instead. That "tempfirstname" above should be "firstname"

You did the same thing with scorez in the next loop.

You are also storing scorez as strings, which means a score of 11 is lower than a score of 5. You really need to score them as ints of floats or something that will sort arithmetically.

Also you named a variables "scorez." I would deduct points just for that lol.

Yeah, its the way the professor likes things named, surprisingly.
 
mackattk said:
What the problem is is that i am not getting any errors compiling the code, but when I try to run it it crashes out on me.


Code:
	for(y = 0; y < numtesttaker; y++)
	{
		for(x = 0; x < numtesttaker-1; x++)
		{
			[b]if (tempfirstname[x] > tempfirstname[x + 1])[/b]
			{
			tempfirstname = firstname[x];
			tempscorez = scorez[x];
			firstname[x] = firstname[x + 1];
			scorez[x] = scorez[x + 1];
			firstname[x+1] = tempfirstname;
			scorez[x+1] = tempscorez;
			}
		}
	}

you are doing a comparison on tempfirstname without initializing it or putting any data in there. the program crashes as soon as it tries to check tempfirstname[x + 1] because string size is 0. i'm not sure you are doing what you want to here anyway, what that line does as it is is compare the first character of a string to the second char of the same string.

don't you want to be comparing first char of one string with first char. of another string?

edit: i'm a really slow typist apparently :|
 

mackattk

Member
Thanks for your help guys. This is why I never got into programming, spend hours trying to find something, and it ends up being a simple mistake. It makes sense why it didn't work.

I had to change the scores to an integer, as the string didn't sort the scores correctly just like you said Margalis.

Hopefully I won't need to ask for much more help as I finish this semester. But I really do appreciate the prompt response.

Thanks!
 

IceCold

Member
mackattk said:
Thanks for your help guys. This is why I never got into programming, spend hours trying to find something, and it ends up being a simple mistake. It makes sense why it didn't work.

I had to change the scores to an integer, as the string didn't sort the scores correctly just like you said Margalis.

Hopefully I won't need to ask for much more help as I finish this semester. But I really do appreciate the prompt response.

Thanks!

Visual Studio's debugger is your friend.
 
fenners said:
A high enough warning level would have allowed even a decent compiler to catch it...

I hope you're not implying that Visual Studio's compiler is not decent. The days of being able to make fun of Visual Studio's shittiness passed about 3-5 years ago
 

Kalnos

Banned
cpp_is_king said:
I hope you're not implying that Visual Studio's compiler is not decent. The days of being able to make fun of Visual Studio's shittiness passed about 3-5 years ago

Yeah it's awesome. The intellisense isn't quite as good with C++ as .NET though.
 

fenners

Member
cpp_is_king said:
I hope you're not implying that Visual Studio's compiler is not decent. The days of being able to make fun of Visual Studio's shittiness passed about 3-5 years ago

Not at all, use it everyday & love it. More commenting on the warning level.
 

RdN

Member
Guys, I'm in need of some help. This function is freezing and I cant find the problem.


I have a matrix which has the distance between cities in a map.

Its supposed to find the less expensive route between two points. If the two points have no relation, the distance between them is -1.

something like the travelling salesman problem
http://en.wikipedia.org/wiki/Travelling_salesman_problem

Anyone?

int menor_caminho(int matrix[79][79], int origin, int destination)
{

if (origin == destination) return (0);
if (matrix[origin][destination] != -1) return (matrix[origin][destination]);
else {
for(int i = 0; i < 79; i++)
{
if(matrix[origin] != -1)
{
return (menor_caminho(matrix, i, destination) + matrix[origin]);
}
}
}
}
 

RdN

Member
Yep, but thats only cause I've changed names from my native language (portuguese) to english. Sorry about that.
 
You need to keep a list of (origin, destination) pairs for which you have already called this function with (a 'closed' list so to speak), and automatically return the previously computed result in that case.

stl::map<pair<int, int>, int>

Would be the easiest way
 

Margalis

Banned
Fixing the freezing isn't going to fix the underlying problems.

This method doesn't prevent cycles and even if it did it only finds a route, not the shortest route.

It looks like you are trying to do this just with the matrix, so I think you basically want to do this:

http://www.fearme.com/misc/alg/node88.html

(The syntax in the above is a little messed up, array indices starting from 1 instead of 0...but the explanation is ok)

Basically the idea is that you start with the matrix that encodes edge adjacency and fill it in such that it encodes shortest paths as well. From there you can just look up any two points.

If you are supposed to use your recursive approach then you need to do at least two things:

1. Throw a min() in and make sure you are taking the shortest route rather than the first route

2. Prevent cycles, either through a separate data structure or by doing something clever with the matrix by inserting new stuff in it. For example if you are about to explore A->B + B->F you could insert -1 in A->B to unlink them, explore that route, then put back in the real value at the end.

int shortestDistance = 100000000;
for(int i = 0; i < 79; i++)
{
if(matrix[origin] != -1)
{
int savedValue = matrix[origin];
matrix[origin] = -1;
shortestDistance = min(shortestDistance, (menor_caminho(matrix, i, destination) + savedValue);
matrix[origin] = savedValue;
}
}

Something like this. I haven't thought about it too much but the idea is you unlink a path so that you can't revisit it, do the recursion, then restore it.

The version above is a little weird in that if you go from A to B and then unlink it you could end up back at A during the recursion, and while you won't then go to B you will go to other things. It would be (MUCH) more efficient to make A unlinked from EVERYTHING , do all the recursion, then restore it. So instead of setting A->B as -1 you would set an entire row/col as -1 (B->A, C->A, etc etc), then restore the entire row/col after looping.

Something like this:

int shortestDistance = 100000000;
int savedDistances[79];

for(int i = 0; i < 79; i++)
{

//unlink each city from the place we are now to prevent loops
savedDistances = matrix[origin]
matrix[origin] = -1

}

for(int i = 0; i < 79; i++)
{

if(matrix[origin] != -1)
{
shortestDistance = min(shortestDistance, (menor_caminho(matrix, i, destination) + matrix[origin]);
}
}

//now restore the previously broken connections
for(int i = 0; i < 79; i++)
{
matix[origin] = savedDistances;
}
 

IceCold

Member
fenners said:
A high enough warning level would have allowed even a decent compiler to catch it...

Yeah, C++'s warning/exception handling is crap. A lot of errors thrown at you from the compiler are not very clear imo. That's why I always preferred coding in Java (not to mention the better IDEs for it like intellij).
 

RdN

Member
Thanks for the replies, guys. You already helped a lot.

I made some changes, but now Im getting new errors (of course).. Its now returning a value, but its not the shortest (always a smaller value). Also, Im getting different values when I do (for example) 1 to 10 and then 10 to 1.

As for the Floyd algorithm, I dont think it'll serve, since I later in the project I'll need to list every vertex it visited.

Could you please take a look again?

Thanks!

Code:
int existe_vet(int vet [100], int n)
{
    for(int i = 0; i<100; i ++)
    {
            if (vet[i] == n)
            return 1;
    }
    return 0;
}
      	
int menor = 9999999 ;
int menor_caminho(int matrix [79][79], int origin, int destination, int visited[100], int j)
{
     if (origin  == destination) return (0);
     if (matrix[origin][destination] != -1) return (matrix[origin][destination]);
          for(int i = 1; i < 79; i++)
          {
                  if(matrix[origin][i] != -1)
                  {
                  
                                       if(existe_vet(visited, i) == 0)
                                       {
                                       visited[j] = i;
                                       j++;
                                       if(((menor_caminho(matrix, i, destination, visited, j)) + matrix[origin][i]) < menor)
                                       {
                                                                  printf("%d\n", i);
                                       menor = (menor_caminho(matrix, i, destination, visited, j) + matrix[origin][i]);
                                       }
                                       }
                  }
          }
          return menor;
}
 

Lathentar

Looking for Pants
RdN said:
Thanks for the replies, guys. You already helped a lot.

I made some changes, but now Im getting new errors (of course).. Its now returning a value, but its not the shortest (always a smaller value). Also, Im getting different values when I do (for example) 1 to 10 and then 10 to 1.

As for the Floyd algorithm, I dont think it'll serve, since I later in the project I'll need to list every vertex it visited.

Could you please take a look again?

Thanks!
Use the
Code:
 syntax instead of quotes. Retains the syntax making it easier to read.
 
Why does your "visited" list only have 100 entries? Surely there are more than 100 paths through a graph represented by a 79x79 adjacency matrix.
 
RdN said:
Visited lists the vertexes I already visited.

I don't think that's what you want. You want a list of the paths you've already solved the problem for. So you need a lookup table of some sort that is keyed on both origin and destination, and the value that is returned by the lookup is the answer. The first line of the function should be to check if an entry already exists for the combination of (origin, destination) specified in the argument list, and if so it should return the corresponding value.
 

BlueMagic

Member
So I need to make a random layout of a dungeon (think The binding of Isaac). With this I don't mean the layout of the rooms themselves, but the layout of the dungeon.
Right now I have a 10x10 matrix filled with zeroes. I choose a random starting point, and then randomly move 1 place (either up, left, right, or down), repeating this last step a certain number of times.

This works well mostly, except it sometimes generates layouts that are straight horizontal or vertical, such as this:

00000100
00000100
00000100
00000100
00000000

Is there any awesome algorithm that randomly creates paths (mazes?) in a somewhat more natural way? Like more branched out and whatnot.

Thanks in advance!
 

usea

Member
BlueMagic said:
So I need to make a random layout of a dungeon (think The binding of Isaac). With this I don't mean the layout of the rooms themselves, but the layout of the dungeon.
Right now I have a 10x10 matrix filled with zeroes. I choose a random starting point, and then randomly move 1 place (either up, left, right, or down), repeating this last step a certain number of times.

This works well mostly, except it sometimes generates layouts that are straight horizontal or vertical, such as this:

00000100
00000100
00000100
00000100
00000000

Is there any awesome algorithm that randomly creates paths (mazes?) in a somewhat more natural way? Like more branched out and whatnot.

Thanks in advance!
There are indeed many awesome algorithms for this. Take, for example, a variable which defined the chance of turning. It could start at some number (say 0.2) and increase which each successive straight movement. That's just a simple example.

Another problem is that you won't have many branches. Your algorithm as it starts will just create a twisty tunnel, each room having exactly 2 doors (entrance and exit) except the ends of the tunnel. You need to have a chance of branching off. You might implement this as a recursive call to the function that's doing this tunneling.

Here are some starts for you (after a quick google): http://en.wikipedia.org/wiki/Maze_generation_algorithm
http://pcg.wikidot.com/pcg-algorithm:dungeon-generation

By the end you will probably have a ton of different variables with initial values that live throughout your program. I would recommend organizing them all somewhere so that you can tweak them easily and run the program again and again to get it the way you like it.
 

Haly

One day I realized that sadness is just another word for not enough coffee.
You can set weights to each direction (north, south, east, west), so that every time you move in that direction, the chances of moving in that direction again are smaller.

Then you can just start tweaking weights to generate dungeons that tend to be vertical or horizontal or diagonal.
 
Status
Not open for further replies.
Top Bottom