Blackjack 1
1

First, reassign the browser to Full Screen view, to give this worksheet and your code as much space as possible.

Then choose either one of the two options below:

Option 1: Start this worksheet from scratch

- First Enter your name:
- Then
  .
- All answers that you subsequently enter/edit will be auto-saved to this sheet.

Option 2: Continue, or view, previous work

- All answers that you subsequently enter/edit will be auto-saved to this sheet.
- The first time you re-load an answers sheet - within a single session on Elan - you will be asked to confirm that you understand this.

This worksheet is copyright © Richard Pawson 2025, and protected by the Creative Commons license: Attribution-NonCommercial-NoDerivatives 4.0 International. You may freely make and distribute copies of this worksheet as is, but if you modify this worksheet you may not distribute your modified version (outside your own teaching institution) without the author's permission. Please email the author to report errors or suggest improvements.

# Step 1: learning the rules of Blackjack

Watch the first video:

Now
# 9b4db9c7c04abae34ee73a7669ea4d763b6e5989ccb8a58657387f7465748a01 Elan 2.0.0-alpha5 valid main variable game set to new Game(1000) call game.addPlayer(new HumanPlayer("Player A", 1000)) variable anotherRound set to true while anotherRound call playOneRound(game) call game.setMessage("Points updated. Do you want to play another round? (press y or n)") call clearKeyBuffer() call display(game) variable k set to waitForKey().lowerCase() if k.equals("y") then call game.setMessage("") else reassign anotherRound to false end if end while end main procedure playOneRound(game as Game) call game.newRound() call display(game) variable dealer set to game.dealer variable faceCard set to dealer.faceCard for player in game.players call player.startTurn() call display(game) while player.status is Status.active call player.nextAction(faceCard) call display(game) end while end for call dealer.play() call display(game) while dealer.status is Status.active call dealer.nextAction(faceCard) call display(game) end while call game.updatePoints() end procedure procedure display(game as Game) variable html set to $"<style>{styleSheet}</style>{htmlForGame(game)}" call displayHtml(html) call sleep(1.5) end procedure function determinePlayerOutcome(dealer as Dealer, player as Player) returns Outcome variable d set to dealer.status variable dTotal set to dealer.handTotal variable p set to player.status variable pTotal set to player.handTotal variable bust set to Status.bust variable bj set to Status.blackjack variable win set to Outcome.win variable winDouble set to Outcome.winDouble variable lose set to Outcome.lose variable draw set to Outcome.draw variable playerOutcome set to draw if p is bust then reassign playerOutcome to lose elif (p is bj) and (d isnt bj) then reassign playerOutcome to winDouble elif d is bust then reassign playerOutcome to win elif (d is bj) and (p is bj) then reassign playerOutcome to draw elif p is bj then reassign playerOutcome to winDouble elif d is bj then reassign playerOutcome to lose elif pTotal > dTotal then reassign playerOutcome to win elif pTotal < dTotal then reassign playerOutcome to lose else # strictly, this 'else' clause is redundant - as the variable was initialised to 'draw' - but added for clarity reassign playerOutcome to draw end if return playerOutcome end function test test_determinePlayerOutcome let dbj be (new Dealer(0)).withStatus(Status.blackjack) assert dbj.status is Status.blackjack let d21 be (new Dealer(0)).withStatus(Status.standing).withHandTotal(21) assert d21.status is Status.standing assert d21.handTotal is 21 let d17 be (new Dealer(0)).withStatus(Status.standing).withHandTotal(17) let dbu be (new Dealer(0)).withStatus(Status.bust) let pbj be (new HumanPlayer("", 0)).withStatus(Status.blackjack) assert pbj.status is Status.blackjack let p21 be (new HumanPlayer("", 0)).withStatus(Status.standing).withHandTotal(21) let p17 be (new HumanPlayer("", 0)).withStatus(Status.standing).withHandTotal(17) let pbu be (new HumanPlayer("", 0)).withStatus(Status.bust) assert determinePlayerOutcome(dbj, pbj) is Outcome.draw assert determinePlayerOutcome(dbj, p21) is Outcome.lose assert determinePlayerOutcome(dbj, pbu) is Outcome.lose assert determinePlayerOutcome(d21, pbj) is Outcome.winDouble assert determinePlayerOutcome(d21, p21) is Outcome.draw assert determinePlayerOutcome(d21, p17) is Outcome.lose assert determinePlayerOutcome(d21, pbu) is Outcome.lose assert determinePlayerOutcome(dbu, pbj) is Outcome.winDouble assert determinePlayerOutcome(dbu, p17) is Outcome.win assert determinePlayerOutcome(dbu, pbu) is Outcome.lose end test function dealCard(random as Float) returns Card variable number set to (random*52).floor() variable rank set to rankValue().keys()[divAsInt(number, 4)] variable suit set to number mod 4 return new Card(rank, intAsSuit(suit), false) end function test test_dealCard let c1 be dealCard(0) assert c1.rank is "2" assert c1.suit is Suit.clubs let c2 be dealCard(0.9999999) assert c2.rank is "A" assert c2.suit is Suit.spades let c3 be dealCard(0.5) assert c3.rank is "8" assert c3.suit is Suit.hearts let c4 be dealCard(0.24) assert c4.rank is "5" assert c4.suit is Suit.clubs end test function intAsSuit(n as Int) returns Suit variable suit set to Suit.clubs if n is 1 then reassign suit to Suit.diamonds elif n is 2 then reassign suit to Suit.hearts elif n is 3 then reassign suit to Suit.spades end if return suit end function test test_intAsSuit assert intAsSuit(0) is Suit.clubs assert intAsSuit(1) is Suit.diamonds assert intAsSuit(2) is Suit.hearts assert intAsSuit(3) is Suit.spades end test function htmlForGame(game as Game) returns String variable html set to "<div class='game'>" reassign html to html + htmlForPlayer(game.dealer) for player in game.players reassign html to html + htmlForPlayer(player) end for reassign html to html + $"<div class='message'>{game.message}</div>" return html + "</div>" end function test test_htmlForGame let c1 be new Card("3", Suit.clubs, false) let c2 be new Card("K", Suit.spades, true) let p be (new HumanPlayer("fred", 10)).withCards([c1, c2]) let players be (new List<of Player>()).withAppend(p) let g2 be (new Game(1)).withPlayers(players) assert htmlForGame(g2) is "<div class='game'><div class='player'><div class='details'>Dealer - 1 points </div><div class='hand'></div></div><div class='player'><div class='details'>fred - 10 points - hand total: 0</div><div class='hand'><div class='card black'><div class='u'>3</div><div class='v'>&clubs;</div><div class='a'>&clubs;</div><div class='b'>&clubs;</div><div class='c'>&clubs;</div></div><div class='card reversed'></div></div></div><div class='message'></div></div>" end test function htmlForPlayer(player as Player) returns String variable html set to "<div class='player'>" reassign html to html + $"<div class='details'>{player.name} - {player.points} points {player.getMessage()}</div>" reassign html to html + "<div class='hand'>" for card in player.cards variable suit set to card.suit variable rank set to card.rank reassign html to html + htmlForCard(card) end for return html + "</div></div>" end function test test_htmlForPlayer let c1 be new Card("3", Suit.clubs, false) let c2 be new Card("K", Suit.spades, true) let p be (new HumanPlayer("charlie", 10)).withCards([c1, c2]) assert htmlForPlayer(p) is "<div class='player'><div class='details'>charlie - 10 points - hand total: 0</div><div class='hand'><div class='card black'><div class='u'>3</div><div class='v'>&clubs;</div><div class='a'>&clubs;</div><div class='b'>&clubs;</div><div class='c'>&clubs;</div></div><div class='card reversed'></div></div></div>" end test function htmlForCard(card as Card) returns String variable html set to "" if card.faceDown then reassign html to "<div class='card reversed'>" else variable rank set to card.rank variable suit set to card.suit variable colour set to colourForSuit(suit) variable symbol set to symbolForSuit(suit) reassign html to $"<div class='card {colour}'>" variable u set to htmlForSpot("u", rank) variable v set to htmlForSpot("v", symbol) variable grid set to "" for location in gridForRank(rank) if location.equals("royal") then reassign grid to grid + htmlForSpot(location, rank) else reassign grid to grid + htmlForSpot(location, symbol) end if end for reassign html to html + $"{u}{v}{grid}" end if return html + "</div>" end function test test_htmlForCard variable c1 set to new Card("3", Suit.clubs, false) assert htmlForCard(c1) is "<div class='card black'><div class='u'>3</div><div class='v'>&clubs;</div><div class='a'>&clubs;</div><div class='b'>&clubs;</div><div class='c'>&clubs;</div></div>" variable c2 set to new Card("K", Suit.spades, true) assert htmlForCard(c2) is "<div class='card reversed'></div>" end test function htmlForSpot(id as String, content as String) returns String return $"<div class='{id}'>{content}</div>" end function test test_htmlForSpot assert htmlForSpot("c", "&hearts;") is "<div class='c'>&hearts;</div>" assert htmlForSpot("u", "10") is "<div class='u'>10</div>" end test class Game constructor(dealerStartPoints as Int) reassign this.dealer to new Dealer(dealerStartPoints) reassign this.players to new List<of Player>() reassign this.message to "" end constructor property dealer as Dealer property players as List<of Player> property message as String function withPlayers(p as List<of Player>) returns Game let copyOfThis be copy(this) reassign copyOfThis.players to p return copyOfThis end function procedure newRound() variable dealer set to this.dealer call dealer.newHand() for player in this.players call player.newHand() end for end procedure procedure updatePoints() for player in this.players call player.determineOutcomeAndUpdatePoints(this.dealer) end for end procedure procedure addPlayer(player as Player) variable players set to this.players call players.append(player) end procedure procedure setMessage(message as String) reassign this.message to message end procedure function toString() returns String return "a Game" end function end class class Card property suit as Suit property rank as String property faceDown as Boolean constructor(rank as String, suit as Suit, facedown as Boolean) reassign this.rank to rank reassign this.suit to suit reassign this.faceDown to facedown end constructor procedure turnFaceUp() reassign this.faceDown to false end procedure procedure turnFaceDown() reassign this.faceDown to true end procedure function toString() returns String return $"{this.rank}{symbolForSuit(this.suit)}" end function end class abstract class Player property name as String property points as Int property cards as List<of Card> property handTotal as Int property softAce as Boolean property status as Status property hasTurn as Boolean procedure startTurn() if this.status is Status.active then reassign this.hasTurn to true end if end procedure procedure determineOutcomeAndUpdatePoints(dealer as Dealer) variable playerOutcome set to determinePlayerOutcome(dealer, this) if playerOutcome is Outcome.winDouble then call this.changePointsBy(2) call dealer.changePointsBy(-2) elif playerOutcome is Outcome.win then call this.changePointsBy(1) call dealer.changePointsBy(-1) elif playerOutcome is Outcome.lose then call this.changePointsBy(-1) call dealer.changePointsBy(1) end if end procedure procedure evaluateStatus(newCard as Card) if (this.cardCount() is 2) and (this.handTotal is 21) then reassign this.status to Status.blackjack elif (this.handTotal > 21) and (this.softAce) then reassign this.handTotal to this.handTotal - 10 reassign this.softAce to false elif this.handTotal > 21 then reassign this.status to Status.bust elif this.handTotal is 21 then reassign this.status to Status.standing end if if this.status isnt Status.active then reassign this.hasTurn to false end if end procedure procedure stand() reassign this.status to Status.standing reassign this.hasTurn to false end procedure procedure draw() variable newCard set to dealCard(random()) variable cards set to this.cards call cards.append(newCard) if newCard.rank.equals("A") then call this.addAce() else reassign this.handTotal to this.handTotal + rankValue()[newCard.rank] end if call this.evaluateStatus(newCard) end procedure procedure addAce() if this.softAce then reassign this.handTotal to this.handTotal + 1 else reassign this.handTotal to this.handTotal + 11 reassign this.softAce to true end if end procedure function cardCount() returns Int return this.cards.length() end function procedure changePointsBy(amount as Int) reassign this.points to this.points + amount end procedure abstract procedure newHand() procedure newHandHelper() reassign this.hasTurn to false reassign this.softAce to false reassign this.cards to new List<of Card>() reassign this.handTotal to 0 reassign this.status to Status.active call this.draw() call this.draw() end procedure abstract function getMessage() returns String function statusAsString() returns String variable msg set to "" variable status set to this.status if this.hasTurn then reassign msg to msg + " - PLAYING" elif status is Status.standing then reassign msg to msg + " - STANDING" elif status is Status.blackjack then reassign msg to msg + " - BLACKJACK" elif status is Status.bust then reassign msg to msg + " - BUST" end if return msg end function abstract procedure nextAction(dealerFaceCard as Card) end class class Dealer inherits Player constructor(startingPoints as Int) reassign this.name to "Dealer" reassign this.points to startingPoints reassign this.cards to new List<of Card>() reassign this.faceCard to new Card("2", Suit.clubs, true) end constructor property faceCard as Card property hasPlayed as Boolean function withStatus(status as Status) returns Dealer let copyOfThis be copy(this) reassign copyOfThis.status to status return copyOfThis end function function withHandTotal(ht as Int) returns Dealer let copyOfThis be copy(this) reassign copyOfThis.handTotal to ht return copyOfThis end function procedure play() call this.startTurn() variable hiddenCard set to this.cards[1] call hiddenCard.turnFaceUp() reassign this.hasPlayed to true end procedure procedure newHand() reassign this.hasPlayed to false call this.newHandHelper() reassign this.faceCard to this.cards[0] variable hiddenCard set to this.cards[1] call hiddenCard.turnFaceDown() end procedure procedure nextAction(faceCard as Card) if this.handTotal < 17 then call this.draw() else call this.stand() end if end procedure function getMessage() returns String variable msg set to "" if this.hasPlayed then reassign msg to this.statusAsString() + $" - hand total: {this.handTotal}" end if return msg end function function toString() returns String return "the Dealer" end function end class class HumanPlayer inherits Player constructor(name as String, startingPoints as Int) reassign this.name to name reassign this.points to startingPoints reassign this.cards to new List<of Card>() end constructor function withStatus(status as Status) returns HumanPlayer let copyOfThis be copy(this) reassign copyOfThis.status to status return copyOfThis end function function withHandTotal(ht as Int) returns HumanPlayer let copyOfThis be copy(this) reassign copyOfThis.handTotal to ht return copyOfThis end function function withCards(c as List<of Card>) returns HumanPlayer let copyOfThis be copy(this) reassign copyOfThis.cards to c return copyOfThis end function procedure newHand() call this.newHandHelper() end procedure procedure nextAction(dealerFaceCard as Card) variable key set to "" call clearKeyBuffer() while key.equals("") reassign key to waitForKey() if key.equals("d") then call this.draw() elif key.equals("s") then call this.stand() else reassign key to "" end if end while end procedure function getMessage() returns String variable msg set to this.statusAsString() + $"- hand total: {this.handTotal}" if this.hasTurn then reassign msg to msg + " - press 'd' to draw, 's' to stand" end if return msg end function function toString() returns String return $"Player: {this.name}" end function end class enum Choice stand, draw enum Outcome undecided, lose, draw, win, winDouble enum Status active, standing, blackjack, bust enum Suit clubs, diamonds, hearts, spades function symbolForSuit(suit as Suit) returns String variable dc set to [Suit.clubs:"&clubs;", Suit.diamonds:"&diams;", Suit.hearts:"&hearts;", Suit.spades:"&spades;"] return dc[suit] end function function rankValue() returns Dictionary<of String, Int> return ["2":2, "3":3, "4":4, "5":5, "6":6, "7":7, "8":8, "9":9, "10":10, "J":10, "Q":10, "K":10, "A":11] end function function gridForRank(rank as String) returns List<of String> variable dc set to ["A":["royal"], "2":["b", "c"], "3":["a", "b", "c"], "4":["d", "e", "f", "g"], "5":["a", "d", "e", "f", "g"], "6":["d", "e", "f", "g", "h", "i"], "7":["d", "e", "f", "g", "h", "i", "l"], "8":["d", "e", "f", "g", "h", "i", "l", "m"], "9":["a", "d", "e", "f", "g", "n", "o", "p", "r"], "10":["d", "e", "f", "g", "n", "o", "p", "r", "s", "t"], "J":["royal"], "Q":["royal"], "K":["royal"]] return dc[rank] end function function colourForSuit(suit as Suit) returns String variable dc set to [Suit.clubs:"black", Suit.diamonds:"red", Suit.hearts:"red", Suit.spades:"black"] return dc[suit] end function constant styleSheet set to ":root { background-color: darkgreen; padding-left: 5px;}.game { padding: 5px;}.message, .details { color: white; font-family: Arial, Helvetica, sans-serif;}.hand { margin-top: 5px; height: 150px; padding-bottom: 10px; } .card { position: relative; float: left; background-color: white; width: 95px; height:140px; margin-right:10px; padding: 5px; border-radius: 5px; font-family: Helvetica, sans-serif; }.royal,.a,.b,.c,.d,.e,.f,.g,.h,.i,.j,.k,.l,.m,.n,.o,.p,.q,.r,.s,.t,.u,.v,.w,.x,.y,.z {position: absolute; text-align:center;}/* Standard spots */ .a,.b,.c,.d,.e,.f,.g,.h,.i,.l,.m,.n,.o,.p,.r,.s,.t {font-size: 30px;} /* columns */ .d,.n,.h,.p,.f {left: 18px } .a,.b,.c,.l,.m,.s,.t {left: 43px;} .e,.o,.i,.r,.g {left: 68px} /* rows */ .d,.b,.e {top: 0px} .suit {top: 20px;} .l {top: 28px;} .n,.o {top: 37px;} .h,.a,.i {top: 57px} .p,.r {top: 75px;} .m {top: 86px;} .t {top: 93px;} .f,.c,.g {top: 114px;}/* royals */ .royal { position: absolute; z-index: 1; width: 95px; height: 140px; line-height: 140px; font-size: 100px; }/* corner summary */ .u {font-size: 15px; width: 15px; text-align: center; left: 0px; top: 2px;} .v {font-size: 20px; width: 15px; text-align: center; left: 0px; top: 12px;}/* suit colors */ .red {color: red} .black {color: black}/* back */ .card.reversed { background-color: rgba(0, 0, 255, 0.607);}"
and immediately use file > auto save the code to your local file storage: because you will be making changes and want to ensure that your changes are saved.

