Goodbye, Hello World?

Alfred Thompson questioned on his blog today whether the customary first programming exercise, Hello World, should be replaced with something that’s more flexible and calls on students to engage in a short, non-trivial first act as a programmer. I admit, I’ve used Hello World myself with students, but usually not as a first activity. Instead, I use Hello World to help students who have had some hours or days of programming instruction understand that they now know quite a bit about how programming languages express an intention. I ask students to visit the ACM Hello World web page and compare and contrast that simple program in different languages. How are code blocks started and ended? How is output generated? How is an infinite loop expressed? How are strings represented?

But to address the primary question Alfred poses, should we use a different first exercise, I’d say yes. I’ve used a constructive series of exercises in JavaScript that builds on the idea of rolling dice and a number guessing game for several years with great success and enthusiasm from students.

The first example I offer introduces an activity with which students are already familiar: rolling a single die. Students understand that we’re trying to generate a number from 1 to 6 (inclusive) and to let the user know the generated number.

<script>
  var num = Math.floor((Math.random() * 6)) + 1;
  alert("You rolled a " + num);
</script>

This example allows us to discuss how a function is called (Math.random and Math.floor), the use of the asterisk to denote multiplication, what the outputs of those functions are, and the order of operations, grounded in their prior knowledge about algebra. It also introduces the use of a scalar variable, output, and concatenation; all of that in just two lines of code.

However, the example is necessarily constrained. Users must reload a web page to see a different number generated and there’s no input from the user. Adding just a few lines of code, we address those issues in the second exercise.

<script>
  var num = Math.floor((Math.random() * 6)) + 1;
  var guess = prompt("Guess a number from 1 to 6");
  guess = parseInt(guess);
  if (guess == num) {
    alert("You win!");
  } else {
    alert("Sorry!");
  }
</script>

This exercise also allows me to introduce conditionals, the use of == as the equality predicate, and basic data types via the  user string input needing to be converted to an integer. Still, however, the page must be reloaded for each guess, which causes a new random number to be generated, thus making it a game you can only win if your first guess happens to be correct. This allows us to talk about the life cycle of the interpreted code and motivates the need for loops.

<script>
  var num = Math.floor((Math.random() * 6)) + 1;
  var guess = prompt("Guess a number from 1 to 6");
  guess = parseInt(guess);
  while (guess != num) {
    alert("Sorry! Try again");
    guess = prompt("Guess another number from 1 to 6");
    guess = parseInt(guess);
  }
  alert("You win!");
</script>

Each of these exercises builds on the previous examples by adding just one or two new ideas and lines of code, so that students can see the logical development of the code and so that each new idea is motivated by a desire to improve game play, for example, by subtly introducing != as a “not equals” predicate. Students are free to experiment with the range of numbers and the details of the feedback provided to users. Once we’ve got a reasonably playable game, we can refactor the upper and lower limits of the game to variables.

<script>
  var min = 1;
  var max = 6;
  var num = Math.floor((Math.random() * max)) + min;
  var guess = prompt("Guess a number from " + min + " to " + max);
  guess = parseInt(guess);
  while (guess != num) {
    alert("Sorry! Try again");
    guess = prompt("Guess another number from " + min + " to " + max);
    guess = parseInt(guess);
  }
  alert("You win!");
</script>

This refactoring is motivated by students’ desire to quickly change the game’s parameters so that they each have a slightly different version of the game (guess a number between 1 and 10,000,000 isn’t uncommon!).

This allows us to discuss whether the same code would work, if the range were to include negative numbers (-10…10, for example), or fractional numbers (-0.5…0.5, for example; hint: Math.floor might cause problems), or if we wanted to generate richer feedback to users.

In short, I lead students to these examples by providing the motivating context and introducing the new language features just in time. Students get to interact with a fairly interesting first game and to push at the edges of what can be achieved from that simple code base.