Built-in project · Arduino Uno R3

Number guess on an Arduino Uno

A 4x3 telephone keypad and a 16x2 LCD on an Uno: guess the number, and the display says higher or lower. The whole build, an Arduino Uno and 2 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.

IntermediateRuns in your browser. Free, and no account needed.

Number guess · Arduino Uno R3live0.000 s 0.00x
Click to open it in the editor
The circuit itself, running here on the simulator. Press what can be pressed; click anything else to open it in the editor.

The code

The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.

sketch.ino · Arduino Uno R3
// Number guess: the board thinks of a number, you type it on a phone keypad.
//
//   pins 12, 11, 10, 9     keypad rows R1 to R4
//   pins 8, 7, 6           keypad columns C1 to C3
//   A0  LCD RS             A1  LCD E
//   A2, A3, A4, A5         LCD D4 to D7   (RW and V0 to GND)
//
// The pad is the twelve-key one off a telephone:
//
//     1  2  3
//     4  5  6
//     7  8  9
//     *  0  #
//
// Type a number between 1 and 100 and press `#` to send it. The display says
// HIGHER or LOWER, and `*` rubs out what you have typed. Get it right and it
// tells you how many goes it took and thinks of another.
//
// # Where the number comes from
//
// A board has no dice and no clock that is different on each run, so seeding
// the generator in `setup()` gives the same "random" number every time, which
// is the classic bug in every guessing game written on a microcontroller. This
// one seeds from `micros()` at the moment the first key of the game is pressed.
// That reading is a person's reaction time in microseconds, and nothing on the
// board can predict it.
//
// # Reading the pad
//
// Twelve keys on seven pins and no chip: each key shorts its row to its column,
// so the sketch scans: one row driven low at a time, the three columns read
// with their pull-ups on. mokxi_keypad.h does the scan and the debounce and
// hands back one character per press. It never drives a row high, because two
// keys held in one column would put one driven output across another.

#include "mokxi_keypad.h"
#include "mokxi_lcd1602.h"

const uint8_t ROWS[4] = {12, 11, 10, 9};
const uint8_t COLS[3] = {8, 7, 6};

Keypad4x3 pad(ROWS, COLS);
Lcd1602 lcd(A0, A1, A2, A3, A4, A5);

const int LOWEST = 1;
const int HIGHEST = 100;

int secret = 0;
int entry = 0;
int tries = 0;
bool seeded = false;

static void newGame()
{
  secret = (int)random(LOWEST, HIGHEST + 1);
  entry = 0;
  tries = 0;
}

static void showEntry(const char *note)
{
  lcd.setCursor(0, 0);
  lcd.print(note);
  lcd.padLine();
  lcd.setCursor(0, 1);
  lcd.print("Guess: ");
  if (entry > 0) {
    lcd.print(entry);
  } else {
    lcd.write('_');
  }
  lcd.padLine();
}

void setup()
{
  pad.begin();
  lcd.begin();
  lcd.print("Number guess");
  lcd.setCursor(0, 1);
  lcd.print("1 to 100, # ends");
}

void loop()
{
  char key = pad.pressed();
  if (key == 0) {
    return;
  }

  // The first press of the session is what the generator is seeded from: a
  // person's reaction time, which nothing on the board can work out for itself.
  if (!seeded) {
    randomSeed(micros());
    seeded = true;
    newGame();
    showEntry("Think of a go");
  }

  if (key == '*') {
    entry = 0;
    showEntry("Cleared");
    return;
  }

  if (key >= '0' && key <= '9') {
    if (entry < 100) {
      entry = entry * 10 + (key - '0');
    }
    showEntry("Typing");
    return;
  }

  if (key != '#') {
    return;
  }

  if (entry < LOWEST || entry > HIGHEST) {
    entry = 0;
    showEntry("1 to 100 only");
    return;
  }

  tries++;
  if (entry < secret) {
    entry = 0;
    showEntry("HIGHER");
    return;
  }
  if (entry > secret) {
    entry = 0;
    showEntry("LOWER");
    return;
  }

  lcd.setCursor(0, 0);
  lcd.print("Got it: ");
  lcd.print(secret);
  lcd.padLine();
  lcd.setCursor(0, 1);
  lcd.print(tries);
  lcd.print(tries == 1 ? " go. Again..." : " goes. Again...");
  lcd.padLine();
  delay(2000);
  newGame();
  showEntry("New number");
}

Parts list

4 parts, plus the jumper wires. Every one is in the editor's parts bin.

How it is wired

15 connections, pin by pin, read from the circuit itself. Each line is one set of pins joined together, by a jumper wire or a breadboard strip.

  • Arduino Uno R3 pin 12; Keypad, 4x3 telephone pin R1
  • Arduino Uno R3 pin 11; Keypad, 4x3 telephone pin R2
  • Arduino Uno R3 pin 10; Keypad, 4x3 telephone pin R3
  • Arduino Uno R3 pin 9; Keypad, 4x3 telephone pin R4
  • Arduino Uno R3 pin 8; Keypad, 4x3 telephone pin C1
  • Arduino Uno R3 pin 7; Keypad, 4x3 telephone pin C2
  • Arduino Uno R3 pin 6; Keypad, 4x3 telephone pin C3
  • Arduino Uno R3 pin 5V; Character LCD, 16x2 pin VDD; Character LCD, 16x2 pin A
  • Ground: Arduino Uno R3 pin GND; Character LCD, 16x2 pin VSS; Character LCD, 16x2 pin V0; Character LCD, 16x2 pin RW; Character LCD, 16x2 pin K
  • Arduino Uno R3 pin A0; Character LCD, 16x2 pin RS
  • Arduino Uno R3 pin A1; Character LCD, 16x2 pin E
  • Arduino Uno R3 pin A2; Character LCD, 16x2 pin D4
  • Arduino Uno R3 pin A3; Character LCD, 16x2 pin D5
  • Arduino Uno R3 pin A4; Character LCD, 16x2 pin D6
  • Arduino Uno R3 pin A5; Character LCD, 16x2 pin D7

Change it and keep it

Open it in the editor, change the circuit or the code, and keep your version in a free account.