When you run the program, the display tab will be shown in place of this worksheet, you can flip between them by clicking on the tab headings.

So, run the program now, either:

- using the mouse, by clicking on the run button at the top of the screen, or
- using the keyboard, by pressing Ctrl+r

and play exactly 10 rounds of Blackjack.

Make sure that you have grasped the following points:

- Most cards have a obvious numeric value. The Royal cards - Jack, Queen, King - each have the value 10. An Ace is special: it can be valued at 11, or at 1. An Ace valued at 11 is known as a 'soft Ace'. If a dealt card takes the hand total over 21 then a soft Ace is automatically devalued to 1.
- The aim is to get the value of your hand as close to 21 as you can - but if drawing a card causes the total to go over 21 then (unless you have a 'soft Ace') you will be 'BUST' and your turn is over.
- If the first two cards of any player total exactly 21 - which would require one Ace, and one Royal or 10 card - then you have 'BLACKJACK' - the best hand possible - so no further action is needed from you.
- When all hands have finished playing, the outcome is determined, points swapped as follows:
  - If a player is BUST then 1 point is passed from them to the dealer even the dealer is also BUST.
  - If a player has BLACKJACK then they gain 2 points from the dealer unless the dealer also has BLACKJACK, in which case it is a draw.
  - else, if the player is STANDING and the dealer has BLACKJACK the dealer gains one point from the player.
  - else, if the player is STANDING and their hand total is greater than the dealer's, the player gains one point from the dealer.
  - else, if the player is STANDING and their hand total is the same as the dealer's, it is a draw.
  - else, if the player's total is less than the dealer's, the dealer gains one point from the player.
