Zahlenschätzer

This sketch is a number guessing game where players try to discover a secret number between 1 and 100 by entering guesses and receiving feedback. The game displays instructions, remaining attempts, and directional hints (too high/too low) on a clean interface with an input field and buttons.

🧪 Try This!

Experiment with the code by making these changes:

  1. Change the game difficulty — Lower the starting tries to make winning harder, or raise it to make the game easier.
  2. Expand the number range
  3. Celebrate winning in color — When the player guesses correctly, turn the background green instead of gray to make victory feel special.
  4. Make buttons bigger
Prefer the full editor? Open it there →

📖 About This Sketch

This sketch creates an interactive number guessing game: you have ten attempts to discover a secret number between 1 and 100. The sketch combines several important p5.js techniques—a responsive canvas that fills the window, DOM elements like input fields and buttons positioned with JavaScript, and game state management using flags and counters. By studying it, you will learn how to build an interactive application that blends p5.js drawing with HTML form elements.

The code is organized into a setup() function that initializes the game and creates all interactive elements, a draw() function that continuously displays the game interface, and three helper functions (checkGuess, resetGame, windowResized) that handle player input and game logic. Reading this sketch teaches you how to manage game state across functions, validate user input, and build a complete game loop from start to victory or defeat.

⚙️ How It Works

  1. When the sketch loads, setup() creates a full-window canvas, generates a random secret number between 1 and 100, and builds an input field and two buttons—one to submit guesses and one to start a new game (initially hidden).
  2. Every frame, draw() clears the canvas with a light gray background and displays the game title, instructions, remaining attempts, and feedback text at fixed positions on the screen.
  3. When the player types a number and clicks the 'Raten!' button, checkGuess() runs: it reads the input value, validates it, and reduces the attempts counter by 1.
  4. checkGuess() compares the guess to the secret number and updates feedbackText with hints ('Too low!' or 'Too high!') or celebrates victory—if correct or out of attempts, it hides the input/button and shows the reset button.
  5. If the player clicks 'Neues Spiel', resetGame() generates a fresh secret number, restores attempts to 10, clears the feedback, and reveals the input field and guess button again.
  6. When the window is resized, windowResized() stretches the canvas and repositions all buttons and the input field to stay centered and responsive.

🎓 Concepts You'll Learn

DOM interaction (input fields and buttons)Game state managementConditional logicInput validationResponsive canvasEvent handling

📝 Code Breakdown

setup()

setup() runs exactly once when the sketch starts. Use it to initialize your canvas, create all interactive elements (buttons, inputs), and set starting values for game variables. Everything you create here persists until you call resetGame() or the player closes the browser.

function setup() {
  // Erstelle den Canvas, der die gesamte Fenstergröße einnimmt
  createCanvas(windowWidth, windowHeight);

  // Wähle eine zufällige ganze Zahl zwischen 1 und 100
  secretNum = floor(random(1, 101));

  // Erstelle das Eingabefeld
  guessInput = createInput('');
  guessInput.attribute('placeholder', 'Gib eine Zahl ein'); // Platzhaltertext
  // Positioniere das Eingabefeld in der Mitte des Canvas
  guessInput.position(width / 2 - guessInput.width / 2, height / 2 + 50);

  // Erstelle den Raten-Button
  guessButton = createButton('Raten!');
  // Positioniere den Button neben dem Eingabefeld
  guessButton.position(guessInput.x + guessInput.width + 10, height / 2 + 50);
  guessButton.mousePressed(checkGuess); // Weist die Funktion checkGuess zu, die bei Klick aufgerufen wird

  // Erstelle den Neues-Spiel-Button
  resetButton = createButton('Neues Spiel');
  // Positioniere den Button in der Mitte unter dem Feedback-Text
  resetButton.position(width / 2 - resetButton.width / 2, height / 2 + 150);
  resetButton.mousePressed(resetGame); // Weist die Funktion resetGame zu
  resetButton.hide(); // Verstecke den Button am Anfang

  // Zentriere den Text auf dem Canvas
  textAlign(CENTER, CENTER);
  textSize(24); // Setze die Textgröße
}
Line-by-line explanation (11 lines)

🔧 Subcomponents:

calculation Canvas Creation createCanvas(windowWidth, windowHeight);

Creates a canvas that stretches to fill the entire browser window, making the game responsive

calculation Secret Number Generation secretNum = floor(random(1, 101));

Generates a random integer from 1 to 100 that the player must guess

calculation Input Field Creation guessInput = createInput('');

Creates an HTML input field where the player types their guess

calculation Element Positioning guessInput.position(width / 2 - guessInput.width / 2, height / 2 + 50);

