Using a medieval workshop game to teach programming

The Workshop Method

How it works

In stead of starting the journey of your students by familiarizing them with the syntax and quirks of the programming language of your choice, teach them to solve problems in the way you would solve them in code. With very small, discrete, steps that are executed sequentially to get to a result. In order to do this, we introduce the metaphor of the Medieval Workshop. You give the students a setting, and a bunch of rules. Afterwards, you challenge them to draw up a design of a logical flow that solves the problem statement. Give them an example of how you may visualize a flow like this.

Once the students have gotten a grasp of designing workshop flows, you introduce them to the syntax. Each worker will then be mapped to one or two lines of code. This way, we can separate solving the problem at hand, and figuring out how to write it in code. “Solve first, then translate to code”

The model bellow is still in quite a crude form. It is directed more towards young adults that understand they are trying to learn how to code, and that this mental model is an intermediary step in that process.

The setting

The setting is as follows:

Imagine we are in medieval times, you are the owner of a workshop that provides services to the king. The people working in your shop are lowly peasants, and are very limited in what they can do. The king has given you an assignment to complete. If successful, you will become even richer. If you fail, you will be beheaded.

Of course, there are some limitations to what our workforce is able to do.

The Basic rules

People in your workforce:

  • Are not allowed to speak to each other as you do not trust them to not entice rebellion. They are only allowed to communicate by passing each other notes or boxes containing items.
  • Are unlettered, they can not understand the meaning of written words
  • Are able to count, and write down numbers
  • Are able to see if things that are written on a note are identical, by holding two notes over a light source. They are not able to recognise similar shapes when these shapes are surrounded by other shapes.
  • Are unable to remember things, so they have to write down all information that is needed.

Your workshop:

  • Your workers sit in your workshop, and each can perform a very specific and simple task. Then they pass the thing they are working on to the next person.
  • To keep the floor organized, you can group people together in a room.
  • You can pass boxes or notes from the main room into this room through the ‘IN’ door, and the other way around through the ‘OUT’ door
  • You can have as many items going in to a room through the IN-door as you want
  • Only one item is allowed to leave a room through the OUT-door. You are allowed to put multiple things together in a big box (or boxes in boxes)
  • Each room is equipped with a blackboard that can be used to share information within the room (but workers can only see the whiteboard in the same room). Each room has an educated ‘master of the blackboard’ that is able to write on the blackboard, but can not perform any other tasks.
  • Workers can only read and write on the blackboard in their own room

Inspectors of the king

  • The king is concerned about the quality of the tasks performed at your workshop, and will send inspectors over after you have told him you are ready to process his requests
  • You may draw these outside the door with inputs for your workshop, in order to verify that your solution works well
  • If you find an improvement to your flow because of the test runs with the inspectors input, you may update your floor. The king will be pleased to know that you are being innovative and efficient.

Some extra comments

You may put everyone in the main room if you want, and you may put as much on the main blackboard as you want. The blackboard is intended as a way to not have to draw too much note passing within the same room. Your workshop will look more pleasing to the inspector of the king if it is nicely organized into rooms.

Given this setting and the rules that apply to it, try and figure out a way to make your workshop comply with the orders the king has given you.

An example task, and a possible solution

I will provide an example of an assignment, and a possible workshop layout. Then I will show the code that results from this design.

Assignment

The king wants to know how many times his favorite letter appears in words. He will send you papers with words, and you are asked to tell him how many times his favorite letter appears.

As an added bonus, the workers in your workshop have learned how to use scissors to cut up notes into smaller notes

At the end of the workshop, there is one worker that is able to copy text or numbers from a paper onto a form, intended to be sent to the king

As some guidance when starting this exercise, take a look at this image of some possible input entering your shop:

An image depicting the door, and the input to the workshop

Possible solution

Workshop flow
Resulting Code
After the students have had experience with the designing their workshops, you assist them in translating their design into code. Make sure the first version of the code you write matches the workshop flow design quite precisely, even if it could be a lot more elegant. In later stages of the teaching, you can show how you can write this program in a more concise way.

Below is an example of the code you would end up writing together from the assignment in the example:

fun main() {
    val wordToCountIn = "Word"
    val kingFavoriteLetter = 'o'
    //Send the word to the counting team
    val countedLetters = count(wordToCountIn, kingFavoriteLetter)
    //Send the response to the king
    println("The word '$wordToCountIn' contains the letter '$kingFavoriteLetter' a whopping $countedLetters times")
}

fun count(word: String, favoriteLetter: Char): Int {
    // Take a piece of paper to keep count on
    var occurrenceCounter = 0
    // Cut the word into pieces
    val lettersInWordSplit: CharArray = word.toCharArray()
    // "for each letter"
    for (letter in lettersInWordSplit) {
        // draw a mark for each occurrence
        occurrenceCounter = if (letter == favoriteLetter) occurrenceCounter + 1 else occurrenceCounter 
    }
    // Bring the paper back to the main team
    return occurenceCounter 
}

Some additional assignment ideas you can work out

For some of these, the workers will have to get special skills. These special skills are not present in the main model, as it would overly complicate things. Feel free to add abilities for the worker when the resulting code needs it.

Given a word , answer with all the vowels contained in this word (duplicates in answer are okay)

Given a word , answer with all the consonants contained in this word (duplicates in answer are okay)

Given a word , the answer should be a count of how many time each vowel is in the word. ex. “BananaPeel” -> “a3|e2”

Testrunning the Workshop approach on my SO

I have tried to teach my fiancee to write code in the past. She tried solving the “king’s favorite letter counter” example without looking at my
model solution. All I showed her was the door, and the input her workshop would get.

She came up with a different way of fulfilling the assignment. We then introduced the “King’s Inspector”, who would see if the workshop is able to complete it’s work with any word the king could throw at them, she even found a possible optimisation in her program.

I took the liberty of transforming her solution into a working Kotlin program, using most the names and concepts she used in her design.

fun main() {
    val kingWord = "banana"
    val kingLetter = 'a'
    val selectedLetters = splitterRoom(kingWord, kingLetter)
    // the counter
    val occurences = selectedLetters.size
    // The scribe
    println("The king's word '$kingWord' contains his favorite letter '$kingLetter' a whopping '$occurences' times!")
}

fun splitterRoom(kingWord: String, kingLetter: Char): List<Char> {
    // Prepare an empty box
    var selectedLettersBox = ArrayList<Char>()
    // The divider
    val kingWordLetters = kingWord.toCharArray()
    //The second divider, aka the box filler
    for(letter in kingWordLetters) {
        if(letter == kingLetter) {
            selectedLettersBox.add(letter)
        }
    }
    // Return the "selected letters"-box
    return selectedLettersBox
}