Introduction to Programming in Matlab – High-Low Game Dr Michael Sek, 2006

INTRODUCTION TO PROGRAMMING IN MATLAB High-Low Game The development of a computer program to play the Hi-Lo game on a computer will be used to illustrate programming concepts and constructs. Study and implement the example shown below and then implement the Task on page 7. See the Matlab on-line help for syntax information. HI-LO GAME The aim of the game is to guess a randomly selected integer number in the range from 1 to xmax by a try-and-error method. In the example shown below the computer selects a number and the user tries to guess it. The only information provided after a guess is made, is whether the guess is too high or too low than the target number. The object of the game is to guess the number in the least number of trials. It is obvious that the complexity of the game increases when xmax is larger. The method we typically use to converge on the right answer is similar to a numerical method of finding roots, the bisection method. The root finding is used in many engineering problems, such as optimisation, error minimasation and boundary value problems involving ordinary differential equations. It would be desirable if the game • acknowledged the player when the number is guessed correctly. • tipped the player during the progress of the game if the same guess has been made before twice. • supported the match competition between an unspecified number of players, with the record keeping. • on completion, supplied the progressive score of the game for each player in graphical form and announced the winner. The Hi-Lo game algorithm is commonly known and understood. The Hi-Lo game will be used to illustrate the majority of MATLAB keywords, data types such as cells and structures, flow control constructs, graphics and other approaches limited only by imagination. GENERATION OF RANDOM NUMERS For the purpose of the Hi-Lo game the computer should generate a random integer number from a uniformly distributed population. It is desired that the number is between 1 and xmax , whatever xmax is. The xmax can be larger as the level of difficulty increases. Generation of a random number in the specified range Look in Help Index for "random". It states that: • "The rand function generates arrays of random numbers whose elements are uniformly distributed in the interval (0,1)." • "…rand, by itself, returns a scalar whose value changes each time it's referenced". x = rand x = 0.9501 x = rand x = 0.2311 In order to generate a random number between (0, xmax) when xmax is, say 100, try: xmax = 100; x = xmax * rand x = 55.4842 To round the result to the nearest integer use the function round() x = round(x) x = 55

1

Introduction to Programming in Matlab – High-Low Game Dr Michael Sek, 2006

As an example let's check if rand() really generate uniformly distribited random numbers. Let's generate 10000 uniformly distributed points from 0 to 100 and plot their frequency distribution (histogram) using 20 bins: xmax = 100; nBins = 20; nPoints = 10000; x = xmax * rand(nPoints,1); hist(x,nBins) xlabel('x') ylabel('Ocurrence') title('Uniform distribution') Uniform distribution 600

500

Ocurrence

400

300

200

100

0 0

10

20

30

40

50 x

60

70

80

90

100

In contrast to the uniformly distrubuted random number generator rand(), the function randn() produces the normally distributed (Gaussian) random numbers. In this instance, a set of points has the mean value of 0 and the standard deviation of 1. nPoints = 10000; nBins = 20; x = randn(nPoints,1); hist(x,nBins) %this function plots a histogram xlabel('x') ylabel('Occurrence') title('Gaussian distribution') grid on

2

Introduction to Programming in Matlab – High-Low Game Dr Michael Sek, 2006

Gaussian distribution 1500

occurrence

1000

500

0 -5

-4

-3

-2

-1

0

1

2

3

4

x

The so-called white noise is the normally (Gaussian) random signal which when plotted appears as shown below (the mean is 0, the standard deviation is 1). plot(randn(10000,1)) xlabel('Index') ylabel('x')

4

3

2

1

x

0

-1

-2

-3

-4

-5

0

1000

2000

3000

4000

5000 In d e x

6000

7000

8000

9000

10000

To hear the accoustic effect of the white noise on the computer with the sound turned on: sound(randn(50000,1)) For the purpose of the Hi-Lo game, to generate uniformly distributed numbers between 1 (not the zero) and xmax , when xmax is say 100 we need to make some adjustments: xmax = 100; x = 1 + round((xmax-1) .* rand) x = 26 3

Introduction to Programming in Matlab – High-Low Game Dr Michael Sek, 2006

The addition and subtraction of 1 is needed to adjust the range from (0, xmax-1) to (1, xmax) . Random number generators are very important in engineering. They are used eg in the measurement and analysis of structural vibration (automotive research and development, civil engineering troubleshooting) or in solving differential equations using the so called Monte Carlo method. For more information, see the on-line help.

HILO.M SCRIPT Ensure that you have changed the current folder from the dafault to your own working folder. Open a new empty *.M file script in the Matlab editor. To start the script type in comments such as : %hilo1.m script %This script is version 1 of the HI-LO game and save as hilo1.m . Although the script, when run, will not perform any action, the first comment in any *.M file will be displayed when help on that *.M file is sought. help hilo1 hilo1.m script This script is version 1 of the HI-LO game Continue the script to program the core part of the algorithm of the game. Later, new lines of code will be added, inserted amended as applicable. clear all %to clear workspace etc. xmax = 10; %For trial runs and debugging fprintf('The range is up to ') xmax x = 1 + round((xmax-1) * rand) guess = 0; %needed to enter the while loop while guess ~= x guess = input('Enter your guess: '); if guess > x fprintf('Your guess is too high\n') %\n stands for the new line character elseif guess < x fprintf('Your guess is too low\n') else fprintf('Congratulations - spot on\n') end end The script thus far has used • keywords while, if, elseif and end and other objects • functions fprintf(), input(), round(), rand() • a string-formatting character, newline, \n • relational operators ~= (not equal), > , < • assignment = A semicolon at the end of lines has been used to suppress displaying the result of each line of code. To play the game the random number generated by the computer must be hidden - place the semicolon at the end of the line: x = 1 + round((xmax-1) * rand);

