Cross Training Home Development Chat Log Concept #3 — Conditional Logic: if/else
TNT  ›  Cross Training  ›  Conditional Logic: if/else
Concept #3

Conditional Logic: if/else

Ask the ball a question. It rolls a number. A chain of if/else decisions turns that number into an answer.
The same branching logic — and the same way randomness works — in three languages.

What the Magic 8 Ball is Really Doing

Behind the swirling sphere and the mystical responses, the Magic 8 Ball is solving a very specific problem: given a random number between 0 and 1, decide which category it falls into.

The original app defines four response types with different probabilities: positive (35%), negative (35%), vague (20%), and snarky (10%). Every time you shake the ball, a random number is generated and then a chain of if/else comparisons tests it against cumulative threshold values — cut-offs that divide the number line into four regions.

This pattern — generate a random value, compare it against thresholds, execute different code for each region — appears everywhere: game AI, simulations, A/B testing, recommendation engines. The 8 Ball is the most entertaining version of one of the most widely-used decision structures in software.

The two things this page demonstrates are inseparable: how each language generates a random number, and how each language writes the branching logic that classifies it.

The concept, before any language

// Generate a random decimal between 0.0 and 1.0:
roll ← RANDOM()

// Divide the 0–1 range into four probability bands:
cutoff1 ← 0.35  // 35% positive
cutoff2 ← 0.70  // + 35% negative
cutoff3 ← 0.90  // + 20% vague (snarky fills the rest)

IF roll ≤ cutoff1:
RETURN “positive”
ELSE IF roll ≤ cutoff2:
RETURN “negative”
ELSE IF roll ≤ cutoff3:
RETURN “vague”
ELSE:
RETURN “snarky”  // 0.90–1.0 = 10%

Every language below is a direct translation of this pseudocode. Notice that the logic is identical — what changes is the syntax for generating the random number and the keywords used for branching.

The Same Idea in Three Languages

Same logic. Same thresholds. Same output. Study how each language handles the random roll — and what vocabulary it uses for the branch.

JavaScript Vanilla JS
// No import — Math.random() is built-in
var roll = Math.random(); // 0.0 to 1.0

function chooseMessageType(roll) {
    var cutoff1 = 0.35;  // positive
    var cutoff2 = 0.70;  // + negative
    var cutoff3 = 0.90;  // + vague

    if (roll <= cutoff1) {
        return "positive";
    } else if (roll <= cutoff2) {
        return "negative";
    } else if (roll <= cutoff3) {
        return "vague";
    } else {
        return "snarky";  // remaining 10%
    }
}

var type = chooseMessageType(roll);
console.log("Roll: " + roll.toFixed(3)
            + " => " + type);
Java Java 17+
import java.util.Random; // must import

public class Magic8BallDemoDriver {

    public static String chooseMessageType(
            double roll) {
        double cutoff1 = 0.35;
        double cutoff2 = 0.70;
        double cutoff3 = 0.90;

        if (roll <= cutoff1) {
            return "positive";
        } else if (roll <= cutoff2) {
            return "negative";
        } else if (roll <= cutoff3) {
            return "vague";
        } else {
            return "snarky";
        }
    }

    public static void main(String[] args) {
        Random rng = new Random();
        double roll = rng.nextDouble();
        System.out.printf("Roll: %.3f => %s%n",
                          roll,
                          chooseMessageType(roll));
    }
}
Python 3 Python 3.x
import random  # must import the module

def choose_message_type(roll):
    cutoff1 = 0.35
    cutoff2 = 0.70
    cutoff3 = 0.90

    if roll <= cutoff1:
        return "positive"
    elif roll <= cutoff2:  # Python: elif
        return "negative"
    elif roll <= cutoff3:
        return "vague"
    else:
        return "snarky"    # remaining 10%

def main():
    roll = random.random() # 0.0 to 1.0
    msg_type = choose_message_type(roll)
    print(f"Roll: {roll:.3f} => {msg_type}")

if __name__ == "__main__":
    main()

Why Does Each Version Look Different?

The guiding question for every Cross Training page: “What does each version reveal about the language’s personality?”

JavaScript

Built-in and borderless. Math.random() is always available — no import, no class, no object. JavaScript treats random number generation as a global utility, part of the Math namespace that ships with every browser and every Node.js runtime. You never have to ask for it.

The else if chain looks nearly identical to Java — but JavaScript has no type system to enforce it. The function returns a string in every branch, but nothing prevents a careless developer from returning a number from one branch and a string from another. JavaScript would silently comply. The contract lives in comments, not in the compiler.

TypeScript (which compiles to JavaScript) exists in part to close exactly that gap. The fact that developers created a whole language to add types back in says something about both JavaScript’s freedom and its risks.

Java

Typed, declared, and explicit. import java.util.Random is required before you can use it. new Random() instantiates an object before you call .nextDouble() on it. Java’s philosophy: randomness is a service provided by an object. You declare it, you instantiate it, you own it.

The method signature public static String chooseMessageType(double roll) declares the return type (String) and the parameter type (double) before you read a single line of the body. The compiler verifies that every branch returns a String — if you add a branch that returns an int by accident, the build fails immediately.

The verbosity is intentional. Java was designed for teams and production code. The extra words are documentation the compiler enforces.

P.S. — Java also has Math.random(), which works exactly like JavaScript’s: no import, no object, returns a double from 0.0 to 1.0 — and the code would have been one line shorter. The reason to prefer new Random() anyway: a Random object can be seeded (new Random(42)), making its output reproducible — the same sequence every run. Reproducibility is essential for testing and debugging. Math.random() cannot be seeded. Beyond that, Random exposes a full toolkit: nextInt(n) for integers in a range, nextBoolean(), nextGaussian() for bell-curve distributions. The pattern — instantiate the tool you need, own it explicitly — is the same philosophy as declaring types in the method signature. Java rewards the extra line.

Python 3

Import makes it explicit. import random is required — Python’s random number generation lives in a module, not in a built-in namespace. random.random() reads: “from the random module, call the random() function.” The module name and function name are the same, which trips up every beginner exactly once.

elif — not else if — is Python’s single-token shorthand for the combined keyword. It works identically to Java’s else if but reveals the language’s preference for economy: two words became one.

No return type is declared. Python 3.5+ supports optional type hints (def choose_message_type(roll: float) -> str:), but they are never enforced at runtime — they are documentation you opt into, not a contract the interpreter verifies.