user50732: noob here
So what I am trying to do is output a different number depending on the number of button presses e.g. for 1 button press it should output 1 and so forth. After that I only really want the outputs for 1 to 4 presses. I am using these inputs for a game.  Right now, it does work and counts up until 4 and then resets back to 0. The problem that I am having is it continues after 1 click to 2 clicks; what I want it to do is count 1 click when its clicked once, twice when its clicked twice etc. I am trying to use a debouncing code to distinguish between single tap, double tap, triple tap etc 
@VE7JRO kindly provided a great solution to this problem, albeit it was for one button. I am trying to adjust the code to accommodate 2 separate buttons (on separate pins), but it is giving me an error.
This is the code:
#include <Bounce2.h>

// Connect both buttons in series with one connection
// to GND and the other to a digital pin.
const int buttonPin1 = 2;
const int buttonPin2 = 3;

class Button
{
  private:

    int m_buttonPin1;
    int m_buttonPin2;
    int m_counter;
    unsigned long m_buttonPressTimeout;
    unsigned long m_previousMillis;

  public:

    Button(int button):
      m_buttonPin1(buttonPin1),
      m_buttonPin2(buttonPin2),
      m_counter(0),
      m_buttonPressTimeout(1500), // Button press timeout 500 ms.
      m_previousMillis(0){}



    void Update()
    {
      int valA = digitalRead(button1); // read button stateint 
      int  valB = digitalRead(button2); // read button state
       if (valA == LOW &&valB == LOW)
       { 
      if(m_counter > 0 && millis() - m_previousMillis >= m_buttonPressTimeout)
      {
        Serial.print("Count from Update() just before it's re-set to 0 = ");
        Serial.println(GetCounter());
        m_counter = 0;
      }
    }

    void IncrementCounter(){
      m_counter++;
      if(m_counter > 4){m_counter = 4;}
      if(m_counter == 1){
        m_previousMillis = millis();
      }
    }

    byte GetCounter(){
      return m_counter;
    }

};

Bounce button1Debouncer = Bounce();
Bounce button2Debouncer = Bounce();
Button MyButton(buttonPin1);
Button MyButton(buttonPin2);

void setup(){

  Serial.begin(9600);

  pinMode(buttonPin1, INPUT_PULLUP);
  button1Debouncer.attach(buttonPin);
  button1Debouncer.interval(5);
  pinMode(buttonPin2, INPUT_PULLUP);
  button2Debouncer.attach(buttonPin);
  button2Debouncer.interval(5);

}

void loop(){

  // Call the Update function as fast as possible.
  MyButton.Update();

  // Button pressed.
  if(button1Debouncer.update() && button2Debouncer.update())
  {
    if(button1Debouncer.fell() && button2Debouncer.fell()){
      MyButton.IncrementCounter();
      Serial.print("Count from Button Debouncer = ");
      Serial.println(MyButton.GetCounter());
    }
  }

}
}

The error is: "'buttonPin1' is not a type", I do not understand this error as it didn't give that error for when a single button was used.

user20245: It is likely you are experiencing problems associated with button contact bounce. This is where the processor is so fast that it "sees" the button make several contacts when the user only intends for 1 contact to be seen by the program. Consider using this button de-bounce library instead of reading the state of the buttons directly in the sketch.
The code for the above debounce Arduino library is hosted here at github.com. In general, people using github.com will have an "example" folder along with the source code and documentation folders.  The debounce Arduino library example folder is here.  There are about half a dozen Arduino sketch examples including this 2 button example which might be used as the starting point for the project in the question.
There may be a logic problem in the code when interpreting the number of button presses into "a", "b", "c" & "d".  The modulo operator "%" is used.  And in the first test, the number of button presses % 1 is tested. If the result is zero the test is true.  As any number % 1 has no remainder this test will always be zero and therefor always true.  As all other tests are nested inside "else" statements none of the other tests will be executed.  Instead consider using a switch / case statement where the code switches on the number of button presses and the case statements are "case 1:", case 2:", "case 3:" & "default:".  It is good coding practice to always have a "default:" case in a switch statement.  Here we use "default:" instead of "case 4:". After using the value representing the number of button presses, always remember to clear this value before the next iteration.  Remember, any "global" values (values defined outside a function) will retain their values between calls to that function. Any "local" value (values defined inside a function) will not retain their values and need to be initialize each time they are used.