4

Introduction to Programming in Matlab – High-Low Game Dr Michael Sek, 2006

Modification 1 Say, it would be desirable at the end of the game to • print how many guesses were needed to guess the number – a scalar variable that we call counter will be used for this purpose • plot a graph showing how the answers have converged on the solution – a vector variable, say, guessRecord will be used for this purpose

clear all xmax = 100; fprintf('The range is up to ') xmax x = 1 + round((xmax-1) * rand) counter = 0; guessRecord = []; guess = 0; while guess ~= x guess = input('Enter your guess: counter = counter+1; guessRecord(counter) = guess;

');

if guess > x fprintf('Your guess is too high\n') elseif guess < x fprintf('Your guess is too low\n') else fprintf('Congratulations - spot on\n') end end fprintf('The record:\n') guessRecord plot([1:length(guessRecord)]',guessRecord) hold on plot([1:length(guessRecord)]',guessRecord,'ro') plot([1;length(guessRecord)],[x; x],'r') hold off

The test output is, for example is The record: guessRecord = 30 60 40 48

60

55

50

Some new functions, eg length() and plot() in particular, have been used to achieve this outcome. See HELP for more information.

45

40

35

30

1

1.5

5

2

2.5

3

3.5

4

Introduction to Programming in Matlab – High-Low Game Dr Michael Sek, 2006

Modification 2 Three new keywords: switch, case and otherwise will be introduced to enable the entry of the level of difficulty at the start of the program (level is just a new scalar variable): level = input('Enter the level of difficulty: 1 to 3: switch level case 1 xmax = 100; case 2 xmax = 500; case 3 xmax = 5000; otherwise xmax = 100; end fprintf('The range is up to ') xmax

');

Modification 3 The final modification will enable a match play between practically unlimited number of players. New variable types, structure and cell are introduced to hold information about players' names and scores. Roles of the lines are explained in the comments %hilow2.m %HI-LOW game ver. 2 clear all %allocating the fields to the structure player %and assigning empty content {} [] player.name = {}; %string cell player.score = []; %a vector level = input('Enter the level of difficulty: 1 to 3: switch level case 1 xmax = 100; case 2 xmax = 500; case 3 xmax = 5000; otherwise xmax = 100; end fprintf('The range is up to ') xmax

');

%%%%%%%%start for a new player%%%%%%%%%%%%%%% for playerCounter = 1: Inf player.name{playerCounter} = input('Enter your name or just ENTER to exit: %to abort the for loop when just enter is pressed if strcmp(player.name{playerCounter},'') break end x = 1 + round((xmax-1) * rand) %append a semicolon for a real play counter = 0; guessRecord = []; guess = 0; while guess ~= x guess = input('Enter your guess: '); counter = counter+1; 6

','s');

Introduction to Programming in Matlab – High-Low Game Dr Michael Sek, 2006

guessRecord(counter,1) = guess; %to check a duplicate entry for k = 1: counter-1 if guessRecord(k) == guess fprintf('You have tried this number before\n'); end end %%%%%%%%%%%%%%%%%%%%%%%% if guess > x fprintf('Your guess is too high\n') elseif guess < x fprintf('Your guess is too lowl\n') else fprintf('Congratulations - spot on\n') player.score(playerCounter) = counter; %to add sound effects e.g. music load handel %load a *.MAT file sound(y,Fs) %play it with frequency Fs end end fprintf('The record:\n') guessRecord plot([1:length(guessRecord)]',guessRecord) hold on plot([1:length(guessRecord)]',guessRecord,'ro') plot([1;length(guessRecord)],[x; x],'r') hold off end

%%%%%%%%%%%%%%%%%%end of the new player for loop%%%%%%%%%%%%%%

%playerCounter is decremented by one to get it right (can you see why?) playerCounter = playerCounter - 1; fprintf('Results\n') for k = 1:playerCounter player.name{k} player.score(k) %uncomment these lines for formatted output %fprintf('%s\n',player.name{k}) %fprintf('%i\n',player.score(k)) end

There are endless possibilities to extend the program and to approach its development. A good way to learn various techniques used in programming and adopt your own programming style is to analyse examples of the Matlab code.

CONCLUSIONS AND ASSIGNMENT If you analyse how you make your choices as you keep guessing you will notice that for your next guess you halve the interval between the second last and the last choice when your guesses oscillate around the target. For example, if xmax =100 and your initial guess of 50 turns out to be too low, your next guess would be 75, and if this is too high, your next guess is either 62 or 63. The logical pattern indicates that you are in fact following a numerical algorithm. The computer, when appropriately programmed, can make guesses that will converge on the target, the same way you do. This "halving" logic is in fact similar in approach to a numerical method of finding roots of equations called bisection method.

TASK Write a program for the High-Low game with the reversed roles compared to the worked out example shown above, ie the computer is now to guess the number that you are thinking of, using the bisection method.

7