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.
- React to input – an age-check on a website: if you are old enough it lets you in, otherwise it blocks you.
- Validate data – if a mark is below 0 or above 100, warn the user it is invalid.
- Choose an outcome – if a learner scored 50 or more, display "Passed", otherwise display "Failed".
- Stay safe – if the password matches, grant access; otherwise deny it.
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.
IF … THEN (one-way)
if condition then
statement;IF … THEN … ELSE (two-way)
Never put a ; on the line before else — it ends the if statement too early.
if condition then
statement
else
statement;Multiple Statements — use BEGIN…END
if iAge >= 18 then
begin
lblResult.Caption := 'Adult';
btnVote.Enabled := True;
end
else
begin
lblResult.Caption := 'Minor';
btnVote.Enabled := False;
end;Examples
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
| Operator | Meaning | Example |
|---|---|---|
= | Equal to | iAge = 18 |
<> | Not equal to | sName <> 'Admin' |
> | Greater than | iScore > 50 |
< | Less than | iAge < 18 |
>= | Greater than or equal to | iMark >= 30 |
<= | Less than or equal to | rPrice <= 100.0 |
Nested IF
An IF inside another IF.
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".
| Operator | Rule | Example |
|---|---|---|
AND | Both conditions must be true | (iAge >= 18) AND (bHasID = True) |
OR | At least one condition must be true | (sGender = 'M') OR (sGender = 'F') |
NOT | Inverts the condition | NOT (iScore > 50) |
if (iAge >= 18) AND (bHasLicense = True) then
bCanDrive := True;
if (iScore >= 30) OR (bHasSymbol = True) then
lblResult.Caption := 'Passed';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.
// 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.
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;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.
// 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:
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');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.
if rgpGender.ItemIndex = 0 then
sGender := 'Male'
else
sGender := 'Female';CheckBox
Uses the Checked property — True or False.
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.
case expression of
value1: statement1;
value2: statement2;
value3: statement3;
else
statementDefault;
end;CASE has no begin, but always has end. You can use ranges with ..
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.
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:
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 caseOnly 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.
if MessageDlg('Are you sure?', mtConfirmation, mbYesNo, 0) = mrYes then
// execute if user clicked Yes
ShowMessage('Confirmed!');| Parameter | Options |
|---|---|
| Message type | mtConfirmation, mtInformation, mtWarning, mtError |
| Buttons | mbYesNo, mbOKCancel, mbYesNoCancel |
| Result | mrYes, 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:
- Valid data — the value falls within rules a program can check on its own, e.g. a ticket quantity of
4is a whole number the program can accept. - Correct data — the value is actually the right one for this situation, e.g. that this particular learner really did order 4 tickets. A program cannot verify this by itself; a person has to check it against a reliable source.
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:
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:
if rNumber < 0 then
ShowMessage('Cannot calculate the square root of a negative number')
else
rAnswer := Sqrt(rNumber);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:
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:
- Format — does the value match an expected pattern, e.g. a South African ID number must be exactly 13 digits.
- Type — is the value the right kind of data, e.g. rejecting text where a numeric mark is expected.
- Presence — has a required field been left empty, e.g. testing
edtName.Text <> ''.
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.
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;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.