Centers the input field horizontally and places it below the middle of the canvas

calculation Button Event Listeners guessButton.mousePressed(checkGuess);

Connects button clicks to functions that handle the game logic

createCanvas(windowWidth, windowHeight);
Creates a canvas that is exactly as wide and tall as your browser window, so the game fills the screen
secretNum = floor(random(1, 101));
Generates a random number: random(1, 101) picks a decimal between 1 and 101, and floor() rounds it down to an integer from 1 to 100
guessInput = createInput('');
Creates an HTML input box where the player can type a number; the empty string '' means it starts empty
guessInput.attribute('placeholder', 'Gib eine Zahl ein');
Adds placeholder text that appears inside the input box as a hint until the player starts typing
guessInput.position(width / 2 - guessInput.width / 2, height / 2 + 50);
Centers the input box horizontally (width/2 minus half its own width) and places it 50 pixels below the vertical center
guessButton = createButton('Raten!');
Creates a clickable button labeled 'Raten!' (German for 'Guess!')
guessButton.mousePressed(checkGuess);
Tells p5.js to call the checkGuess() function whenever someone clicks the guess button
resetButton.mousePressed(resetGame);
Tells p5.js to call the resetGame() function when the reset button is clicked
resetButton.hide();
Hides the reset button at the start; it will only appear when the game ends
textAlign(CENTER, CENTER);
Centers all text both horizontally and vertically from the point you specify in text() calls
textSize(24);
Sets the font size to 24 pixels for all text drawn after this line

draw()

draw() runs 60 times per second and is where all graphics are rendered. Every frame, it clears the old canvas and redraws everything—this is what makes animation and real-time updates possible. In this game, draw() displays the fixed interface, while game logic happens in separate functions like checkGuess().

function draw() {
  // Setze den Hintergrund
  background(220);

  // Setze die Füllfarbe für den Text auf Schwarz
  fill(0);
  // Zeige den Spieltitel an
  text("Zahlenraten", width / 2, height / 2 - 100);
  // Zeige die Spielanleitung an
  text("Ich habe eine Zahl zwischen 1 und 100 gewählt. Rate sie!", width / 2, height / 2 - 50);
  // Zeige die verbleibenden Versuche an
  text("Versuche übrig: " + triesLeft, width / 2, height / 2);
  // Zeige das Feedback des Spiels an
  text(feedbackText, width / 2, height / 2 + 100);
}
Line-by-line explanation (6 lines)

🔧 Subcomponents:

calculation Background Clearing background(220);

Clears the canvas and repaints it light gray each frame so old text doesn't stay on screen

calculation Text Display text("Zahlenraten", width / 2, height / 2 - 100);

Draws the game title at the top center of the screen

background(220);
Fills the entire canvas with light gray (220 is a gray value in RGB). This must be called every frame to erase the previous frame's drawings
fill(0);
Sets the color for all subsequent text and shapes to black (0 means no red, green, or blue—pure black)
text("Zahlenraten", width / 2, height / 2 - 100);
Draws the title 'Zahlenraten' at the center horizontally and 100 pixels above the middle vertically
text("Ich habe eine Zahl zwischen 1 und 100 gewählt. Rate sie!", width / 2, height / 2 - 50);
Displays the game instructions at the center, 50 pixels above the middle
text("Versuche übrig: " + triesLeft, width / 2, height / 2);
Shows how many guesses are left by concatenating the string 'Versuche übrig: ' with the current triesLeft value, displayed at the vertical center
text(feedbackText, width / 2, height / 2 + 100);
Displays the feedback message (e.g., 'Too low!' or 'Correct!') that was set by checkGuess(), shown 100 pixels below the middle

checkGuess()

checkGuess() is called every time the player clicks the guess button. It is the engine of the game: it reads input, validates it, compares the guess to the secret number, and updates all game state (feedbackText, triesLeft, gameOver, and UI visibility). Notice how it manages both the game logic and the visual state—hiding/showing buttons and clearing the input field. This is a common pattern: functions that both calculate and update what the player sees.

