QCircularBuffer has exactly what I need, but adding Qt3D to our compiler bloats the build too much and I'm the only one who needs it so I'm looking for some help figuring out how to write this kind of functionality.
QRingbuffer also is an additional include that I cannot use. This needs to be accomplished without adding any new libraries.
I'm using c++ and I've seen a couple of ideas but they always include using QLists without limiting its size.
I need the QList to be limited to say 10 items, and once the tenth item has been added, the old items are overwritten and new items are pushed to the front.
So for example, if the array contains [0,1,2,3,4,5,6,7,8,9], and we continue adding elements, we'll see this:
[10,1,2,3,4,5,6,7,8,9]
[11,10,2,3,4,5,6,7,8,9]
[12,11,10,3,4,5,6,7,8,9]
[13,12,11,10,4,5,6,7,8,9]
etc
Here is what I'm doing currently:
if(list.size() > 10)
list.push_front(newItem);
else
list.push_back(newItem);
Obviously this isn't limiting the size of the list, and it's not overwriting the oldest items, only the first.
Any help would be wonderful.
If you want them to push from the front with a max of ten then I would do something like this:
//somewhere higher up (maybe static) int curIndex = 0;
static const int LIST_SIZE = 10;
if(list.size() >= LIST_SIZE) //added an = here to make it 10 elements
{
list.removeAt(curIndex);
list.push_front(newItem);
curIndex = (curIndex + 1) % LIST_SIZE;
}
else
list.push_back(newItem);
Note: I do not have a compiler off hand to test this.
Related
I developed a game in C++, and want to make sure everything is properly done.
Is it a good solution to use a QHashIterator to check which item in the list has the lowest value (F-cost for pathfinding).
Snippet from my code:
while(!pathFound){ //do while path is found
QHashIterator<int, PathFinding*> iterator(openList);
PathFinding* parent;
iterator.next();
parent = iterator.value();
while(iterator.hasNext()){ //we take the next tile, and we take the one with the lowest value
iterator.next();
//checking lowest f value
if((iterator.value()->getGcost() + iterator.value()->getHcost()) < (parent->getGcost() + parent->getHcost())){
parent = iterator.value();
}
}
if(!atDestionation(parent,endPoint)){ //here we check if we are at the destionation. if we are we return our pathcost.
clearLists(parent);
filllists(parent,endPoint);
}else{
pathFound = true;
while(parent->hasParent()){
mylist.append(parent);
parent = parent->getParent();
}
pathcost = calculatePathCost(mylist); //we calculate what the pathcost is and return it
}
}
If no? Are there better improvements?
I also found someting about the std::priority_queue. It this mutch better then a QHashIterator?
It's maybe not a problem with gameworld where there which are not big. But i'm looking for a suitable solution when the game worlds are big (like + 10000 calculations).Any marks?
Here you basically scan the whole map to find the element that is the minimum one according to some values:
while(iterator.hasNext()){ //we take the next tile, and we take the one with the lowest value
iterator.next();
//checking lowest f value
if((iterator.value()->getGcost() + iterator.value()->getHcost()) < (parent->getGcost() + parent->getHcost())){
parent = iterator.value();
}
}
All this code, if you had an stl container, for instance a map, could be reduced to:
auto parent = std::min_element(iterator.begin(), iterator.end(), [](auto& lhs, auto& rhs)
{ lhs.value()->getGcost() + lhs.value()->getHcost()) < (rhs.value()->getGcost() + rhs.value()->getHcost() }
Once you have something easier to understand you can play around with different containers, for instance it might be faster to hold a sorted vector in this case.
)
Your code does not present any obvious problems per se, often performance gains are not conquered by optimizing little loops, it's more on how you code is organized. For instance I see that you have a lot of indirections, those cost a lot in cache misses. Or if you have to always find the minimum element, you could cache it in another structure and you would have it at a constant time, all the time.
I'm doing this slot machine game where a 3x3 2D-array is being generated with random letters.
I have successfully made the game work as I want but I wonder if you have any tips on how I can optimize or improve my code.
What I've gotten my code to do:
Generate an 2D-array (3x3) and randomly assign chars out of 3
letters.
An "if" that will compare and see what elements in the array belong
to each other (same char next to eachother for getting
columns/rows/diagonals).
An "if else" that will take total amount of columns/rows/diagonals
and make a prize out of it, depending on total amounts of row in the
slot machine and the bet.
So I'm now wondering if you have any suggestions on how I can improve the "if" code where the program checks if there are any rows/columns/diagonals? The game works as it should but I just wonder if there's any way of optimizing it - Perhaps with a "for-loop"?
I also wonder if you have any tips on the "prize" code where the code calculates total amout of rows/columns/diagonals and multiplies that with the bet.
I mean, there must be a way to optimize this. If I was to do a 100x100 array, the code where the elements are compared would be awfully long :)
I'm new to C++ (this is a course) so I'm looking forward to optimize this.
PS! I'm not asking for a solution but rather suggestions/tips of methods I can use to optimize it.
This is a homework so no solutions please, only suggestions/tips!
My code for the array comparison and prize calculation:
To optimize, running a profiler would give you a lot of information. If you're talking about general guidelines to optimizing your application, here are some:
1 - use threads to process in parallel
2 - reduce cache miss by keeping the data properly aligned depending on the processing done on it. For instance, if you need to use the speed to process the position, keeping them both near each other in memory will reduce cache-misses.
ie:
struct Particle
{
float position;
float speed;
};
Particle particles[NUM_PARTICLES];
vs
float positions[NUM_PARTICLES];
float speeds[NUM_PARTICLES];
3- Don't process what you don't need to process or user can't see. For instance, some stuff may not affect the current states - no need to process it (in graphics, we use scene management like octtrees but the same applies to all - if you don't need it, don't process it).
4- Reduce the amount of floating point operations.
See this post as well - it provices with some good C++ references for optimizations: C++ Optimization Techniques.
About optimizing:
Don't optimize prematurely - it won't help anything. I'm too lazy to write about that, but search internet, read "Code Complete" and "C++ Coding Standards: 101 Rules, Guidelines, and Best Practices" books.
Don't waste - if optimization won't take more time and is at same readability level, than you can use it.
Optimize AFTER a speed problem arise.
About your problem:
You are absolutely right that there should be better ways to write a code. What you wrote is what workers do, but you need to be smart programmer to make it more easy.
But what you need is more knowledge about language.
Yes, there is a looping possibility for C++. For example following code checks whether a line contains same values:
const int rowCount = 3; // Number of rows
const int colCount = 3; // Number of columns
// Variable for counting same rows
int sameRowsCount = 0;
// Following line is loop: first it sets variable row to 0
// and for each pass it increments it until rowCount is reached
for(int row = 0; row < rowCount; ++row)
{
// This variable stores whether the row contains same values.
// At beginning we assume that it does.
bool isSame = true;
// Now we will check each column in current row. Note that
// we begin with 1 and not 0 - at 0 position is value which
// we check against all others.
for(int col = 1; (col < colCount) && isSame; ++col)
{
if(matrix[0] != matrix[col])
{
// We found different values
isSame = false;
}
}
// If row contains same values, isSame remained true and
// we increment same-rows counter.
if(isSame)
{
++sameRowsCount;
}
}
cout << "Number of same rows: " << sameRowsCount << "." << endl;
Depends on the array size(s) as you mentioned. With small arrays the if statements may be more efficient than using a loop (or two nested) to iterate over all the elements (this is also called 'loop unrolling' and is considered a performance improvement).
To 'optimize' (I'd better say generalize) your code for any array sizes you should use for loops of course to iterate over the x/y indices.
Completed code:
//Check all horiztonal and vertical locations
for(int i = 0; i <= 2; i++)
{
if(matris[i][0] == matris[i][1] && matris[i][1] == matris[i][2])
rows++;
if(matris[0][i] == matris[1][i] && matris[1][i] == matris[2][i])
rows++;
}
//Now check diagonals
if(matris[0][0] == matris[1][1] && matris[1][1] == matris[2][2])
if(matris[0][2] == matris[1][1] && matris[1][1] == matris[2][0])
//Calculate prize
prize = g_satsning*(1 << rows);
In terms of speed, what you have is not going to be inefficient. If you are looking to generalize the code and make it scalable (e.g. if you wanted to add 2 more rows/columns), there are several things you could do (e.g. looping and a more mathematical form of prize calculation).
The looping has already been discussed, but the prize calculation could be simplified a bit using something like the following:
if (rows > 0 && rows < SOMEMAXIMUMVALUE)
{
prize = g_satsning * (1 << rows);
}
else
{
prize = 0;
}
Since your multiplier is an exponent of 2, the math is fairly straight forward. SOMEMAXIMUMVALUE should be declared to be the maximum number of matching rows you expect. For a 3x3 setup, there would be 8 potential matches (3 rows, 3 columns, 2 diagonals), so SOMEMAXIMUMVALUE should be set to 8.
I have a vector holding 10 items (all of the same class for simplicity call it 'a'). What I want to do is to check that 'A' isn't either a) hiding the walls or b) hiding another 'A'. I have a collisions function that does this.
The idea is simply to have this looping class go though and move 'A' to the next position, if that potion is causing a collision then it needs to give itself a new random position on the screen. Because the screen is small, there is a good chance that the element will be put onto of another one (or on top of the wall etc). The logic of the code works well in my head - but debugging the code the object just gets stuck in the loop, and stay in the same position. 'A' is supposed to move about the screen, but it stays still!
When I comment out the Do while loop, and move the 'MoveObject()' Function up the code works perfectly the 'A's are moving about the screen. It is just when I try and add the extra functionality to it is when it doesn't work.
void Board::Loop(void){
//Display the postion of that Element.
for (unsigned int i = 0; i <= 10; ++i){
do {
if (checkCollisions(i)==true){
moveObject(i);
}
else{
objects[i]->ResetPostion();
}
}
while (checkCollisions(i) == false);
objects[i]->SetPosition(objects[i]->getXDir(),objects[i]->getYDir());
}
}
The class below is the collision detection. This I will expand later.
bool Board::checkCollisions(int index){
char boundry = map[objects[index]->getXDir()][objects[index]->getYDir()];
//There has been no collisions - therefore don't change anything
if(boundry == SYMBOL_EMPTY){
return false;
}
else{
return true;
}
}
Any help would be much appreciated. I will buy you a virtual beer :-)
Thanks
Edit:
ResetPostion -> this will give the element A a random position on the screen
moveObject -> this will look at the direction of the object and adjust the x and Y cord's appropriately.
I guess you need: do { ...
... } while (checkCollisions(i));
Also, if you have 10 elements, then i = 0; i < 10; i++
And btw. don't write if (something == true), simply if (something) or if (!something)
for (unsigned int i = 0; i <= 10; ++i){
is wrong because that's a loop for eleven items, use
for (unsigned int i = 0; i < 10; ++i){
instead.
You don't define what 'doesn't work' means, so that's all the help I can give for now.
There seems to be a lot of confusion here over basic language structure and logic flow. Writing a few very simple test apps that exercise different language features will probably help you a lot. (So will a step-thru debugger, if you have one)
do/while() is a fairly advanced feature that some people spend whole careers never using, see: do...while vs while
I recommend getting a solid foundation with while and if/else before even using for. Your first look at do should be when you've just finished a while or for loop and realize you could save a mountain of duplicate initialization code if you just changed the order of execution a bit. (Personally I don't even use do for that any more, I just use an iterator with while(true)/break since it lets me pre and post code all within a single loop)
I think this simplifies what you're trying to accomplish:
void Board::Loop(void) {
//Display the postion of that Element.
for (unsigned int i = 0; i < 10; ++i) {
while(IsGoingToCollide(i)) //check is first, do while doesn't make sense
objects[i]->ResetPosition();
moveObject(i); //same as ->SetPosition(XDir, YDir)?
//either explain difference or remove one or the other
}
}
This function name seems ambiguous to me:
bool Board::checkCollisions(int index) {
I'd recommend changing it to:
// returns true if moving to next position (based on inertia) will
// cause overlap with any other object's or structure's current location
bool Board::IsGoingToCollide(int index) {
In contrast checkCollisions() could also mean:
// returns true if there is no overlap between this object's
// current location and any other object's or structure's current location
bool Board::DidntCollide(int index) {
Final note: Double check that ->ResetPosition() puts things inside the boundaries.
I am currently working on a A* search algorithm. The algorithm would just be solving text file mazes. I know that the A* algorithm is supposed to be very quick in finding the finish. Mine seems to take 6 seconds to find the path in a 20x20 maze with no walls. It does find the finish with the correct path it just takes forever to do so.
If I knew which part of code was the problem I would just post that but I really have no idea what is going wrong. So here is the algorithm that I use...
while(!openList.empty()) {
visitedList.push_back(openList[index]);
openList.erase(openList.begin() + index);
if(currentCell->x_coor == goalCell->x_coor && currentCell->y_coor == goalCell->y_coor)
}
FindBestPath(currentCell);
break;
}
if(map[currentCell->x_coor+1][currentCell->y_coor] != wall)
{
openList.push_back(new SearchCell(currentCell->x_coor+1,currentCell->y_coor,currentCell));
}
if(map[currentCell->x_coor-1][currentCell->y_coor] != wall)
{
openList.push_back(new SearchCell(currentCell->x_coor-1,currentCell->y_coor,currentCell));
}
if(map[currentCell->x_coor][currentCell->y_coor+1] != wall)
{
openList.push_back(new SearchCell(currentCell->x_coor,currentCell->y_coor+1,currentCell));
}
if(map[currentCell->x_coor][currentCell->y_coor-1] != wall)
{
openList.push_back(new SearchCell(currentCell->x_coor,currentCell->y_coor-1,currentCell));
}
for(int i=0;i<openList.size();i++) {
openList[i]->G = openList[i]->parent->G + 1;
openList[i]->H = openList[i]->ManHattenDistance(goalCell);
}
float bestF = 999999;
index = -1;
for(int i=0;i<openList.size();i++) {
if(openList[i]->GetF() < bestF) {
for(int n=0;n<visitedList.size();n++) {
if(CheckVisited(openList[i])) {
bestF = openList[i]->GetF();
index = i;
}
}
}
}
if(index >= 0) {
currentCell = openList[index];
}
}
I know this code is messy and not the most efficient way to do things but I think it should still be faster then what it is. Any help would be greatly appreciated.
Thanks.
Your 20x20 maze has no walls, and therefore many, many routes which are all the same length. I'd estimate trillions of equivalent routes, in fact. It doesn't seem so bad when you take that into account.
Of course, since your heuristic looks perfect, you should get a big benefit from excluding routes that are heuristically predicted to be precisely as long as the best route known so far. (This is safe if your heuristic is correct, i.e. never overestimates the remaining distance).
Here is a big hint.
If ever you find two paths to the same cell, you can always throw away the longer one. If there is a tie, you can throw away the second one to get there.
If you implement that, with no other optimizations, the search would become more than acceptably fast.
Secondly the A* algorithm should only bother backtracking if the length to the current cell plus the heuristic exceeds the length to the current cell plus the heuristic for any other node. If you implement that, then it should directly find a path and stop. To facilitate that you need to store paths in a priority queue (typically implemented with a heap), not a vector.
openList.erase is O(n), and the for-loop beginning with for(int i=0;i<openList.size();i++) is O(n^2) due to the call to CheckVisited - these are called every iteration, making your overall algorithm O(n^3). A* should be O(n log n).
Try changing openList to a priority-queue like it's supposed to be, and visitedList to a hash table. The entire for loop can then be replaced by a dequeue - make sure you check if visitedList.Contains(node) before enqueuing!
Also, there is no need to recalculate the ManHattenDistance for every node every iteration, since it never changes.
Aren't you constantly backtracking?
The A* algorithm backtracks when the current best solution becomes worse than another previously visited route. In your case, since there are no walls, all routes are good and never die (and as MSalters correctly pointed, there are several of them). When you take a step, your route becomes worse than all the others that are one step shorter.
If that is true, this may account for the time taken by your algorithm.
I finally determined that this function is responsible for the majority of my bottleneck issues. I think its because of the massively excessive random access that happens when most of the synapses are already active. Basically, as the title says, I need to somehow optimize the algorithm so that I'm not randomly checking a ton of active elements before landing on one of the few that are left.
Also, I included the whole function in case of other flaws that can be spotted.
void NetClass::Explore(vector <synapse> & synapses, int & n_syns) //add new synapses
{
int size = synapses.size();
assert(n_syns <= size );
//Increase the age of each active synapse by 1
Age_Increment(synapses);
//make sure there is at least one inactive vector left
if(n_syns == size)
return;
//stochastically decide whether a new connection is added
if((rand_r(seedp) %1000) < ( x / (1 +(n_syns * ( y / 100)))))
{
n_syns++; //a new synapse has been created
//main inefficiency here
while(1)
{
int syn = rand_r(seedp) % (size);
if (!synapses[syn].active)
{
synapses[syn].active = true;
synapses[syn].weight = .04 + (float (rand_r(seedp) % 17) / 100);
break;
}
}
}
}
void NetClass::Age_Increment(vector <synapse> & synapses)
{
for(int q=0, int size = synapses.size(); q < size; q++)
if(synapses[q].active)
synapses[q].age++;
}
Pass a random number, k, in the range [0, size-n_syns) to Age_Increment. Have Age_Increment return the kth empty slot.
Since you're already traversing the whole list in Age_Increment, update that function to return the list of the indexes of inactive synapses.
You can then pick a random item from that list directly.
This is similar to the problem of finding free blocks in memory management, so I would take a look at algorithms used in that domain, specifically free lists, which is a list of free positions. (These are usually implemented as linked lists to be able to pop elements off an end efficiently. Random access in a linked list would still be O(n) - with a smaller n, but still not the best choice for your use case.)