Decision Making — IF & CASE Grade 10

Decision structures let your program choose different paths based on conditions. Delphi uses if…then…else and case for this.

What is Decision Making?

Decision-making (also called conditional logic) is when a program tests whether something is true or false and then chooses what to do next based on the answer. A condition is any question that can only be answered with true or false — for example, "is the age 18 or more?".

Everyday analogy: A robot (traffic light) at an intersection makes a decision for you. If the light is green you go; else you stop. Your program does the same thing — it looks at a condition and takes one path or another.

Why Do Programs Need to Make Decisions?

Without decisions, a program could only ever do the exact same thing every single time it runs. Decisions make a program react to its data and its user.

T1Term 1 · Basic IF & IF…ELSE

The IF Statement

The IF statement evaluates a condition that must resolve to True or False, and executes a statement only when that condition is True.

In plain words it says: "If this is true, then do that; otherwise (else) do something else." Everyday analogy: "If it is raining, take an umbrella, else wear a cap." The "if it is raining" part is the condition that is checked first.

THE IF STATEMENT Keyword — starts every decision Keyword — leads into the action if iAge >= 18 then Condition — must evaluate to True or False

IF … THEN (one-way)

Syntax
if condition then
  statement;

IF … THEN … ELSE (two-way)

No semicolon before ELSE

Never put a ; on the line before else — it ends the if statement too early.

Syntax
if condition then
  statement
else
  statement;

Multiple Statements — use BEGIN…END

Delphi
if iAge >= 18 then
begin
  lblResult.Caption := 'Adult';
  btnVote.Enabled   := True;
end
else
begin
  lblResult.Caption := 'Minor';
  btnVote.Enabled   := False;
end;

Examples

Delphi
if iNum1 > iNum2 then
  ShowMessage(IntToStr(iNum1) + ' is larger');

if iAge >= 18 then
  ShowMessage('Old enough to vote');

if sUsername <> 'admin' then
  ShowMessage('Access denied')
else
  ShowMessage('Welcome, administrator!');

Comparison Operators

OperatorMeaningExample
=Equal toiAge = 18
<>Not equal tosName <> 'Admin'
>Greater thaniScore > 50
<Less thaniAge < 18
>=Greater than or equal toiMark >= 30
<=Less than or equal torPrice <= 100.0
T2Term 2 · Full IF…ELSE, Nested IF, Boolean Operators & CASE

Nested IF

An IF inside another IF.

Delphi
if iAge >= 18 then
begin
  if bHasLicense = True then
    bDrive := True
  else
    bDrive := False;
end
else
  bDrive := False;

Boolean Operators

Combine multiple conditions in one statement.

Boolean operators let you ask more than one question at the same time. Everyday analogy: to get into a club you might need to be 18 AND have an ID — both must be true. To qualify for a discount you might need to be a student OR a pensioner — either one is enough. NOT simply flips an answer around, like saying "if it is not a holiday, school is open".

OperatorRuleExample
ANDBoth conditions must be true(iAge >= 18) AND (bHasID = True)
ORAt least one condition must be true(sGender = 'M') OR (sGender = 'F')
NOTInverts the conditionNOT (iScore > 50)
Delphi — AND and OR examples
if (iAge >= 18) AND (bHasLicense = True) then
  bCanDrive := True;

if (iScore >= 30) OR (bHasSymbol = True) then
  lblResult.Caption := 'Passed';
Watch the order AND and OR are applied

When a condition mixes AND and OR without brackets, Delphi does not test them strictly left-to-right — NOT is applied first, then AND, and only then OR. This is the same idea as multiplication happening before addition in a maths expression. Two learners could type the exact same words and end up with logically different conditions, so get into the habit of bracketing every individual condition — it removes any doubt about what is being tested against what.

Shortcut — Assigning a Boolean Directly

Sometimes an entire if…then…else exists purely to store True or False in a Boolean variable. In that case the condition already is the answer you want, so the if is not needed at all — the condition can be assigned straight to the variable.

Delphi — two ways to record whether a learner passed
// Longer version:
if iMark >= 50 then
  bPassed := True
else
  bPassed := False;

// Shorter, equivalent version:
bPassed := iMark >= 50;

Simplifying a Long Condition with 'Flags'

A single if line that strings together many ANDs and ORs across several variables becomes hard to read, and one misplaced bracket can break the whole thing. A tidier approach is to work out each separate rule on its own line first, storing every result in its own Boolean variable (often called a flag), and letting the final decision combine only the flags.

