Tic-tac-toe in Erlang — utilities to introduce randomness
This is part of an Erlang tutorial built around a tic-tac-toe program. The program is stuffed into one file, called tic.erl and available here. The source code and this tutorial are organized into these sections:
- Introduction
- Top-level loop
- User input
- Board display
- Board abstraction
- Game abstraction
- Next move calculations and predictions
- Predicted outcome abstraction
- Utilities to introduce randomness (this page)
- Macros for testing and debugging
Utilities to introduce randomness
The appearance of randomness is important for some games, where the computer sometimes has to choose between several equally good moves. By varying its choices, the computer’s play seems more natural, more human, and more interesting.
The game calls randomize_random_seed() once, when it starts up. If it didn’t then the computer would always play exactly the same moves if, for example, you had it play itself.
Of course when running some daily regression tests you might want the computer to play exactly the same moves every time. In that situation you shouldn’t call randomize_random_seed(). Instead you should set the seed explicitly or just use the fixed default seed.
Interface
This short section has only two functions, and both deal with psuedo-random integers.
Source code
Here’s the Erlang source code for the random utilities section of the tic.erl file.
% --------------------------------------------------------------
% Random Utilities
%
% Utilities to introduce randomness into the game play.
% --------------------------------------------------------------
% --------------------------------------------------------------
% random_list_element( List )
%
% Returns a single element from List.
% List must have at least one element.
random_list_element( List ) ->
if
List == [] -> erlang:error( badarg);
tl( List) == [] -> hd( List);
true ->
Count = length( List),
Index = random:uniform( Count),
lists:nth( Index, List)
end.
% --------------------------------------------------------------
% randomize_random_seed( )
%
% Seed the random generator with unpredictable numbers.
%
% Uses now( ), which returns the current time in this form:
% {Mega_seconds, Seconds, Micro_seconds}
%
% Maybe these integers aren't the best seeds since
% Mega-seconds doesn't change much and Micro-seconds is
% always a multiple of 1000 on my machine.
%
% There are other sources of unpredictable numbers we could
% use as seeds:
%
% statistics( wall_clock) ->
% {Total_milliseconds, Elapsed_milliseconds}
% Total milliseconds seems a good candidate.
%
% statistics( garbage_collection) ->
% {Number_of_gcs, Words_reclaimed, 0}
% Words_reclaimed is a good unpredictable integer.
%
% random:seed(..) returns the previous seed value (3-tuple
% of integers), so we could restore the seed value in case
% some other system is counting on it.
% Remember that random:seed(..) returns the atom 'undefined'
% if the seed has never been set before.
randomize_random_seed( ) ->
% Get a seed of 3 psuedo-random looking integers.
{Meg_secs, Secs , Micro_secs} = now( ),
% Set the seed.
random:seed( Meg_secs, Secs, Micro_secs).
Comments
Leave a Reply