- This program uses deck of multiple packs of cards: so there is a small chance that the same card may appear on screen more than once.

After playing 10 rounds, how many points did you, and the dealer, end up with?

If you have not already exited the program, click stop.

#### Notes

Step Completed Total hints used: /

# Step 2: start to explore the code

Watch the next video:

How many instructions are there in total within the Blackjack program (just find the largest instruction number)?

The initial keyword in an instruction defines the type of instruction. Find and list here at least five initial keywords not mentioned explicitly in the video:

#### Notes

Step Completed Total hints used: /

# Step 3: the different elements within instructions

Watch the next video:

List below the different colours that you can see being used within the code (they are all shown within the first 15 instructions):

What is the significance of the colour dark-blue, and black?

#### Notes

Step Completed Total hints used: /

# Step 4: comments

Watch the next video:

Scrolling through the code, find two comments, not including the one at the top showing the Elan version, and write down the instruction number immediately below each comment:

#### Notes

Step Completed Total hints used: /

# Step 5: identifiers

Watch the next video:

Find five identifiers used in the program - not including any that were mentioned in the video - and list them here:

#### Notes

Step Completed Total hints used: /

# Step 6: literals

Watch the next video:

Find an example of a literal number, and a literal string - not including any specifically mentioned in the video - and note their instruction numbers below:

