# Binary and linear search methods for a number-guessing game

This is a code written is Pascal (Delphi). It asks the user to think of a number between min_ and max_ and then guesses the number using either a Binary or a Linear method.

  program BandLSearch;

{$APPTYPE CONSOLE} {$R *.res}

uses
System.SysUtils;

var
min_, max_: integer; // set the max and min to check between the two (inclusive)

BinorLin: string;  // Get user input as to which method they wish to use

procedure Linear();
{
This uses a linear search technique to guess the number.
It will ask min_ then min_ +1 etc up to max_. e.g. 1, 2, 3, ... , 99, 100
}
var
input: string;
count: integer; // For the foor loop

begin
for count := min_ to max_ do  // loop from min to max and ask if the number is corect, one by one
begin
write('Is your number ',count,'? Y or N? > ');
if (input = 'Y') or (input = 'y') then
begin
writeln('Found your number, it is ',count);
readln;       // Prevent the code ending without being able to read the output.
break
end
else
begin
if count = max_ then  //If they have reached max and not said yes, they are lying
begin
writeln('You have cheated');
end;
end;

end;
end;

procedure Binary();
{
This uses a linear search technique to guess the number
It will ask (min_ + max_)/2 and the user says too high or too low.
Depending on the response, it will set either min_ or max_ to the guessed number
Eventually it narrows down, eg:
50, 75, 62, 68, 65, 63, 64
L   H   L   H   H   L   C
}
var
input: string;
guess, preGuess: integer; // For the current computer guess
goesTaken : integer; // To monitor the guesses needed
end_: integer;  // Will increase for each guess that max_ = min_

begin

preGuess := -1; // Will not be the guess.
goesTaken := 0;
end_ := 0;

while end_ < 2 do  //when it is 2, it will have guessed all the numbers.
begin

inc(goesTaken);

guess := (max_ + min_) div 2;

writeln('If guess is too high enter H, if it''s too low, enter L.');
write('If the guess is corect, enter C > ');

if input = 'H' then  // Number is too high, so guess lower
max_ := guess - 1
else
if input = 'L' then  // Number is too low, so guess higher
min_ := guess + 1
else                 // Number is correct
begin
writeln('Found your number, it is ',guess);
writeln('It took me ',goesTaken,' goes.');
break
end;

if guess = preGuess then // If the computer asks the same number two times in a row, the user has cheated.
begin
writeln('You have cheated');
break
end
else
preGuess := guess;

if (max_ = min_) then // If min is the same as max, then 1 go later the code can exit.
begin
end_ := end_ + 1;
end;

end;

end;

begin

min_ := 0;
max_ := 100;

writeln('Think of a number between ',min_, ' and ', max_, '. I will guess it.');

write('Do you want to use a (l)inear or a (b)inary search? > ');

if BinorLin = 'l' then   // User input comparison
begin
writeln('Starting Linear Search...');
Linear();
end
else;
begin
if BinorLin = 'b' then
begin
writeln('Starting Binary Search...');
Binary();
end
else  // didn't enter 'l' or 'b'
begin
exit
end;
end;
end.


This is a high school assignment, however I have already handed it in (today) for marking. I'd be interested in the opinion of more than my teacher.

• I would rather use Free Pascal than Delphi, makes code more promptly editable;
• You should avoid nested if's, specially in pascal, where you can easily get lost otherwise. Use the case statement instead.
• pascal do not use camelCase but PascalCase.
• you should use const for constants, and name them like PASCAL_CONSTANT.
• you should prefix your own variables to avoid getting lost in terms of scope and variables types:
• F for class fields;
• T for objects;
• A for property (generic) values;
• I for integers, for local variables
• S for strings, for local variables
• and so on
• starting code messages should be put at the starting of the code, i.e., first line after a begin statement of the corresponding procedure, function or program.
• It is not necessary to write the () for methods that does not require entries.
• Pascal is case insensitive. However, it does not mean you should not be consistent with existing code: you should use WriteLn, instead writeln, for example.

Putting all together:

program BandLSearch;

uses SysUtils;

var
SInput: string;  // Get user input as to which method they wish to use

const // set the max and min to check between the two (inclusive)
MIN_VALUE : integer = 0;
MAX_VALUE : integer = 100;