Consider selecting a learner for the school athletics team: they must have run the trial faster than the qualifying time, attended at least 80% of the practice sessions, and not currently be under a sports suspension.

Delphi — team selection built from three flags
var
  bFastEnough, bAttendedEnough, bMaySelect : boolean;
  rTrialTime, rQualifyTime, rAttendancePercent : real;
  bSuspended : boolean;
begin
  bFastEnough     := rTrialTime <= rQualifyTime;
  bAttendedEnough := rAttendancePercent >= 80;
  bMaySelect      := NOT bSuspended;

  if bFastEnough AND bAttendedEnough AND bMaySelect then
    lblResult.Caption := 'Selected for the team'
  else
    lblResult.Caption := 'Not selected';
end;
Why this is worth doing

Each flag can be checked on its own, which makes it much easier to spot a mistake in one rule without untangling a single sprawling condition. The final decision then reads almost like plain English.

The IN Operator

Tests if a value is in a set. Cleaner than multiple OR conditions.

Delphi
// Check for specific values
if iNumber IN [1, 3, 5, 7] then
  ShowMessage('Odd single digit found');

// Range using ..
if iMark IN [0..49] then
  lblSymbol.Caption := 'F';

// Works with Char too
if cLetter IN ['A', 'E', 'I', 'O', 'U'] then
  ShowMessage('Vowel');

Sets, Ordinal Types & Sub-Ranges

Everything written inside those square brackets is called a set. Sets only work with ordinal data types — types where every value has one clear predecessor and one clear successor, so the values can be counted off in order. Integer, Char and Boolean all qualify. Real and String do not: between any two real numbers there are infinitely many more real numbers, so there is no single "next" one, which rules them out of a set.

Instead of listing every value separately, a sub-range lets you give just the two endpoints as <lowest> .. <highest>. A single set is allowed to mix plain values and sub-ranges together, separated by commas:

Delphi — a grade band and a seating rule built from sub-ranges
if cGrade IN ['A'..'C'] then
  ShowMessage('Well done — top achiever!');

if NOT (iSeat IN [1..15, 40..55]) then
  ShowMessage('Seat number must be 1-15 or 40-55');
Set limits

A sub-range built from Integers can only test values between 0 and 255 — anything outside that band raises an error. A set is also capped at a maximum of 265 values in total.

Decision Components

RadioGroup

Uses an ItemIndex property — first item is index 0.

Delphi
if rgpGender.ItemIndex = 0 then
  sGender := 'Male'
else
  sGender := 'Female';

CheckBox

Uses the Checked property — True or False.

Delphi
if chkInsurance.Checked = True then
  rCost := rCost + rInsuranceAmount;

The CASE Statement

Cleaner alternative to multiple IF…ELSE when testing one variable against many values. Works with Integer and Char only.

Use CASE when one variable could take many possible values and each value leads to a different outcome — like turning a mark into a grade symbol. Everyday analogy: a vending machine. You press one button (the value), and depending on which button it was, a different snack drops out. Writing that as a long chain of IF…ELSE statements works, but CASE lays it out neatly so it is much easier to read.

Syntax
case expression of
  value1: statement1;
  value2: statement2;
  value3: statement3;
else
  statementDefault;
end;
Remember

CASE has no begin, but always has end. You can use ranges with ..

Delphi — Grade symbol example
case iMark of
  80..100: lblSymbol.Caption := '7 — Outstanding';
  70..79:  lblSymbol.Caption := '6 — Meritorious';
  60..69:  lblSymbol.Caption := '5 — Substantial';
  50..59:  lblSymbol.Caption := '4 — Adequate';
  40..49:  lblSymbol.Caption := '3 — Moderate';
  30..39:  lblSymbol.Caption := '2 — Elementary';
else
  lblSymbol.Caption := '1 — Not Achieved';
end;

What Can Go in a CaseList

The value being tested (the Selector Expression, straight after the word case) must be ordinal. Each individual caseList is flexible about how it lists the values it matches — it can be one constant on its own, several constants separated by commas, a sub-range, or any mixture of these on the same line. The only rule is that a value may not show up in two different caseLists.

Delphi — bus fare worked out from the zone number
case iZone of
  1             : rFare := 12;
  2, 3          : rFare := 18;
  4..6          : rFare := 25;
  7, 8, 10..12 : rFare := 35;
