Random variables changing for no reason

I am beyond confused and never had this issue before.
To sum up what I am doing: I am trying to make a card game run on the arduino. Basically, the arduino is used to calculate and keep score of all players. The scores are written into the Serial Monitor. however, I have run into a very odd problem.

The whole code is very messy looking, but I have things in place that allow me to keep track of all of the variables after each loop, so I can make sure they are correct. I'll sum up the code and keep it simple.

For the loop, I have it running side commands that I've created so I can keep the loop section neat and tidy. It looks something like this:

void loop(){
Serial.println("Hey, how many players you want?");

countPlayers();   // grabs number typed into Serial Monitor, and saves it as "int pNumber"

Serial.println("Let's start the next round");

StartRound(); // this loops until the round is over, taking player points typed into the SM

displayScores(); // descriptive enough

resetBids();  // resets bids for next round, because they need to be 0 at the start

setNewDealer();  // Shifts dealer number by 1, but if max player is reached, its set to 0 (starting player)
}

There is another command "debug();" , where this command simply puts a list of variables into the SM, that way I can check where all the variables are in between commands. By placing this debug command in between each command, I can see how the variables change. This is where I noticed something going on.

During the countPlayers command, it takes the SM input and saves a variable pNumber as the max players for that game. This should never change unless the arduino is restarted and a new number is set. However, for whatever reason, during the "resetBids" command, it is resetting the pNumber to 0. Here is the code for the "resetBids" command:

int bet[]={0,0,0,0,0,0,0};

void resetBids() {
  for (int x = 0; x < 7; x++) {
    bet[x] = 0;
  }
}

As you can see, pNumber has NOTHING to do with this command. Another thing is, if I switch the command to look like this:

int bet[]={0,0,0,0,0,0,0};

void resetBids() {
bet[0]=0;
bet[1]=0;
bet[2]=0;
bet[3]=0;
bet[4]=0;
bet[5]=0;
bet[6]=0;
}

The command no longer resets pNumber to 0. Does anyone know what's going on? is this just a random bug that I found and I should just stick with my second setup? my concern is that if I don't fix this, it may cause unforseen problems down the road, since I cannot anticipate every order of moves/bets players will make in one game.

Sorry this is long, I appreciate any help you guys can give!!

The compiler can do many optimization. For example, the compiler can do pre-calculations to reduce the calculations that are done during runtime. A variable might not be something with a memory location.
If you change something very little in the code, then the compiler might decide to do other optimizations. As a result, a bug might show itself in a different way, or perhaps not at all.

This is actually how a common memory problem behaves (assuming it is a memory problem). Perhaps you ran out of SRAM, or write beyond the limits of an array, or a pointer is used in the wrong way. Enable the maximum warning level of the compiler, that might help.

May we see the complete sketch ?
Which Arduino board do you use ?

Of course. Like I said, it is a mess and I don't have notations anywhere (probably not helping either), but here is the whole code in it's current state:

int pNum;
int X = -1;
int currentRound = 1;
int dealer = 0;
int currentBet = 1;
int totalPlayer = 0;
int C = 0;
int S;


String player[] = {"", "", "", "", "", "", ""};

int bet[] = {0, 0, 0, 0, 0, 0, 0};
int score[] = {0, 0, 0, 0, 0, 0, 0};


void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.println("How many players do we have?");
  playerCount();
  delay(1000);
  Serial.println("What are their names?");
  getNames();
  delay(1000);
  displayNames();
  delay(1000);
  for (currentRound = 1; currentRound < 8; currentRound++) {
    //    debug();
    Serial.println("Let's start the next round!");
    Serial.print("Round: ");
    Serial.print(currentRound);
    Serial.print("    ");
    Serial.print(player[dealer]);
    Serial.print(" deals: ");
    Serial.print(8 - currentRound);
    Serial.println(" cards");
    Serial.println();
    delay(1000);
    StartRound();
    Serial.println();
    delay(1000);
    //    debug();
    checkBets();
    delay(1000);
    displayScores();
    //    debug();
    resetBets();
    //    debug();
    setDealer();
    delay(1000);
    //    debug();
    delay(1000);
  }
  Serial.println("DONE");
  while (0 == 0) {
  }
}


void debug() {
  Serial.println();
  Serial.print("pNum= ");
  Serial.println(pNum);
  Serial.print("currentBet= ");
  Serial.println(currentBet);
  Serial.print("dealer= ");
  Serial.println(dealer);
  Serial.println();
}


void checkBets(){
  
}


void StartRound() {
  for (totalPlayer = 0; totalPlayer < pNum; totalPlayer++) {
resetBid:
    C = 0;
    Serial.print("What is ");
    Serial.print(player[currentBet]);
    Serial.println("'s bet?");
    if (totalPlayer == pNum - 1) {
      for (int i = 0; i < pNum; i++) {
        C = C + bet[i];
      }
      X = 8 - C - currentRound;
      if (X < 0) {
        Serial.println("You can bet anything!");
      }
      else {
        Serial.print("You cannot bet: ");
        Serial.println(X);
      }
    }
    do {
      if (Serial.available()) {
        S = Serial.parseInt();
        if (S > 8 - currentRound || S == X) {
          Serial.println("Bet is too high, too low, or you can't bet that");
          goto resetBid;
        }
        else {
          bet[currentBet] = S;
          currentBet++;
          break;
        }
      }
    } while (0 == 0);
    Serial.print(player[currentBet - 1]);
    Serial.print("'s bet is: ");
    Serial.println(bet[currentBet - 1]);

    if (currentBet == pNum) {
      currentBet = 0;
    }
  }
}

