It's my first time posting here, but I always look for some ideas between your posts.
I'm trying to fill the upper half of an array accordingly to the other filled cells (all with 0s and 1s), something like this:
if (matrix[3,2] == 1) and (matrix[3,1] == 1){
matrix[2,1] = 1;}
After much trying, I've made something that barely works with:
matrix[a][b] = 1;
for (unsigned int i = 0; i < max_index; i++){
if (matrix[i][a] == 1){
matrix[i][b] = 1;
}
}
But all I can do is wait for a matrix[corner_i.v1][corner_i.v2] that fills some gaps that shouldn't exists... like this [0, 2]:
01011
00111
00011
00001
00000
Can you guys give me some advices or show some way that I can make this happen? Thank you all.
[edit 2]:
I figured out this was left, but the code still not working at 100%:
for (unsigned int i = 0; i < max_index; i++){
if (matriz[i][a] == 1){
matriz[i][b] = 1;
}
else if (matriz[b][i] == 1){
matriz[a][i] = 1;
}
}
Output be like
[EDIT 3]:
I've solved part of the problem in the function void conectar_matriz(), but some of the inputs seems to bug the program, specially matrices over 40x40.
https://pastebin.com/L3GsciK0
Related
I'm learning Artificial Intelligence from a book, the book vaguely explains the code I'm about to post here, I assume because the author assumes everyone has experienced hill climbing algorithm before. The concept is rather straightforward, but I just don't understand some of the code below and I'd like someone to help me understand this algorithm a bit clearer before I move on.
I commented next to the parts that confuses me most, a summary of what these lines are doing would be very helpful to me.
int HillClimb::CalcNodeDist(Node* A, Node* B)
{
int Horizontal = abs(A->_iX - B->_iX);
int Vertical = abs(A->_iY - B->_iY);
return(sqrt(pow(_iHorizontal, 2) + pow(_iVertical, 2)));
}
void HillClimb::StartHillClimb()
{
BestDistance = VisitAllCities();
int CurrentDistance = BestDistance;
while (true)
{
int i = 0;
int temp = VisitAllCities();
while (i < Cities.size())
{
//Swapping the nodes
Node* back = Cities.back();
Cities[Cities.size() - 1] = Cities[i];
Cities[i] = back; // Why swap last city with first?
CurrentDistance = VisitAllCities(); // Why visit all nodes again?
if (CurrentDistance < BestDistance) // What is this doing?
{
BestDistance = CurrentDistance; //???
break;
}
else
{
back = Cities.back();
Cities[Cities.size() - 1] = Cities[i];
Cities[i] = back;
}
i++;
}
if (CurrentDistance == temp)
{
break;
}
}
}
int HillClimb::VisitAllCities()
{
int CurrentDistance = 0;
for (unsigned int i = 0; i < Cities.size(); i++)
{
if (i == Cities.size() - 1)//Check if last city, link back to first city
{
CurrentDistance += CalcNodeDist(Cities[i], Cities[0]);
}
else
{
CurrentDistance += CalcNodeDist(Cities[i], Cities[i + 1]);
}
}
return(CurrentDistance);
}
Also the book doesn't state what type of hill climb this is. I assume it's basic hill climb as it doesn't restart when it gets stuck?
Essentially, it does this in pseudo-code:
initialize an order of nodes (that is, a list) which represents a circle
do{
find an element in the list so that switching it with the last element of the
list results in a shorter length of the circle that is imposed by that list
}(until no such element could be found)
VisitAllCities is a helper that computes the length of that circle, CalcNodeDist is a helper that computes the distance between two nodes
the outer while loop is what I called do-until, the inner while loop iterates over all elements.
The if (CurrentDistance < BestDistance) part simply checks whether changing that list by swapping results in a smaller length, if so, update the distance, if not, undo that change.
Did I cover everything you wanted to know? Question about a particular part?
I am making a little game (just console) and my vectors don't act like I think they have to. One Value of the vector just changes and I don't know why. The Code shown below is part where this bug come from, I have deleted the rest of the code where these 2 vectors show up and the bug still appears and I DONT KNOW WHY!!
This part of the code is responsible for letting the Enemy spread to a random direction.
/**in this part the first value of the 2 vectors are created
(only once, I've tested it)**/
if(moves == 0){
int randomNum1 = (rand() % HEIGHT)+1;
int randomNum2 = (rand() % WIDTH)+1;
_EnemysY.push_back(randomNum1);
_EnemysX.push_back(randomNum2);
}
/**_Enemy vectors have normal values. For instance: _EnemysX[0]
is 23 and _EnemysY[0] is 12**/
/**In this part, the Enemy spreads in a random direction**/
if (moves > 3){
//save Enemys at the border here (those who can move)
std::vector<int> topX;
std::vector<int> topY;
std::vector<int> botX;
std::vector<int> botY;
std::vector<int> rigX;
std::vector<int> rigY;
std::vector<int> lefX;
std::vector<int> lefY;
/**here, I wanna save all Fields of the Enemy where it can spread to:**/
for (Uint it = 0; it < _EnemysY.size(); it++){
/**_EnemysY is still normal, but _EnemysX is like: 86BF163E0**/
if (_map[_EnemysY[it]-1][_EnemysX[it]] == _Grenade || _map[_EnemysY[it]-1][_EnemysX[it]] == _Field){
topY.push_back(_EnemysY[it]);
topX.push_back(_EnemysX[it]);
}
if (_map[_EnemysY[it]+1][_EnemysX[it]] == _Grenade || _map[_EnemysY[it]+1][_EnemysX[it]] == _Field){
botY.push_back(_EnemysY[it]);
botX.push_back(_EnemysX[it]);
}
if (_map[_EnemysY[it]][_EnemysX[it]-1] == _Grenade || _map[_EnemysY[it]][_EnemysX[it]-1] == _Field){
lefX.push_back(_EnemysX[it]);
lefY.push_back(_EnemysY[it]);
}
if (_map[_EnemysY[it]][_EnemysX[it]+1] == _Grenade || _map[_EnemysY[it]][_EnemysX[it]+1] == _Field){
rigX.push_back(_EnemysX[it]);
rigY.push_back(_EnemysY[it]);
}
}
/**and here is a random direction created and the programm
chooses which Field it will spread to: **/
for (;;){
int ranDir = (rand() % 4)+1;
if (ranDir == 1 && !topY.empty()){
int temp = (rand() % topY.size())+1;
_EnemysY.push_back(topY[temp]);
_EnemysX.push_back(topX[temp]);
return true;
}
if (ranDir == 2 && !botY.empty()){
int temp = (rand() % botY.size())+1;
_EnemysY.push_back(botY[temp]);
_EnemysX.push_back(botX[temp]);
return true;
}
if (ranDir == 3 && !lefY.empty()){
int temp = (rand() % lefY.size())+1;
_EnemysY.push_back(lefY[temp]);
_EnemysX.push_back(lefX[temp]);
return true;
}
if (ranDir == 4 && !rigY.empty()){
int temp = (rand() % rigY.size())+1;
_EnemysY.push_back(rigY[temp]);
_EnemysX.push_back(rigX[temp]);
return true;
}
}
}
First off, why not have a struct describing the "enemy", including its position (via two fields X and Y)? It would improve the code a bit and avoid the need for two vectors that are meaningless if separated.
On topic:
int temp = (rand() % rigY.size())+1;
_EnemysY.push_back(rigY[temp]);
rand() % rigY.size() will give you a number in the interval [0, rigY.size() ). You then add 1 to both sides so temp would be in the interval [1, rigY.size() ].
But rigY[rigY.size()] is not a valid element in the vector...
First of all: thank you Andrei and PaulMcKenzie for your time, your answers didn't solve the problem, but they were still usefull. :)
Now to the answer of the problem:
Alright! I'm a complete douchebag! Because what I didn't print in the code above, was my std::cout s for my variables and I accidentally wrote: "std::cout << ... << std:cout << ... std::endl" and for some reason the second "std::cout" caused a bug, where it printed out an ridiculously high number. So my code in general (without the cout s) works fine, but I still changed some things which you said.
Ok so I have simple function that returns the highest non-pair card from a 5 card poker hand. But he problem I'm having is wierd. There is this random bus error that occurs randomly, and I don't know for what reason. I thought it was the print statements I was using but now I'm not sure. I know it looks a mess, but if you look at the line below where I print the words "test print", can someone tell me why immediately after this line theres a bus error and it doesn't get to the second "test print" statement. Could I have run out of memory for my program??? That probably makes no sense, but I can't really think of anything else (please exclude the slightly confusing code):
int Hand::highestNonPair(int *face_array_exclude, int size)
{
int highest = 0;
int contains_excludable = 0;
int i = 0;
if(this->hasAnother(i) == false)
highest = cards[i]->getFace();
for(i= 0;i<cards.size();i++)
{
if((cards[i+1]->getFace() > cards[i]->getFace()) &&
(this->hasAnother(i) == false)){
if(size>0){
for(int c = 0;c<size;c++){
if(cards[i]->getFace() == face_array_exclude[c])
contains_excludable = 1;
}
}
if(!contains_excludable)
highest = cards[i+1]->getFace();
cout<<\nTEST PRINT"<<endl;
contains_excludable = 0;
cout<<\nTEST PRINT"<<endl;
}
}
return highest;
}
The bit can case problems:
if((cards[i+1]->getFace() > cards[i]->getFace()) &&
As the highest value of i could be cards.size() - 1. This would mean that cards[i+1 will be an invalid entry.
Change the loop:
for(i= 0;i<cards.size();i++)
to
for(i= 0;i<cards.size() - 1;i++)
Perhaps
Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 11 years ago.
Improve this question
I have been programming for about 3 years now and feel confident in my skills. But recently I began working alongside embedded systems and working on other peoples code and have begun to question how good my code is.
I see all these complex answers on SO and think I would have done that with a vector and if statements and wonder if I am any more than a beginner as I was self taught and don't really know my level.
So I was wondering if more experienced programmers could show me ho to do things better.
This is code I wrote to for an rpg game to pick a target to attack. using it as an example could you show me better/more advanced/professional ways of doing it.
int FindTarget(Player &player);
{
int aimPoint[5] = 0;
for(int i = 0; i <= 5; i++)
{
if(player.team[i].exist == true)
{
// set random starting point between 1 - 3
aimPoint[i] = random /3;
// add a point if you hve an elemental advantage minus if not
if(player.team[i].type == weak)
{
aimPoint += 1;
}
else if(player.team[i].type == strong)
{
aimPoint -= 1;
}
//add for front row minus for back
if(i == 1 || i== 3)
{
aimPoint += 1;
}
else
{
aimPoint -= 1;
}
}
}
return 0;
}
EDIT: If you don't have the time or effort to show me examples I would appreciate a good book that a beginner/intermediate could understand.
Comment #1:
This line starts at 0, and goes exactly once? Why is it a loop?
for(int i = 0; i <= 0; i++)
Comment #2:
Don't compare a boolean against true.
if(player.team[i].exist == true)
Just re-write it to:
if(player.team[i].exist)
Comment #3:
Professionals rarely use hardcoded values.
Why is this value 5?
int aimPoint[5] = 0;
Instead, make it clear:
int aimPoint[TARGET_SIZE] = 0;
Similarly, change
aimPoint[i] = random /3;
to:
aimPoint[i] = random /INITIAL_TARGET_VALUE;
This is pointless; it's not a loop, it's a single pass.
for(int i = 0; i <= 0; i++)
ahem since nobody mentioned it, let me point this one out:
int FindTarget(Player &player);
{
int aimPoint[5] = 0;
...
return 0
}
to roughly
void FindTarget(const Player &player)
{
std::vector<int> aimPoint(5, 0);
...
}
Also, since there is no knowing what the code should do (and how 'aimPoint' is related to teams; guessing doesn't help because none of it is used, aimPoint is discarded?), I don't have anything else than fixing the obvious breakage that was above
---- Edit from a comment
The handling of random seems misguided. Someone suggested that you might have meant random %3 + 1;
I noted that too but decided there is nothing to base the assumption on. Perhaps random is already an int in the range [3, 12).
Also, random % 3 won't yield a uniform distribution, so you'd need to do something else
For many applications, rand() will perform admirably when used correctly, but with the current sad state of affairs, rand() is very rarely used correctly.
The problem is that of distribution
Here is how I would write it.
void FindTarget(Player &player);
{
int aimPoint[5];
for(int i = 0; i <= 5; ++i)
{
if(!player.team[i].exist)
continue;
// set random starting point between 1 - 3
aimPoint[i] = random / 3;
// add a point if you hve an elemental advantage minus if not
switch(player.team[i].type) {
case weak:
++aimPoint[i];
break;
case strong:
--aimPoint[i];
break;
}
//add for front row minus for back
if(i == 1 || i== 3)
++aimPoint[i];
else
--aimPoint[i];
}
}
That piece of code:
// set random starting point between 1 - 3
aimPoint[i] = random /3;
don't get you random number between 1 and 3, try this:
aimPoint[i] = random % 3 + 1
I'm trying to write a method that takes an array of integers (0-51, in that order), cuts it into two separate arrays (A and B in the below function by using the cut method, which I know for sure works) and then re-fuses the two arrays together by randomly selecting 0, 1 or 2 cards from the BOTTOM of either A or B and then adding them to the deck.
(ps- by "array" I mean linked list, I just said array because I thought it would be conceptually easier)
This is my code so far, it works, but there's a definite bias when it comes to where the cards land. Can anybody spot my logic error?
[code]
void Deck::shuffle(){
IntList *A = new IntList();
IntList *B = new IntList();
cut(A, B);
IntListNode *aMarker = new IntListNode;
aMarker = A->getSentinel()->next;
//cout<< A->getSentinel()->prev->prev->data <<'\n'<<'\n';
IntListNode *bMarker = new IntListNode;
bMarker = B->getSentinel()->next;
//cout<< B->getSentinel()->prev->data;
deckList.clear();
srand(time(NULL));
int randNum = 0, numCards = 0, totalNumCards = 0;
bool selector = true, aisDone = false, bisDone = false;
while(totalNumCards < 52){
randNum = rand() % 3;
if(randNum == 0){
selector = !selector;
continue;
}
numCards = randNum;
if(!aisDone && !bisDone){
if(selector){
for(int i = 0; i < numCards; i++){
deckList.push_back(aMarker->data);
aMarker = (aMarker->next);
if(aMarker == A->getSentinel()){
aisDone = true;
break;
}
}
selector = false;
}else{
for(int i = 0; i < numCards; i++){
deckList.push_back(bMarker->data);
bMarker = (bMarker->next);
if(bMarker == B->getSentinel()){
bisDone = true;
break;
}
}
selector = true;
}
}
if(aisDone && !bisDone){
for(int i = 0; i < (52 - totalNumCards); i++){
deckList.push_back(bMarker->data);
bMarker = (bMarker->next);
if(bMarker == B->getSentinel()){
bisDone = true;
break;
}
}
//return;
}
if(bisDone && !aisDone){
for(int i = 0; i < (52 - totalNumCards); i++){
deckList.push_back(aMarker->data);
aMarker = (aMarker->next);
if(aMarker == A->getSentinel()){
aisDone = true;
break;
}
}
//return;
}
totalNumCards += numCards;
}
int tempSum = 0;
IntListNode *tempNode = deckList.head();
for(int j = 0; j < 52; j++){
//cout<< (tempNode->data) << '\n';
tempSum += (tempNode->data);
tempNode = (tempNode ->next);
}
if(tempSum != 1326)
system("PAUSE");
return;
}
[/code]
What about just using std::random_shuffle? Yeah, it won't work for linked list, but you can change it to vector :)
If your instructor would have the moral to teach you programming the way it should be done then they'd encourage you to solve the problem like so, with four lines of code:
#include<algorithm>
#include<vector>
// ...
std::vector<int> cards; // fill it in ...
std::random_shuffle(cards.begin(), cards.end());
Using the standard library is the right way of doing things. Writing code on your own when you can solve the problem with the standard library is the wrong way of doing things. Your instructor doesn't teach you right. If they want to get a point across (say, have you practice using pointers) then they should be more attentive in selecting the exercise they give you.
That speech given, here is a solution worse than the above but better than your instructor's:
52 times do the following:
Choose two random none-equal integers in the range [0,52).
Swap the values in the array corresponding to these positions.
For most random number generators, the low bits are the least random ones. So your line
randNum = rand() % 3;
should be modified to get its value more from the high- to middle-order bits from rand.
Your expectations may be off. I notice that you swap the selector if your random value is 0. Coupled with the relative non-randomness of randNum, this may be your problem. Perhaps you need to make things less random to make them appear more random, such as swapping the selector every time through the loop, and always taking 1 or more cards from the selected deck.
Comments:
srand(time(NULL));
This should only be called once during an applications run. This it is usally best to call it in main() as you start.
int randNum = 0, numCards = 0, totalNumCards = 0;
bool selector = true, aisDone = false, bisDone = false;
One identifier per line. Every coding standard written has this rule. It also prevents some subtle errors that can creep in when using pointers. Get used to it.
randNum = rand() % 3;
The bottom bits of rand are the lest random.
rand Num = rand() / (MAX_RAND / 3.0);
Question:
if(!aisDone && !bisDone)
{
This can execute
and set one of the above to isDone
Example:
Exit state aisDone == false bsiDone == false // OK
Exit state aisDone == true bsiDone == false // Will run below
Exit state aisDone == false bsiDone == ture // Will run below
}
if(aisDone && !bisDone)
{
Is this allowed to run if the first block above is run?
}
if(bisDone && !aisDone)
{
Is this allowed to run if the first block above is run?
}
The rest is too complicated and I don't understand.
I can think of simpler techniques to get a good shuffle of a deck of cards:
for(loop = 0 .. 51)
{
rand = rand(51 - loop);
swap(loop, loop+rand);
}
The above simulates picking a card at random from the deck A and putting it on the top of deck B (deck B initially being empty). When the loop completes B is now A (as it was done in place).
Thus each card (from A) has the same probability of being placed at any position in B.