// Funktion zum Überprüfen der Vermutung des Spielers
function checkGuess() {
  if (gameOver) return; // Wenn das Spiel vorbei ist, tue nichts

  let userGuess = int(guessInput.value()); // Konvertiere den Eingabewert in eine ganze Zahl
  guessInput.value(''); // Leere das Eingabefeld nach der Eingabe

  // Überprüfe, ob die Eingabe eine gültige Zahl ist und im Bereich liegt
  if (isNaN(userGuess) || userGuess < 1 || userGuess > 100) {
    feedbackText = "Ungültige Eingabe. Bitte gib eine Zahl zwischen 1 und 100 ein.";
    return;
  }

  triesLeft--; // Reduziere die Anzahl der verbleibenden Versuche

  if (userGuess === secretNum) {
    // Wenn die Vermutung richtig ist
    feedbackText = "Richtig! Du hast die Zahl in " + (10 - triesLeft) + " Versuchen erraten!";
    gameOver = true; // Setze das Spiel auf "Game Over"
    guessButton.hide(); // Verstecke den Raten-Button
    guessInput.hide(); // Verstecke das Eingabefeld
    resetButton.show(); // Zeige den Neues-Spiel-Button an
  } else if (triesLeft <= 0) {
    // Wenn keine Versuche mehr übrig sind
    feedbackText = "Du hast keine Versuche mehr! Die Zahl war " + secretNum + ".";
    gameOver = true;
    guessButton.hide();
    guessInput.hide();
    resetButton.show();
  } else if (userGuess < secretNum) {
    // Wenn die Vermutung zu niedrig ist
    feedbackText = "Zu niedrig! Versuche es erneut.";
  } else { // userGuess > secretNum
    // Wenn die Vermutung zu hoch ist
    feedbackText = "Zu hoch! Versuche es erneut.";
  }
}
Line-by-line explanation (17 lines)

🔧 Subcomponents:

conditional Game Over Guard if (gameOver) return;

Stops the function immediately if the game has already ended, preventing the player from submitting more guesses

calculation Input Parsing let userGuess = int(guessInput.value());

Reads the text from the input field and converts it to an integer