#### Notes

Step Completed Total hints used: /

# Step 7: methods

Watch the next video:

Find five method names - not including any specifically mentioned in the video - and write them here:

#### Notes

Step Completed Total hints used: /

# Step 8: types

Which of the types mentioned in the video are defined within the standard Elan language (if necessary, watch the video again)?

#### Notes

Step Completed Total hints used: /

# Step 9: adding a new instruction

Watch the next video:

Your first task is to turn the program into a two-player game (not counting the dealer, played by the computer):

- Near the top of `main`, find this instruction:
  call game.addPlayer procedureName?(new HumanPlayer("Player A", 1000)arguments?)0
  game.addPlayer procedureName?(HumanPlayer("Player A", 1000)arguments?) # call procedure 0
  game.addPlayer procedureName?(new HumanPlayer("Player A", 1000)arguments?); // call procedure 0
  game.addPlayer procedureName?(New HumanPlayer("Player A", 1000)arguments?) ' call procedure 0
  game.addPlayer procedureName?(new HumanPlayer("Player A", 1000)arguments?); // call procedure 0
  and immediately below it insert a new `call` instruction.
- Into the two editable fields type in the same code that you see in the instruction immediately above it, except that instead of `"Player A"`, write `"Player B"`. Note that:
  - your text will initially be black, but it will be coloured once you leave the field
  - a drop-down list will offer you some 'auto-completion' options, which can save typing and errors. You can select an option with the mouse or with the cursor ↑↓ keys and Enter.
  - You might see a message appear on the right, but you can ignore it for now, unless it is coloured red (you will also then see the word invalid or error appear) in which case you should Backspace to correct the mistake.
