Arnov Sharma
Published © MIT

Guessatron

Guessatron is a "20 Ques Guessing Game Device, " which is like the OG Akinator; you think of something and this device will guess that thing!

IntermediateFull instructions provided1 hour117
Guessatron

Things used in this project

Hardware components

ESP32 S3 1.69 Inch Display
×1
PCBWay Custom PCB
PCBWay Custom PCB
×1

Software apps and online services

Fusion
Autodesk Fusion
Arduino IDE
Arduino IDE

Hand tools and fabrication machines

3D Printer (generic)
3D Printer (generic)

Story

Read more

Custom parts and enclosures

cad file

Schematics

WIRING

Code

20QuestionsUpdated2.ino

C/C++
// 20 Questions Game for Raspberry Pi Pico with Smart Adaptive Questions
// OLED (SSD1306), 3 Buttons (GPIO 12, 13, 14), 4 WS2812B LEDs on GPIO 0

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_NeoPixel.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define BUTTON_YES 12
#define BUTTON_NO 13
#define BUTTON_SOMETIMES 14
#define LED_PIN 0
#define NUM_LEDS 4
Adafruit_NeoPixel leds(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);

struct QuestionNode {
  String text;
  int yesNext = -1;
  int noNext = -1;
  int sometimesNext = -1;
  int index;
};

struct Object {
  String name;
  int answers[20];
};

#include "objects_70.h"
const int objectCount = sizeof(objects) / sizeof(objects[0]);

QuestionNode questionTree[] = {
  {"Is it alive?", 1, 2, 3, 0},
  {"Is it an animal?", 4, 5, 6, 1},
  {"Is it man-made?", 7, 8, 9, 2},
  {"Can it be alive sometimes?", 10, 11, 12, 3},
  {"Does it live with humans?", 13, 14, 15, 4},
  {"Does it have a screen?", 16, 17, 18, 5},
  {"Is it used in work?", 19, 20, 21, 6},
  {"Is it electronic?", 22, 23, 24, 7},
  {"Is it used for cooking?", 25, 26, 27, 8},
  {"Can it be used outside?", 28, 29, 30, 9},
  {"Does it grow?", 31, 32, 33, 10},
  {"Does it walk?", 34, 35, 36, 11},
  {"Does it swim?", 37, 38, 39, 12},
  {"Is it a pet?", -1, -1, -1, 13},
  {"Is it a wild animal?", -1, -1, -1, 14},
  {"Is it a farm animal?", -1, -1, -1, 15},
  {"Is it a phone?", -1, -1, -1, 16},
  {"Is it a computer?", -1, -1, -1, 17},
  {"Is it a television?", -1, -1, -1, 18},
  {"Is it used in office?", -1, -1, -1, 19},
  {"Is it used in school?", -1, -1, -1, 20},
  {"Is it used in kitchen?", -1, -1, -1, 21},
  {"Is it a gadget?", -1, -1, -1, 22},
  {"Is it a tool?", -1, -1, -1, 23},
  {"Is it a vehicle?", -1, -1, -1, 24},
  {"Is it an appliance?", -1, -1, -1, 25},
  {"Is it edible?", -1, -1, -1, 26},
  {"Is it found outdoors?", -1, -1, -1, 27},
  {"Is it used for exercise?", -1, -1, -1, 28},
  {"Is it used for fun?", -1, -1, -1, 29},
  {"Can it float?", -1, -1, -1, 30},
  {"Is it a plant?", -1, -1, -1, 31},
  {"Is it a tree?", -1, -1, -1, 32},
  {"Does it need water?", -1, -1, -1, 33},
  {"Is it a mammal?", -1, -1, -1, 34},
  {"Is it a bird?", -1, -1, -1, 35},
  {"Is it an insect?", -1, -1, -1, 36},
  {"Is it a fish?", -1, -1, -1, 37},
  {"Is it a reptile?", -1, -1, -1, 38},
  {"Is it an amphibian?", -1, -1, -1, 39},
};

int answers[20];
bool asked[40];
int answerIndex = 0;
int currentNodeIndex = 0;

void showQuestion(String q) {
  display.clearDisplay();
  display.setCursor(0, 0);
  display.println("Q" + String(answerIndex + 1) + ": " + q);
  display.display();
}

int readButton() {
  while (true) {
    if (digitalRead(BUTTON_YES) == LOW) {
      delay(250); while (digitalRead(BUTTON_YES) == LOW); return 1;
    }
    if (digitalRead(BUTTON_NO) == LOW) {
      delay(250); while (digitalRead(BUTTON_NO) == LOW); return 0;
    }
    if (digitalRead(BUTTON_SOMETIMES) == LOW) {
      delay(250); while (digitalRead(BUTTON_SOMETIMES) == LOW); return 2;
    }
    delay(10);
  }
}

String guessObject() {
  int bestScore = -1;
  String bestMatch = "Not sure!";
  for (int i = 0; i < objectCount; i++) {
    int score = 0;
    for (int j = 0; j < 20; j++) {
      if (objects[i].answers[j] == answers[j]) score++;
    }
    if (score > bestScore) {
      bestScore = score;
      bestMatch = objects[i].name;
    }
  }
  return bestMatch;
}