end;

A caseList is not restricted to a single statement either — wrap several statements in begin…end exactly as you would for a multi-statement IF:

Delphi — tallying a register by arrival time
case iArrivalMinutes of
  0..5    : Inc(iOnTime);
  6..15   : Inc(iLate);
  16..60  : begin
                Inc(iLate);
                Inc(iVeryLate);
              end
else
  ShowMessage('Please check the time entered');
end; // end of case
Two easy mistakes to avoid

Only one caseList can fire per run of the statement, so double-check that your ranges don't overlap. And remember there is never a semicolon directly before the else part — the same rule as an IF statement. If a CASE branch needs to abandon the rest of the procedure entirely (say, after finding invalid data), call Exit — it works inside any procedure or function, not only inside a CASE.

MessageDlg

A pop-up dialog that asks the user a yes/no question and returns a result.

Delphi
if MessageDlg('Are you sure?', mtConfirmation, mbYesNo, 0) = mrYes then
  // execute if user clicked Yes
  ShowMessage('Confirmed!');
ParameterOptions
Message typemtConfirmation, mtInformation, mtWarning, mtError
ButtonsmbYesNo, mbOKCancel, mbYesNoCancel
ResultmrYes, mrNo, mrOK, mrCancel

Input Validation

No amount of clever code can rescue a program that starts with bad data — this is often summed up as GIGO: Garbage In, Garbage Out. Before a program uses a value in a calculation or a decision, it should first check that the value is reasonable. Checking a value before it gets used is called input validation, and the IF statement is the tool most often used to do it.

It helps to separate two ideas that are easy to confuse:

A validation rule spells out exactly what "valid" means for a piece of data, for example: "the number of matric dance tickets ordered must be a whole number from 1 to 6." Once the rule is written down, an IF statement can enforce it:

Delphi — range check
if (iTickets < 1) or (iTickets > 6) then
  ShowMessage('You may order between 1 and 6 tickets.');

Validation matters most when an invalid value would otherwise crash the program during a calculation. Delphi's Sqrt function, for instance, cannot handle a negative number, so the sign has to be checked first:

Delphi — check before Sqrt
if rNumber < 0 then
  ShowMessage('Cannot calculate the square root of a negative number')
else
  rAnswer := Sqrt(rNumber);
Keep asking until the answer is valid

A single warning message still leaves the program with no usable value to work with. Wrapping the input and the check in a REPEAT..UNTIL loop forces the user to keep trying until they enter something acceptable:

Delphi — repeat until valid
repeat
  iTickets := StrToInt(edtTickets.Text);
  if not (iTickets in [1..6]) then
    ShowMessage('You may order between 1 and 6 tickets.');
until iTickets in [1..6];

A range is only one kind of validation rule. Depending on the field, a program might instead need to check:

Worked Example — Validate, Grade & Decide

A typical question chains several decisions together: first validate the input with an if, then use a case to map the mark to a symbol, then a final if to decide pass/fail. This shows exactly when to reach for if and when for case.

Delphi — mark → symbol → result
procedure TForm1.btnGradeClick(Sender: TObject);
var
  iMark   : Integer;
  sSymbol : string;
begin
  iMark := StrToInt(edtMark.Text);

  // 1. Validate first — reject impossible marks (IF with OR)
  if (iMark < 0) or (iMark > 100) then
  begin
    ShowMessage('A mark must be between 0 and 100.');
    Exit;                       // stop here — don't grade an invalid mark
  end;

  // 2. Map the mark to a symbol — CASE handles the many bands neatly
  case iMark of
    80..100: sSymbol := '7';
    70..79:  sSymbol := '6';
    60..69:  sSymbol := '5';
    50..59:  sSymbol := '4';
    40..49:  sSymbol := '3';
    30..39:  sSymbol := '2';
  else
    sSymbol := '1';
  end;

  // 3. A final pass/fail decision (IF)
  if iMark >= 50 then
    lblResult.Caption := 'Symbol ' + sSymbol + ' - PASS'
  else
    lblResult.Caption := 'Symbol ' + sSymbol + ' - needs improvement';
end;
IF or CASE — how to choose

Use CASE when one variable maps to many ranges or values (the mark → symbol step). Use IF for a true/false test or when conditions combine different variables (the validation and the pass/fail steps). The pattern validate → work out → decide appears in almost every practical question.