Morse Code
by Jack Fearn: L6 Age ~16
Introduction
Morse code translation is a suitably challenging programming exercise for students, and solutions in several languages are available on websites. Jack's program MorseCode (now available as a web version) translates from a string of characters to its Morse code equivalent. It both displays the Morse as dots and dashes (with a space added to represent the end of each character and a slash to represent the end of each word) and outputs it as sound. You can also input the dots and dashes with Morse punctuation and the program will translate it to the string of characters that it represents. Jack provides useful information about Morse code and also links to a the web site for further details, creating a nicely finished product.
A string array stores each string of dots and dashes at the index equal to the ASCII value of the character it represents. Decryption is trickier than encryption. Jack uses string manipulation neatly to separate a Morse stream into individual character strings for decryption, which he then achieves by linearly searching the array. Helpfully, the program outputs error messages in red when the input cannot be translated.
The following screenshots show a decryption, an encryption and a transmission.

Morse code translated to text

Text translated to Morse code

Morse code transmitted
Compile the program using Lazarus because it the uses the Clrscr procedure in the crt unit (which not built into Delphi) or see how to download and use crt in Delphi in our Graphics tutorial.
The Program
program MorseCode; { Copyright (c) 2011 Jack Fearn Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License, as described at http://www.apache.org/licenses/ and http://www.pp4s.co.uk/licenses/ } {$mode objfpc}{$H+} uses Classes, SysUtils, Crt, ShellAPI, Windows; {$IFDEF WINDOWS}{$R MorseCode.rc}{$ENDIF} const Pitch = 902; Dot = 75; Dash = 200; var Morse_Ascii : Array[1..90] of String = ({1}'','','','','','','','','','','','','','','','','','','','','','', '','','','', '','','','','',{32}'/ ',{*No proper code for '!'*}'', {34}'.-..-. ','','','','','.----. ', '-.--.- ', '-.--.- ','','','--..-- ', {45}'-....- ','.-.-.- ','-..-. ','----- ','.---- ','..--- ','...-- ','....- ', {53}'..... ','-.... ','--... ','---.. ','----. ','---... ','','','-...- ','', {63}'..--.. ','.--.-. ',{'A'}'.- ','-... ','-.-. ','-.. ','. ','..-. ','--. ', {72}'.... ','.. ','.--- ','-.- ','.-.. ','-- ','-. ','--- ','.--. ','--.- ', {82}'.-. ','... ','- ','..- ','...- ','.-- ','-..- ','-.-- ',{'Z'}'--.. '); Signal : String; Choice, i : Integer; Error : Boolean; Procedure Instructions; var handle : HWND; begin Clrscr; Writeln('Morse Code is transmitted through different combinations of two signals: '); Writeln; Writeln('''.'' - short signal (often called "dots" or "dits")'); Writeln('''-'' - long signal (often called "dashes" or "dahs")'); Writeln; Write('Press Enter to continue...'); Readln; Clrscr; Writeln('This program uses the . and - symbols (full stop and hyphen)'); Writeln('The morse code is written as so: '); Writeln; Writeln('".... . .-.. .-.. --- / .-- --- .-. .-.. -.. "'); Writeln; Write('Press Enter to continue...'); Readln; Clrscr; Writeln('Each space represents the end of a character,'); Writeln('breaking the sequence up so it can be understood.'); Writeln; Writeln('Each forward slash, represents the end of a word.'); Writeln('This must also be followed by a space.'); Writeln; Writeln('Punctuation and numbers have their own set of signals.'); Writeln('Code must be input this way for the computer to understand.'); Writeln; Writeln('For further online information, Press 1, or to go back to the menu, Press 2.'); Readln(Choice); Case Choice of 1 : begin Writeln('Your browser will now direct you to www.learnmorsecode.com'); Delay(2000); Shellexecute(handle, 'open', pchar('http://www.learnmorsecode.com/'), nil,nil, sw_show); Delay(5000); Writeln('Press Enter to continue'); Readln; end; 2 : begin end; end; //Case end; Procedure Transmit(SignalX : String); begin Clrscr; Writeln('Transmitting...'); Writeln; Delay(500); For i := 1 to (Length(SignalX)) do begin Case SignalX[i] of '-' : begin Windows.Beep(Pitch,Dash); Write ('-'); end; '.' : begin Windows.Beep(Pitch,Dot); Write('.'); end; ' ' : begin Delay(300); Write('/ '); end; end; //Case Delay(80) end; //For i Writeln; Writeln; Writeln('Sent!'); Readln; end; Procedure Encrypt; var Passage : String; CharCount : Integer; begin Clrscr; Signal := ''; Writeln('Enter passage to be encrypted. Press Enter when complete.'); gotoxy(1,15); Writeln('A : .- B : -... C : -.-. D : -.. E : . '); Writeln('F : ..-. G : --. H : .... I : .. J : .---'); Writeln('K : -.- L : .-.. M : -- N : -. O : --- '); Writeln('P : .--. Q : --.- R : .-. S : ... T : - '); Writeln('U : ..- V : ...- W : .-- X : -..- Y : -.--'); Writeln('Z : --.. 0 : ----- 1 : .---- 2 : ..--- 3 : ...--'); Writeln('4 : ....- 5 : ..... 6 : -.... 7 : --... 8 : ---..'); Writeln('9 : ----. " : .-..-. '' : .----. ( or ) : -.--.- '); Writeln(', : --..-- - : -....- . : .-.-.- / : -..-. '); Writeln(': : ---... ; : -.-.-. = : -...- ? : ..--.. @ : .--.-.'); gotoxy(1,2); Readln(Passage); CharCount := Length(Passage); Passage := UpperCase(Passage); For i := 1 to CharCount do begin If Ord(Passage[i]) < 90 then begin Signal := Signal + (Morse_Ascii[Ord(Passage[i])]); // For playback with windows beep // turn Code on screen Red/Green when played? Write(Morse_Ascii[Ord(Passage[i])]); end; //If Ord end; //For i Readln; Transmit(signal); end; Procedure Decrypt; var StartCode, Code, Letter, Translation : String; a, x, y, SpacePos : Integer; begin Clrscr; Translation := ''; Writeln('Enter code to be decrypted. Press Enter when complete.'); gotoxy(1,15); Writeln('A : .- B : -... C : -.-. D : -.. E : . '); Writeln('F : ..-. G : --. H : .... I : .. J : .---'); Writeln('K : -.- L : .-.. M : -- N : -. O : --- '); Writeln('P : .--. Q : --.- R : .-. S : ... T : - '); Writeln('U : ..- V : ...- W : .-- X : -..- Y : -.--'); Writeln('Z : --.. 0 : ----- 1 : .---- 2 : ..--- 3 : ...--'); Writeln('4 : ....- 5 : ..... 6 : -.... 7 : --... 8 : ---..'); Writeln('9 : ----. " : .-..-. '' : .----. ( or ) : -.--.- '); Writeln(', : --..-- - : -....- . : .-.-.- / : -..-. '); Writeln(': : ---... ; : -.-.-. = : -...- ? : ..--.. @ : .--.-.'); gotoxy(1,3); Readln(StartCode); Code := StartCode; a := Length(Code); If not (Code[a] = ' ') then // Most likely error when writing in begin Code := Code + ' '; a += 1; end; //If not Repeat Error := True; SpacePos := Pos(' ',Code); Letter := Leftstr(Code, SpacePos); Code := Rightstr(Code,(a-SpacePos)); a := Length(Code); For i := 32 to 90 do begin If Letter = Morse_Ascii[i] then begin Translation := Translation + (Char(i)); Error := False; end; //If Letter end; //For i Until (Error = True) or (Code = ''); If Error = True then begin Writeln; Writeln('Error! Unable to decipher code:'); Writeln; x := Pos(Letter,StartCode); y := WhereY; Writeln(StartCode); Writeln; gotoxy(x,y); textcolor(red); Writeln(Letter); textcolor(white); end else begin Writeln(Translation); end; //If Error Readln; end; begin Repeat Writeln('Morse Code Encrypter & Decrypter'); Writeln('1 - Encrypt'); Writeln('2 - Decrypt'); Writeln('3 - Code instructions/Help'); Writeln('4 - Quit'); Readln(Choice); Case Choice of 1 : begin Encrypt; end; 2 : begin Decrypt; end; 3 : begin Instructions; end; 4 : begin halt; end; end; //Case clrscr; Until 'The Music' = 'Dead'; end.
Remarks
Could you write your own Morse code translator?