conditional Input Validation if (isNaN(userGuess) || userGuess < 1 || userGuess > 100) {

Checks if the input is not a valid number or is outside the 1-100 range, and shows an error message if so

conditional Correct Guess Check if (userGuess === secretNum) {

Detects when the player guesses correctly and triggers a win state

conditional Out of Tries Check } else if (triesLeft <= 0) {

Ends the game if the player has used all attempts, revealing the secret number

conditional Too Low Hint } else if (userGuess < secretNum) {

Tells the player their guess is too low so they know to try a higher number next

conditional Too High Hint } else {

Tells the player their guess is too high so they know to try a lower number next

if (gameOver) return;
If gameOver is true, the function stops immediately with return. This prevents accepting more guesses after the game ends
let userGuess = int(guessInput.value());
Reads whatever the player typed in the input field with .value(), then converts it to an integer with int()
guessInput.value('');
Clears the input field by setting its value to an empty string, so the player can type their next guess
if (isNaN(userGuess) || userGuess < 1 || userGuess > 100) {
Checks three things: isNaN() returns true if userGuess is not a number; || means 'or', so if ANY of these conditions is true, enter the block
feedbackText = "Ungültige Eingabe. Bitte gib eine Zahl zwischen 1 und 100 ein.";
Sets the feedback message to an error, which will be displayed in draw() on the next frame
triesLeft--;
Subtracts 1 from triesLeft, counting down the number of attempts remaining
if (userGuess === secretNum) {
Checks if the guess equals the secret number using === (strict equality, meaning both value and type must match)
feedbackText = "Richtig! Du hast die Zahl in " + (10 - triesLeft) + " Versuchen erraten!";
Congratulates the player and shows how many tries it took by calculating 10 minus the remaining tries
gameOver = true;
Sets the gameOver flag to true, which prevents further guesses via the first if-statement
guessButton.hide();
Hides the guess button from the screen so the player cannot submit more guesses
resetButton.show();
Shows the reset button so the player can start a new game
} else if (triesLeft <= 0) {
If the guess was wrong AND no tries remain, enter this block to end the game and reveal the answer
feedbackText = "Du hast keine Versuche mehr! Die Zahl war " + secretNum + ".";
Tells the player they lost and reveals the secret number by concatenating it into the message
} else if (userGuess < secretNum) {
If the guess was too low and there are still tries left, enter this block to give a hint
feedbackText = "Zu niedrig! Versuche es erneut.";
Sets the feedback to 'Too low!' so the player knows to guess higher next time
} else {
This final else means: if none of the above conditions are true, then the guess must be too high
feedbackText = "Zu hoch! Versuche es erneut.";
Sets the feedback to 'Too high!' directing the player to try a lower number

resetGame()

resetGame() is called when the player clicks the 'Neues Spiel' button. It reverses all the changes made during the previous game: it generates a new secret number, restores attempt counters, clears feedback, and shows/hides UI elements. This function is a good example of 'resetting state'—a critical pattern in games and interactive apps where you need to return to a known starting condition.

// Funktion zum Zurücksetzen des Spiels
function resetGame() {
  secretNum = floor(random(1, 101)); // Wähle eine neue geheime Zahl
  triesLeft = 10; // Setze die Versuche zurück
  feedbackText = ""; // Leere das Feedback
  gameOver = false; // Setze das Spiel auf "nicht Game Over"
  guessInput.value(''); // Leere das Eingabefeld
  guessButton.show(); // Zeige den Raten-Button wieder an
  guessInput.show(); // Zeige das Eingabefeld wieder an
  resetButton.hide(); // Verstecke den Neues-Spiel-Button
}
Line-by-line explanation (8 lines)

🔧 Subcomponents:

calculation Generate New Secret secretNum = floor(random(1, 101));

Picks a brand new random number for the next game

calculation Reset Game State gameOver = false;

Sets gameOver back to false so checkGuess() will accept guesses again

calculation Reset UI Elements guessButton.show();

Restores the input field and buttons so the player can play again

secretNum = floor(random(1, 101));
Generates a new random integer from 1 to 100, just like in setup(), so each new game has a different secret number
triesLeft = 10;
Resets the attempt counter back to 10, giving the player a fresh set of guesses
feedbackText = "";
Clears the feedback message so the old 'Too high!' or 'You won!' text disappears
gameOver = false;
Sets gameOver back to false, which tells checkGuess() that the game is active again and guesses should be accepted
guessInput.value('');
Empties the input field by setting its value to an empty string, clearing any leftover text
guessButton.show();
Makes the guess button visible again after it was hidden at the end of the previous game
guessInput.show();
Makes the input field visible again so the player can type their first guess of the new game
resetButton.hide();
Hides the reset button now that the game has restarted; it will only show again when this new game ends

windowResized()

windowResized() is a special p5.js function that p5.js automatically calls whenever the browser window is resized. Without it, the canvas would not stretch, and the buttons and input field would stay in fixed pixel positions instead of staying centered. This function is essential for making your sketch responsive—meaning it adapts gracefully to different screen sizes and orientations.

// Funktion, die aufgerufen wird, wenn die Fenstergröße geändert wird
function windowResized() {
  resizeCanvas(windowWidth, windowHeight); // Passe die Canvas-Größe an
  // Positioniere die DOM-Elemente neu, um responsiv zu bleiben
  guessInput.position(width / 2 - guessInput.width / 2, height / 2 + 50);
  guessButton.position(guessInput.x + guessInput.width + 10, height / 2 + 50);
  resetButton.position(width / 2 - resetButton.width / 2, height / 2 + 150);
}
Line-by-line explanation (4 lines)

🔧 Subcomponents:

calculation Canvas Resizing resizeCanvas(windowWidth, windowHeight);

Stretches or shrinks the canvas to match the current browser window size

calculation Element Repositioning guessInput.position(width / 2 - guessInput.width / 2, height / 2 + 50);

Recalculates and applies new positions to all buttons and the input field so they stay centered

resizeCanvas(windowWidth, windowHeight);
Resizes the p5.js canvas to match the current width and height of the browser window, keeping the canvas responsive to resizing
guessInput.position(width / 2 - guessInput.width / 2, height / 2 + 50);
Recalculates the input field's position to stay horizontally centered and 50 pixels below the vertical center, even after the window resizes
guessButton.position(guessInput.x + guessInput.width + 10, height / 2 + 50);
Repositions the guess button to the right of the input field (at the input's x position plus its width) to stay beside it
resetButton.position(width / 2 - resetButton.width / 2, height / 2 + 150);
Recalculates the reset button's position to stay horizontally centered and 150 pixels below the vertical center

📦 Key Variables

secretNum number

Stores the random number between 1 and 100 that the player must guess. It is generated fresh in setup() and resetGame().

let secretNum = floor(random(1, 101));
guessInput object

Stores a reference to the HTML input field where the player types their guess. Created in setup() and reused throughout the game.

let guessInput = createInput('');
guessButton object

Stores a reference to the button labeled 'Raten!'. When clicked, it calls checkGuess().

let guessButton = createButton('Raten!');
resetButton object

Stores a reference to the 'Neues Spiel' button. It is hidden at the start and only shown when the game ends.

let resetButton = createButton('Neues Spiel');
feedbackText string

Stores the message displayed to the player (e.g., 'Too low!' or 'Correct!'). Updated by checkGuess() and displayed by draw().

let feedbackText = "";
triesLeft number

Counts how many guesses the player has remaining. Starts at 10, decrements in checkGuess(), and resets in resetGame().

let triesLeft = 10;
gameOver boolean

A flag that tracks whether the game has ended. It is false during play and becomes true when the player wins or runs out of tries.

let gameOver = false;

🔧 Potential Improvements (5)

Here are some ways this code could be enhanced:

BUG checkGuess()

If the player enters text like 'hello' or leaves the field empty, int() will return NaN, and isNaN() catches it. However, the validation does not account for decimal inputs like 3.5.

💡 Use parseFloat() instead of int() and round the result, or update the validation message to clarify only whole numbers are accepted.

BUG setup() and windowResized()

Button positions are calculated based on guessInput.width, but if the CSS width changes, the positions may become misaligned.

💡 After creating buttons, explicitly set their widths in p5.js or store the expected widths as variables to ensure calculations stay accurate.

STYLE checkGuess()

The function does not prevent submissions when the input field is empty. The validation catches this (isNaN() is true for empty input), but the UX could be clearer.

💡 Add a check like if (guessInput.value().trim() === '') and show a specific message: 'Bitte gib eine Zahl ein!' (Please enter a number!)

FEATURE Overall

The game offers no visual feedback when an invalid input is submitted—only the error text updates, which might be missed.

💡 Add a brief red highlight to the input field or play a sound when validation fails, making errors impossible to ignore.

PERFORMANCE setup()

Every time windowResized() is called, element positions are recalculated using arithmetic—fine for three elements, but inefficient if scaled to many UI components.

💡 Create a repositionElements() helper function that centralizes all positioning logic, making it reusable and easier to maintain.

🔄 Code Flow

Code flow showing setup, draw, checkguess, resetgame, windowresized

💡 Click on function names in the diagram to jump to their code

graph TD start[Start] --> setup[setup] setup --> draw[draw loop] draw --> background-clear[Background Clearing] draw --> text-display[Text Display] draw --> button-callbacks[Button Event Listeners] draw --> game-over-check[Game Over Guard] click setup href "#fn-setup" click draw href "#fn-draw" click background-clear href "#sub-background-clear" click text-display href "#sub-text-display" click button-callbacks href "#sub-button-callbacks" click game-over-check href "#sub-game-over-check" button-callbacks --> checkguess[checkGuess] checkguess --> input-parsing[Input Parsing] checkguess --> input-validation[Input Validation] checkguess --> correct-guess[Correct Guess Check] checkguess --> out-of-tries[Out of Tries Check] checkguess --> too-low-check[Too Low Hint] checkguess --> too-high-check[Too High Hint] click checkguess href "#fn-checkguess" click input-parsing href "#sub-input-parsing" click input-validation href "#sub-input-validation" click correct-guess href "#sub-correct-guess" click out-of-tries href "#sub-out-of-tries" click too-low-check href "#sub-too-low-check" click too-high-check href "#sub-too-high-check" resetgame[resetGame] --> reset-secret[Generate New Secret] resetgame --> reset-state[Reset Game State] resetgame --> reset-ui[Reset UI Elements] click resetgame href "#fn-resetgame" click reset-secret href "#sub-reset-secret" click reset-state href "#sub-reset-state" click reset-ui href "#sub-reset-ui" windowresized[windowResized] --> canvas-resize[Canvas Resizing] windowresized --> element-reposition[Element Repositioning] click windowresized href "#fn-windowresized" click canvas-resize href "#sub-canvas-resize" click element-reposition href "#sub-element-reposition" setup --> create-canvas[Canvas Creation] setup --> random-number[Secret Number Generation] setup --> create-input[Input Field Creation] setup --> position-elements[Element Positioning] click create-canvas href "#sub-create-canvas" click random-number href "#sub-random-number" click create-input href "#sub-create-input" click position-elements href "#sub-position-elements"

❓ Frequently Asked Questions

What visually engaging elements does the Zahlenschätzer sketch feature?

The Zahlenschätzer sketch presents a clean interface with a bright background, displaying the game title, instructions, remaining attempts, and feedback for the player.

How can users participate in the Zahlenschätzer number guessing game?

Users can interact by entering their guesses in an input field and clicking the 'Raten!' button to submit their guesses, with the option to start a new game via the 'Neues Spiel' button.

What creative coding concepts are showcased in the Zahlenschätzer sketch?

This sketch demonstrates user interaction, random number generation, and dynamic feedback through visual elements in a simple game format.

Preview

Zahlenschätzer - p5.js creative coding sketch preview
Sketch Preview
Code flow diagram showing the structure of Zahlenschätzer - Code flow showing setup, draw, checkguess, resetgame, windowresized
Code Flow Diagram