- When you have completed the new instruction, run the program, and take responsibility for both Player A and Player B (or, if you are pairing with another person, control one each).

When does the dealer play, now ?

#### Notes

Step Completed Total hints used: /

# Step 10: modifying an existing instruction

- Go back to the instruction that creates Player A and above itinsert a `let` instruction and note that this features two editable fields.
- In the first field enter `name1` and in the second field type in the following code using the auto-completions to help `input("Enter name for first player") Going back to the first field, try deleting the contents and typing `Name1`

  What message do you see within the code editor?

  And what do you observe in the 'status panel' - at the top of the screen, just to the right of the code editor?

  Then revert the field back to `name2`.`
`
- Select the instruction below this - in other words the one that you added previously - and Tab to the second field. Edit the contents, replacing the literal string `"Player A"` with `name2` (no quotation marks because this is an identifier that holds a string, not a literal string).
- Run the program. When asked, type in your own first name, finishing with the Enter key.

  Has the name you entered made a difference?

  There is an unwanted 'side effect' on the screen - what is it?

- To fix the unwanted side effect, insert the following new instruction immediatelyafter the second player is created and added to the game: `call clearPrintedText()`
- Now change the program so that it asks the user to enter a name for the second player, this time using the identifier `name2`.
- Run the program again, and confirm that you can now name both players.
`

`

What would happen if you define the second identifier as name2, but in the next line you were to write name1? (If you need to check, run the program)

And what if the the second identifier was still name2 but you used name3 in the following instruction? This time, can you even run the program to try it?

`

#### Notes

Step Completed Total hints used: /

# Congratulations! You have completed this worksheet

You have learned:

- How to load, run, and stop a program
- How to recognise the different kinds of instructions that make up a program, including compound instructions, which contain other instructions.
- How to navigate around the program, selecting different instructions in order to draw attention to them and as a prelude to modifying them.
- How to insert new instructions, delete instructions, and to undo changes when they didn't do what you wanted.

In the next worksheet - Blackjack 2 - you'll start to do some real programming, by defining and implementing the logic for a fully-automated Blackjack player - and then in the Blackjack 3 worksheet, pitting different automated players against each other for thousands of games, and using the outcome to refine the strategies.

In the meantime, if you have time, we recommend that you watch the following additional videos - that offer further techniques for navigating and editing instructions. Practice the techniques shown in each video, either while it is running, or immediately afterwards.

All the techniques for navigating and modifying instructions may be looked up in the Help tab. For example: show in Help