void setDealer() {
  dealer++;
  if (dealer >= pNum) {
    dealer = 0;
  }
  currentBet = dealer + 1;
  if (currentBet == pNum) {
    currentBet = 0;
  }
}


void displayScores() {
  for (int i = 0; i < pNum; i++) {
    Serial.print(player[i]);
    Serial.print("= ");
    Serial.print(score[i]);
    Serial.print("  |  ");
  }
  Serial.println();
  Serial.println();
}


void resetBets() {
  //  for (int x = 0; x < 8; x++) {
  //    bet[x] = 0;
  //    delay(10);
  //  }
  bet[0] = 0;
  bet[1] = 0;
  bet[2] = 0;
  bet[3] = 0;
  bet[4] = 0;
  bet[5] = 0;
  bet[6] = 0;
}


void displayNames() {
  for (int i = 0; i < pNum; i++) {
    Serial.print(player[i]);
    Serial.print("  |  ");
  }
  Serial.println();
  Serial.println();
}


void getNames() {
  for (int i = 0; i < pNum; i++) {
    while (0 == 0) {
      if (Serial.available()) {
        player[i] = Serial.readString();
        Serial.print("Player ");
        Serial.print(i + 1);
        Serial.print(": ");
        Serial.println(player[i]);
        break;
      }
    }
  }
  Serial.println();
}


void playerCount() {
  pNum = 0;
  while (pNum == 0) {
    if (Serial.available()) {
      X = Serial.parseInt();
      if (X > 1 && X < 8) {
        pNum = X;
        Serial.print("Player count set to: ");
        Serial.println(pNum);
        Serial.println();
      }
      else {
        Serial.println("Players too high or too low!");
        Serial.println();
      }
    }
  }
  X = -1;
}

In regards to the memory issue, I don't know if that is the cause or how I would fix it if it was. It says I'm only using about a 1/5 of the memory with this current code. If you really think it is a memory issue, I may need some guidance or a source that will help me solve this issue. I am still a bit of a novice when it comes to coding, so this code probably has many ways it could be optimized or there are things I'm doing that more experienced programmers would tell me are "no-no's".

I am currently using an arduino nano, since all I'm really doing is some processing and storage of numbers and only sending them to the SM; and not connecting anything to the arduino itself (ie LEDs or buttons)

If it helps make sense of the code, the point of the card game is this: you get 7 cards round 1, 6 cards round 2, ect ect. There is a trump card and you must make bets 0-total cards in play. if you get the bets you made, you get 10 points + the amount you bid; if you don't, you get only the amount of "tricks" you got. (ie I bid 2, I got 2, so I get 12 points, the other guy bid 2, he got 1, so he gets 1, ect)

A power up pNum is initialized to 0.

i < pNum this means less than zero

But 'pNum' gets set to 1...7 as the first thing in loop() so that condition is never valid

Frequently if a variable is getting changed "for no reason" that is caused by writing to an array with the index out of range. Pepper in some print statements everywhere you store into the bet and player arrays (I don't see you storing into the score array) and see if the index is ever out of range.

Maybe a typo, the following is from your original post:

int bet[]={0,0,0,0,0,0,0};

void resetBids() {
  for (int x = 0; x < 7; x++) {
    bet[x] = 0;
  }
}

but the sketch you posted in reply #3 has x < 8, which would be writing to bet[7].

void resetBets() {
  //  for (int x = 0; x < 8; x++) {
  //    bet[x] = 0;
  //    delay(10);
  //  }
  bet[0] = 0;
  bet[1] = 0;
  bet[2] = 0;
  bet[3] = 0;
  bet[4] = 0;
  bet[5] = 0;
  bet[6] = 0;
}
2 Likes

I can't believe that that fixed it haha thanks man, I didn't even see that typo. I wish I could look at the machine language and figure out why that was causing issues. My guess is that "pNum" is stored in something like memory position 0x1, but when it tried to rewrite "bet[7]" to 0 which also had a theoretical memory position 0x1, it rewrote "pNum" to 0 instead.

Either way, the solution is solved! Thanks man. And thanks to everyone else that replied trying to help!!

When the code accesses an element of the bet array, it takes the starting memory address of the array and adds ( sizeof(int) * array index ) to that address. With bet[7], that would be the first memory address after the array, since the array has only 7 elements ( 0 through 6). With your code, pNum happens to be stored at that location.

What makes errors like this difficult to locate is that something completely unrelated to the actual error, such as simply printing a variable to Serial, can cause the compiler to rearrange the variable storage locations and move the error to a different variable, or possibly eliminate it entirely if the affected memory location is unused.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.