{ This uses a linear search technique to guess the number.
It will ask MIN_VALUE then MIN_VALUE +1 up to MAX_VALUE. e.g. 1, 2, 3, ... , 99, 100 }
procedure Linear;
var
ICount: integer; // For the foor loop

begin
WriteLn('Starting Linear Search...');
for ICount := MIN_VALUE to MAX_VALUE do // loop from min to max and ask if the number is corect, one by one
begin
Write('Is your number ',ICount,'? Y or N? > ');

SInput := UpperCase(SInput);
if SInput = 'Y' then
begin
WriteLn('Found your number, it is ',ICount);
ReadLn; // Prevent the code ending without being able to read the output.
Break
end;

if ICount = MAX_VALUE then  //If they have reached max and not said yes, they are lying
begin
WriteLn('You have cheated.');
end;
end;
end;

{  This uses a binary search technique to guess the number
It will ask (MIN_VALUE + MAX_VALUE)/2 and the user says too high or too low.
Depending on the response, it will set either MIN_VALUE or MAX_VALUE to the guessed number
Eventually it narrows down, eg:
50, 75, 62, 68, 65, 63, 64
L   H   L   H   H   L   C }
procedure Binary;
var
IGuess, IPreGuess, // For the current computer guess
IGoesTaken,        // To monitor the guesses needed
IEnd: integer;     // Will increase for each guess that MAX_VALUE = MIN_VALUE

begin
WriteLn('Starting Binary Search...');
IPreGuess := -1; // Will not be the guess.
IGoesTaken := 0;
IEnd := 0;

repeat
Inc(IGoesTaken);
IGuess := (MAX_VALUE + MIN_VALUE) div 2;

WriteLn('If guess is too high enter H, if it''s too low, enter L.');
Write('If the guess is correct, enter C or Y > ');

SInput := UpperCase(SInput);
case SInput of
'H': MAX_VALUE := IGuess - 1; // Number is too high, so guess lower
'L': MIN_VALUE := IGuess + 1; // Number is too low, so guess higher
'C', 'Y':
begin
WriteLn('Found your number, it is ',IGuess);
WriteLn('It took me ',IGoesTaken,' goes.');
Break;
end;
else // Number is correct

end;

if IGuess = IPreGuess then // If the computer asks the same number two times in a row, the user has cheated.
begin
WriteLn('Sorry, I did not undertand you (or you have cheated).');
Break;
end
else
IPreGuess := IGuess;

if MAX_VALUE = MIN_VALUE then
IEnd := IEnd + 1; // If min is the same as max, then 1 go later the code can exit.
until IEnd >= 2;
end;

begin
WriteLn('Think of a number between ',MIN_VALUE, ' and ', MAX_VALUE, '. I will guess it.');
Write('Do you want to use a (l)inear or a (b)inary search? > ');

SInput := LowerCase(SInput);
case SInput of // User input comparison
'l': Linear;
'b': Binary;
else
Exit;
end;
end.

• FTA is common in Pascal, Free Pascal and Delphi. For local variables there are no standards, but you will frequently find S for local strings and I for loop integers. IS is an extension considering that fact. – cpicanco Nov 13 '15 at 2:58
• @holroy, after all, the point is not getting lost. Works for me :) – cpicanco Nov 13 '15 at 3:01
• I'm all for clarity in naming, but in C# or Python naming standards is used where you don't need prefixes, but rather use variations on camelCase or PascalCase or snake_case. And you should normally not have a problem knowing the type of a variable as that should be given by the name/context. The same applies for scope, as if your code is so long you don't have control of the scope you should add some procedures/methods/functions to narrow down the scope. But YMMV... – holroy Nov 13 '15 at 3:05
• For me works like that, PascalMethod, LPascalLocalVariable, AMethodValue, FFieldAttribute, TAbstractObject. As you can see, methods are not prefixed. But, again, for local variables there are no standards as far as I know. – cpicanco Nov 13 '15 at 3:16
• I will think about these. I essentially have to use Delphi but I'll consider the others. I especially like the use of case statements but I'm unsure the variable prefix is needed, and some of the other naming conventions seem strange. Thanks though. – Tim Nov 13 '15 at 7:55