user60469: You SHOULD pay attention to the following issues:
1. Floating input problem:
Symptom: the reading value from the input pin is not matched with the button's pressing state.
Cause: input pin is NOT used pull-up or pull-down resistor.
Solution: Use pull-up or pull-down resistor. See Arduino Button (with pull-up/pull-down)
2. Chattering phenomenon
It should be considered in only some application that needs to detect exactly number of the pressing.
Symptom: Button is pressed one, but Arduino code detects several times.
Cause: Due to mechanical and physical issues, the state of the button (or switch) is quickly toggled between LOW and HIGH several times
Solution: Debounce. See Arduino Button Debounce

user2967: Your updated code has lots of problems. To do button debouncing, try something like this:
//Adjust debounceTime as desired. Shorter times will make fore faster button 
//response, but make the debouncing less effective. 50 is 1/20th of a second. 
#define debounceTime 50

unsigned long nextButtonCheckTime = 0;
bool buttonAState = false;
bool buttonBState = false;


void loop() {
  //Only check the buttons if the debounce time has passed
  if (millis() > nextButtonCheckTime) 
    bool newButtonAState = digitalRead(buttonAPin) == LOW;
    bool newButtonBState = digitalRead(buttonBPin) == LOW;
    //If one or both buttons have changed state
    if  (buttonAState != newButtonAState || buttonBState != newButtonBState)) {
      nextButtonCheckTime = millis() + debounceTime;
      buttonAState = newButtonAState;
      buttonBState = newButtonBState;
      //Handle change of button state
    }
  }
}

That is pseudocode. It almost certainly contains syntax errors. You should use it as a guide, and rewrite it to suit your needs. Do not say "I copied your code into my sketch and it won't compile."

50732: <p>noob here</p>

<p>So what I am trying to do is output a different number depending on the number of button presses e.g. for 1 button press it should output 1 and so forth. After that I only really want the outputs for 1 to 4 presses. I am using these inputs for a game.  Right now, it does work and counts up until 4 and then resets back to 0. The problem that I am having is it continues after 1 click to 2 clicks; what I want it to do is count 1 click when its clicked once, twice when its clicked twice etc. I am trying to use a debouncing code to distinguish between single tap, double tap, triple tap etc 
@VE7JRO kindly provided a great solution to this problem, albeit it was for one button. I am trying to adjust the code to accommodate 2 separate buttons (on separate pins), but it is giving me an error.</p>

<p>This is the code:</p>

<pre><code>#include &lt;Bounce2.h&gt;

// Connect both buttons in series with one connection
// to GND and the other to a digital pin.
const int buttonPin1 = 2;
const int buttonPin2 = 3;

class Button
{
  private:

    int m_buttonPin1;
    int m_buttonPin2;
    int m_counter;
    unsigned long m_buttonPressTimeout;
    unsigned long m_previousMillis;

  public:

    Button(int button):
      m_buttonPin1(buttonPin1),
      m_buttonPin2(buttonPin2),
      m_counter(0),
      m_buttonPressTimeout(1500), // Button press timeout 500 ms.
      m_previousMillis(0){}



    void Update()
    {
      int valA = digitalRead(button1); // read button stateint 
      int  valB = digitalRead(button2); // read button state
       if (valA == LOW &amp;&amp;valB == LOW)
       { 
      if(m_counter &gt; 0 &amp;&amp; millis() - m_previousMillis &gt;= m_buttonPressTimeout)
      {
        Serial.print("Count from Update() just before it's re-set to 0 = ");
        Serial.println(GetCounter());
        m_counter = 0;
      }
    }

    void IncrementCounter(){
      m_counter++;
      if(m_counter &gt; 4){m_counter = 4;}
      if(m_counter == 1){
        m_previousMillis = millis();
      }
    }

    byte GetCounter(){
      return m_counter;
    }

};

Bounce button1Debouncer = Bounce();
Bounce button2Debouncer = Bounce();
Button MyButton(buttonPin1);
Button MyButton(buttonPin2);

void setup(){

  Serial.begin(9600);

  pinMode(buttonPin1, INPUT_PULLUP);
  button1Debouncer.attach(buttonPin);
  button1Debouncer.interval(5);
  pinMode(buttonPin2, INPUT_PULLUP);
  button2Debouncer.attach(buttonPin);
  button2Debouncer.interval(5);

}

void loop(){

  // Call the Update function as fast as possible.
  MyButton.Update();

  // Button pressed.
  if(button1Debouncer.update() &amp;&amp; button2Debouncer.update())
  {
    if(button1Debouncer.fell() &amp;&amp; button2Debouncer.fell()){
      MyButton.IncrementCounter();
      Serial.print("Count from Button Debouncer = ");
      Serial.println(MyButton.GetCounter());
    }
  }

}
}
</code></pre>

