HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Binary and linear search methods for a number-guessing game

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
linearnumbersearchmethodsgamebinaryforguessingand

Problem

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? > ');
readln(input);
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');
readln;
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 ma

Solution


  • 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? > ');
      ReadLn(SInput);

      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.');
          ReadLn;
        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('Is your number ',IGuess,'?');
    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 > ');
    ReadLn(SInput);

    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.');
          ReadLn;
          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).');
        ReadLn;
        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? > ');
  ReadLn(SInput);

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

Code Snippets

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? > ');
      ReadLn(SInput);

      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.');
          ReadLn;
        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('Is your number ',IGuess,'?');
    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 > ');
    ReadLn(SInput);

    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.');
          ReadLn;
          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).');
        ReadLn;
        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 

Context

StackExchange Code Review Q#108507, answer score: 2

Revisions (0)

No revisions yet.