Articles Archive
Articles Search
Director Wiki
 

Number Sorting

February 13, 2000
by Pat McClellan

I'm doing mathematics courseware using Director. I randomized 4 numbers and I want the courseware to show the students how to put the numbers in order (sort) by comparing the numbers digit by digit. For example:

list = [5561, 4452, 7952, 4541]

First, it will compare the first digits by blinking the digit: 5, 4, 7, 4. If the first digit is the same, then it will compare the second digit for the same numbers 4, 5. The first number (4452) is smaller, so it will move the location of the number to the first step of the stair. The process will continue to the number left (5561, 7952, 4541) until all the numbers have been put in the stair.

Asniza

Asniza,

This is a very complex request -- more than I can cover in this article. But I can help you with a couple of the basic tasks involved. You'll have to take that knowledge and extend it to complete your program.

Let's start by separating our tasks. One task is that we need to do some simple math comparisons. The other task is having specific characters displayed in a text member flash or change colors. We'll get the text flashing out of the way first.

To get a single digit in the number to blink, we'll change the color of that single char (character) and toggle it back and forth. You're going to need to use Text members (rather than fields) because text members allow individual character formatting, while fields do not. We'll be adjusting the "color" of the char, and we'll specify the color in rgb format. For example, black = rgb(0,0,0); white = rgb(255,255,255); red = rgb(255,0,0). We can also add a highlight feature which doesn't blink, but just changes the color of a specified char.

A sample movie is available for download in Mac or PC format. This is a D7 movie. All movies from this article are contained in this single download.

This blinkChar behavior works as follows:

  1. We send that sprite a command to blink, which sets a flag property to #blink.
  2. The exitFrame handler watches that flag and when it sees the flag change to #blink, it starts counting frames. When enough frames have elapsed, it sends out a command to toggleChar.
  3. The toggleChar handler checks to see if the char is the original color. If so, it changes it to the designated blink color; otherwise, it assumes that it must be the blink color and changes it back to the original color.
  4. The toggleChar handler resets the frame counter so the next cycle can begin. It also checks to see if all the blink cycles have been completed. If so, it changes the pFlag back to #off.

The code is fairly long, so you can download the sample movie for the code details.

The highlight function is much simpler, since it doesn't need to count frames or cycles. It simply changes the color of the specified char to a color which was chosen during authoring.

Now let's address the math sorting. Of course, the easiest way to sort the numbers is to put them into a list and use the sort command. The problem with that is that you're trying to emulate the process a person would go through, so we'll try to do it another way. We have two alternatives:

If we use the first approach, in collaboration with the blinkChar behavior from our first example, we can get something that appears to meet your criteria. Here's the handler (run from a movie script) that will do the sorting:

on findMinChar spriteList, whichChar
  minSpriteList = []
  minDigit = 10
  
  repeat with thisSprite in spriteList
  
    thisDigit = value(sprite(thisSprite).member.char[whichChar])
    if not integerP(thisDigit) then
      alert "Equality or non-integer value."
      exit
    end if
    
    if thisDigit = minDigit then
      add minSpriteList, thisSprite
    else if thisDigit < minDigit then
      minSpriteList = [thisSprite]
      minDigit = thisDigit
    end if
    
  end repeat
  
  if minSpriteList.count > 1 then
  
    repeat with whichSprite in minSpriteList
      sendSprite(whichSprite, #lightChar, whichChar)
    end repeat 
    
    whichChar = whichChar + 1
    findMinChar minSpriteList, whichChar
  else
    sendSprite(spriteList[1], #blinkChar, whichChar)
  end if
  
end

This handler simply moves through the list of sprites, comparing the numerical value of the first digits. When it encounters a lower digit than it previously has seen, it puts that sprite's number in the minSpriteList. If it finds an equally low value, it adds that spriteNum to the minSpriteList. When it finishes comparing the first char of all the numbers, then it checks to see if there is more than one spriteNum in the minSpriteList. If not, then the single spriteNum is the lowest, but if there are more than 1 sprite in the minSpriteList, then there is a "tie" on that first char. So the handler calls itself and supplies itself with the minSpriteList and the next char number. (This is called regression and you have to be very careful when writing things like this into your code. If you do it wrong, you can set up an infinite loop that could crash your system.)

We'll call this handler from a script on a button, supplying it with a list of sprites to compare and also specifying which char (from the left) to start with. So if our text sprites (numbers) are in channels 5, 6, 7 and 8, and we want to start with the char 1, then the button script will look like this:

on mouseUp me
        findMinChar [5, 6, 7, 8], 1
end mouseUp

If you click on the "findMinChar" button, it appears to work fine. The problem arises if any of the numbers don't have the same number of digits. For example, if our number are 5561, 4452, 7952, and 978, it's easy for us to see that 978 is the lowest number. However, the findMinChar handler will compare the first char of each of these number: 5, 4, 7 and 9. It will incorrectly assess that the lowest number is 4452 because 4 is less than 9. This is all because text strings (at least in English) run from left to right, while numberical values work right to left from the implied decimal point. So this handler will only work when there are the same number of digits to the left of the (implied) decimal point. (Note that since a decimal point is a char, if you actually used a decimal in your text member, the findMinChar handler would eventually try to evaluate the decimal and would return an error.) I'm not saying you can't use this script -- only that you should be aware of its limitations.

So that you can see for yourself, the values in the demo above are editable. Try entering this values: 5561,4452,7952, and 978. The findMinChar will return the wrong value. Now try clicking the findMinNum button. It will return the correct value. Let's look at findMinNum -- a more mathematical approach.

Instead of tracing through the code line-by-line, I'll describe the process step-by-step. I recommend you download the code and follow along in the Lingo script for "findMinNum" to see what's happening.

  1. Go through the list of sprites and extract the numbers and put them into a list -- we'll call it the numList.
  2. Find the minimum value in numList and count how many digits are in that number. Save that value as minDigits.
  3. Go through the numList and delete any numbers that have more digits than minDigits. Also delete the corresponding spriteNum from the spriteList. That will leave you with all the numbers which have the same number of digits.
  4. It then calls a separate handler called compareMinNum which goes through numList and compares the values of the leftmost digit. The spriteNum corresponding to the lowest value gets added to a new list called minSpriteList.
  5. It puts the minimum value (or muliple values if there is a tie) into a list called minNumList. The corresponding spriteNums are put into a list called minSpriteList.
  6. If there is more than one value in the minSpriteList, then it knows that it needs to do more sorting, so it calls itself (compareMinNum) to sort through the next digits to the right for the sprites in the minSpriteList. It will continue looping until it runs out of digits or until it only one sprite is left in the minSpriteList.

Note that I used the same commands as before to make the chars blink.

Whew! That was a tough one. But we've covered the toughest parts. Now, you'll need to create your movie and figure out when and where to call these routines -- and what to do when you get a result. I think we've given you a pretty good start! Good luck with your program.

Patrick McClellan is Director Online's co-founder. Pat is Vice President, Managing Director for Jack Morton Worldwide, a global experiential marketing company. He is responsible for the San Francisco office, which helps major technology clients to develop marketing communications programs to reach enterprise and consumer audiences.

Copyright 1997-2024, Director Online. Article content copyright by respective authors.