<p>The error is: "'buttonPin1' is not a type", I do not understand this error as it didn't give that error for when a single button was used.</p>
 20245: <p>It is likely you are experiencing problems associated with button <a href="https://en.wikipedia.org/wiki/Switch#Contact_bounce" rel="nofollow noreferrer">contact bounce</a>. This is where the processor is so fast that it "sees" the button make several contacts when the user only intends for 1 contact to be seen by the program. Consider using <a href="https://playground.arduino.cc/Code/Bounce/" rel="nofollow noreferrer">this button de-bounce library</a> instead of reading the state of the buttons directly in the sketch.</p>

<p>The code for the above debounce Arduino library is <a href="https://github.com/thomasfredericks/Bounce2" rel="nofollow noreferrer">hosted here at github.com</a>. In general, people using github.com will have an "example" folder along with the source code and documentation folders.  The <a href="https://github.com/thomasfredericks/Bounce2/tree/master/examples" rel="nofollow noreferrer">debounce Arduino library example folder is here</a>.  There are about half a dozen Arduino sketch examples including <a href="https://github.com/thomasfredericks/Bounce2/blob/master/examples/bounce2buttons/bounce2buttons.ino" rel="nofollow noreferrer">this 2 button example</a> which might be used as the starting point for the project in the question.</p>

<p>There may be a logic problem in the code when interpreting the number of button presses into "a", "b", "c" &amp; "d".  The <a href="https://www.arduino.cc/reference/en/language/structure/arithmetic-operators/modulo/" rel="nofollow noreferrer">modulo operator "%"</a> is used.  And in the first test, the number of button presses % 1 is tested. If the result is zero the test is true.  As any number % 1 has no remainder this test will always be zero and therefor always true.  As all other tests are nested inside "else" statements none of the other tests will be executed.  Instead consider using a <a href="https://www.arduino.cc/reference/en/language/structure/control-structure/switchcase/" rel="nofollow noreferrer">switch / case statement</a> where the code switches on the number of button presses and the case statements are "case 1:", case 2:", "case 3:" &amp; "default:".  It is good coding practice to always have a "default:" case in a switch statement.  Here we use "default:" instead of "case 4:". After using the value representing the number of button presses, always remember to clear this value before the next iteration.  Remember, any "global" values (values defined outside a function) will retain their values between calls to that function. Any "local" value (values defined inside a function) will not retain their values and need to be initialize each time they are used.</p>
 60469: <p>You SHOULD pay attention to the following issues:</p>

<p><strong>1. Floating input problem:</strong></p>

<p><strong><em>Symptom:</em></strong> the reading value from the input pin is not matched with the button's pressing state.</p>

<p><strong><em>Cause:</em></strong> input pin is NOT used pull-up or pull-down resistor.</p>

<p><strong><em>Solution:</em></strong> Use pull-up or pull-down resistor. See <a href="https://arduinogetstarted.com/tutorials/arduino-button" rel="nofollow noreferrer">Arduino Button (with pull-up/pull-down)</a></p>

<p><strong>2. Chattering phenomenon</strong></p>

<p>It should be considered in only some application that needs to detect exactly number of the pressing.</p>

<p><strong><em>Symptom:</em></strong> Button is pressed one, but Arduino code detects several times.</p>

<p><strong><em>Cause:</em></strong> Due to mechanical and physical issues, the state of the button (or switch) is quickly toggled between LOW and HIGH several times</p>

<p><strong><em>Solution:</em></strong> Debounce. See <a href="https://arduinogetstarted.com/tutorials/arduino-button-debounce" rel="nofollow noreferrer">Arduino Button Debounce</a></p>
 2967: <p>Your updated code has lots of problems. To do button debouncing, try something like this:</p>

<pre><code>//Adjust debounceTime as desired. Shorter times will make fore faster button 
//response, but make the debouncing less effective. 50 is 1/20th of a second. 
#define debounceTime 50

unsigned long nextButtonCheckTime = 0;
bool buttonAState = false;
bool buttonBState = false;


void loop() {
  //Only check the buttons if the debounce time has passed
  if (millis() &gt; nextButtonCheckTime) 
    bool newButtonAState = digitalRead(buttonAPin) == LOW;
    bool newButtonBState = digitalRead(buttonBPin) == LOW;
    //If one or both buttons have changed state
    if  (buttonAState != newButtonAState || buttonBState != newButtonBState)) {
      nextButtonCheckTime = millis() + debounceTime;
      buttonAState = newButtonAState;
      buttonBState = newButtonBState;
      //Handle change of button state
    }
  }
}
</code></pre>

<p>That is pseudocode. It almost certainly contains syntax errors. You should use it as a guide, and rewrite it to suit your needs. Do <strong>not</strong> say "I copied your code into my sketch and it won't compile."</p>