void setup() {
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("20Q Game Loading...");
  display.display();

  pinMode(BUTTON_YES, INPUT_PULLUP);
  pinMode(BUTTON_NO, INPUT_PULLUP);
  pinMode(BUTTON_SOMETIMES, INPUT_PULLUP);

  leds.begin();
  for (int i = 0; i < NUM_LEDS; i++) {
    leds.setPixelColor(i, leds.Color(16, 0, 0)); // Dim red
  }
  leds.show();

  for (int i = 0; i < 40; i++) asked[i] = false;
  for (int i = 0; i < 20; i++) answers[i] = -1;
}

void loop() {
  if (answerIndex >= 20) {
    String guess = guessObject();
    display.clearDisplay();
    display.setCursor(0, 0);
    display.println("You are thinking of:");
    display.println(guess);
    display.display();
    delay(8000);

    // Reset everything
    currentNodeIndex = 0;
    answerIndex = 0;
    for (int i = 0; i < 20; i++) answers[i] = -1;
    for (int i = 0; i < 40; i++) asked[i] = false;
    return;
  }

  // Show and answer current question
  showQuestion(questionTree[currentNodeIndex].text);
  int response = readButton();
  answers[questionTree[currentNodeIndex].index] = response;
  asked[currentNodeIndex] = true;
  answerIndex++;

  int next = -1;
  if (response == 1) next = questionTree[currentNodeIndex].yesNext;
  else if (response == 0) next = questionTree[currentNodeIndex].noNext;
  else next = questionTree[currentNodeIndex].sometimesNext;

  // Move to next valid question if possible
  if (next != -1 && !asked[next]) {
    currentNodeIndex = next;
    return;
  }

  // Try to find another unanswered question in fallback
  bool found = false;
  for (int i = 0; i < 40; i++) {
    if (!asked[i]) {
      currentNodeIndex = i;
      found = true;
      break;
    }
  }

  if (!found) {
    // If all questions are asked, move to guess early
    answerIndex = 20;
  }
}

objects_70.h

C Header File
Object objects[] = {
  {"Dog",              {1,1,0,0,1,0,0,0,0,1,0,1,0,1,0,0,0,0,0,0}},
  {"Cat",              {1,1,0,0,1,0,0,0,0,1,0,1,0,1,0,0,0,0,0,0}},
  {"Cow",              {1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0}},
  {"Horse",            {1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0}},
  {"Elephant",         {1,1,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0}},
  {"Human",            {1,1,0,0,1,1,1,1,0,1,0,1,0,1,0,0,0,0,0,0}},
  {"Tree",             {1,0,0,1,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0}},
  {"Flower",           {1,0,0,1,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0}},
  {"Phone",            {0,0,1,0,1,1,1,1,0,1,0,0,0,0,0,0,1,0,0,0}},
  {"Laptop",           {0,0,1,0,1,1,1,1,0,1,0,0,0,0,0,0,0,1,0,0}},
  {"Television",       {0,0,1,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,1,0}},
  {"Chair",            {0,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Table",            {0,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Spoon",            {0,0,1,0,1,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0}},
  {"Car",              {0,0,1,0,1,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Bicycle",          {0,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Fish",             {1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1}},
  {"Bird",             {1,1,0,0,0,0,0,0,0,1,0,1,0,0,1,0,0,0,0,0}},
  {"Book",             {0,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Pen",              {0,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Mouse (device)",   {0,0,1,0,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Fan",              {0,0,1,0,1,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Fridge",           {0,0,1,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0}},
  {"Washing Machine",  {0,0,1,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0}},
  {"Toaster",          {0,0,1,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0}},
  {"Kettle",           {0,0,1,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0}},
  {"Egg",              {1,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0}},
  {"Rock",             {0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Cloud",            {0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Sun",              {0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Moon",             {0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Train",            {0,0,1,0,1,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Bus",              {0,0,1,0,1,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Airplane",         {0,0,1,0,1,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Helicopter",       {0,0,1,0,1,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Drone",            {0,0,1,0,1,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Bottle",           {0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Bag",              {0,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Shoe",             {0,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Shirt",            {0,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Clock",            {0,0,1,0,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Mirror",           {0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Key",              {0,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Knife",            {0,0,1,0,1,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0}},
  {"Camera",           {0,0,1,0,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Calculator",       {0,0,1,0,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Tablet",           {0,0,1,0,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Microwave",        {0,0,1,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0}},
  {"Sandwich",         {0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0}},
  {"Pizza",            {0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0}},
  {"Cup",              {0,0,1,0,1,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0}},
  {"Toothbrush",       {0,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Soap",             {0,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Towel",            {0,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Glasses",          {0,0,1,0,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Ball",             {0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Doll",             {0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Toy Car",          {0,0,1,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Stuffed Animal",   {0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Robot",            {0,0,1,0,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Battery",          {0,0,1,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Light Bulb",       {0,0,1,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0}},
  {"Umbrella",         {0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}}
};

Credits

Arnov Sharma
352 projects • 360 followers
I'm Arnov. I build, design, and experiment with tech—3D printing, PCB design, and retro consoles are my jam.

Comments