January 2004 Archives

Remember last time when I said that I'd show you how to use the IntegerSet datatype in an application? Well.. today is the day where I make good on my word. We're going to solve the 8 Queens Problem pretty easily with IntegerSets.

The 8 Queens Problem is simple to define - try to place 8 queens on a chess board in such a way that no queen is threatening another. This is a classic problem that is usually assigned for homework to Computer Science majors. It's a wonderful thought experiment. College is funny like that.. they teach you how to think. In some cases, that's a good thing.. especially in programming when you get a chance to flex your problem solving muslces.

Anyway, as a freshman in college (almost 5 years ago now), I was required to write a solution for it. Back then, I wrote my solution in C++, but I thought it would be another good ActionScript 2.0 example, as well as another good recursion demonstration... so I decided to show an ActionScript 2 implementation of this classic problem.

Before you download my code and just follow along, I highly encourage you to try the problem for yourself. You can download the code here.

Read on...

Integer Sets in ActionScript

| No Comments

It's been awhile since I talked about data types.... thus, I thought I'd demonstrate the IntegerSet data type by providing an ActionScript 2.0 implementation.

An IntegerSet is simply a set of integers, with a relatively simple API. You can insert an element, remove an element, determine if an element is in the set, get the min element, get the max element, clear all elements from the set, union a set with another set, intersect another set with another set, get the compliment of the set, and finally output the set as a string. Some example usage:

// 01/28/04 - moved to weblog package
import com.darronschall.weblog.IntegerSet;

var set1:IntegerSet = new IntegerSet();
set1.insert(7);
set1.insert(11);
set1.del(7);
trace(set1.member(11)); // true
trace(set1.member(7)); // false

// add a large integer
set1.insert(87162386612);
trace(set1.member(87162386612)); // true
set1.del(87162386612);
trace(set1.member(87162386612)); // false

set1.compliment();
trace(set1.member(11)); // false
trace(set1.member(7)); // true

trace(set1.max()); // 10;
trace(set1.min()); // 0;

// toString is overrided, so this produces useful data
trace(set1); 

set1.del(1);
var set2:IntegerSet = new IntegerSet();
set2.insert(1);
set1.union(set2);
trace(set1.member(1)); // true

var set3:IntegerSet = new IntegerSet();
trace(set3.min() == IntegerSet.EMPTYSET); // true
set3.insert(6);
set1.intersection(set3);
trace(set1); // 6 is the only element

set1.clear();
trace(set1.min() == IntegerSet.EMPTYSET); // true
trace(set1.max() == IntegerSet.EMPTYSET); // true

If you run into any errors with this class, please let me know. I probably didn't test this as thoroughly as I should. At some point I'll be looking at using as2unit to do extensive testing. I currently know of only a minor "technical" issue where set.member(IntegerSet.EMPTYSET) will always fail, even though, "technically" the emptyset is always a member of any set by definition... I don't think it's quite that big of a deal since the statement is always true and you wouldn't need to calculate it. ;-).

The implemention for this is pretty slick. It uses an array of integers (treated more or less as an array of bits), and assigns a single bit for each element in the set. If the bit is 1 then the integer represented by the bit's location is in the set. Otherwise, the bit is 0 and the integer represented by the location is not in the set. Because everything is done with bitwise operators, the majority of the methods are lightning fast, even when dealing with very large integers. I was impressed overall by the performance.

Behind the scenes, I'm taking advantage of the fact that the Flash player will automatically resize an Array for you.. Thus, there doesn't really seem to be a limit of the max element that you can store in a set. However, if you use really large integers, some of the methods will take a long time because they're looping through all of the bits. The methods min, max, union, intersection, compliment and toString are the ones affected. Beware if you plan on using large integers with those methods.

Anyway, enough talk... go download the code. It should be pretty well commented. Let me know if you need clarification of anything - I'll be happy to provide explanations.

Next time I'll show you an example of how to use this class in an application to easily solve a problem. Stay tuned!

What's your Geek Code?

| No Comments

I decided to finally take action and create my own geek code. Yes, the "code" has been around for awhile (since 1996!) but I stumbled across it last summer and just never took the time to create mine.. Yes, some of the parts are a bit dated (for instance, the OS/2 portion), but it it was good for a few minutes of entertainment.

So.. here it is, my official geek code (v3.12):

GCS/MU d- s+: a22>? C++(+++) UL++ P--- L++ !E W+++$ N++ o++++ K-? w> O- M>+ V- PS+@ ... [no carrier].

I lost consciousness towards the end when I got tired of creating my code. The no carrier signifies a lost signal (in this case, lack of interest). I have to say that in 1996 this would've been more amusing, but in 2004 it's time to email Robert Hayden and ask him to finally create an updated version. I want a portion dedicated to reality tv shows and how they're ruining good television.

Some notes on overriding "toString"

| 4 Comments

It's pretty common to override the "toString" method in your classes so that they'll return something useful when used as a string. It doesn't always work though... A quick working example:

class Example1 {
	private var data:Number;
	public function Example1(data:Number) {
		this.data = data
	}
	
	public function toString():String {
		return "Example 1 [" + data + "]";
	}
	
}

This is a pretty simple example just to illustrate a point. The above class would be used like this:

var t:Example1 = new Example1(17);
trace(t);  // output: Example 1 [17]

Hopefully you can see that this technique can be pretty useful, especially for debugging purposes. However, there's an nteresting quirk that I've run in to that I wanted to share with everyone.

When you create a class that extends MovieClip, things don't work as expected. Consider the following:

class Example2 extends MovieClip {
	public function Example2() {
		// do something here
	}
	
	public function toString():String {
		return "Example 2";
	}
}

In theory we can associate this class with a MovieClip (via AS2 Class in the linkage properties in the library), give the MovieClip an instance name, and trace the instance name to see "Example 2" in the output window. Does this work? Nope, not at all. We just see the path of the MovieClip in the output. However, if you explicitly call the toString method, we see the expected output.

So why does tracing an instance name of a MovieClip not implicitly call the toString method? Whenever an Object is used as a string, toString should be called automatically. This isn't just a "Flash-thing," this is pretty standard programming practice.

At first I thought that maybe the original toString function couldn't be overwritten. That doesn't seem to be the case:

// instance of "test_mc" on the stage
// let's see what we have originally
trace(typeof(test_mc.toString)); // function
trace(test_mc);				// _level0.test_mc
trace(test_mc.toString());	    // [object Object]

// overwrite toString
test_mc.toString = function() {
	return "test_mc.toString() called";
}

// did it work?
trace(test_mc);			// _level0.test_mc
trace(test_mc.toString());  // test_mc.toString() called

From the results of the trace statements (the last line, specifically), it's clear that overwriting toString worked just fine for a MovieClip. Also, from Example2 above, when you trace(instanceName.toString()) you see that toString was overridden as well. So, if we can override toString.. why doesn't it work?

The conclusion this leads me to is that MovieClips are treated differently by the player virtual machine when they're used as strings. Instead of implicitly calling the "toString" method, the full path to the MovieClip is returned ignoring the "toString" method altogether..

Now.. the question of the night... why? Honestly, I'm not sure myself. I'm wondering if it has to do with eval at all. Anyone have any insight/ideas?

Getters and setters are evil

| 2 Comments

Just came across this link today on Java World. The article is already 4 months old, but the points are still valid.

Basically, one of the four fundamental principles of OOP is data abstraction. As you know, data abstraction is the process of not exposing any of the "dirty details" of how the class works to those using the class (focusing on the "what" not the "how"). Users of the class have access to the public methods, and as long as those methods stay the same the internal implementation can be changed at will without effecting the end-user.

By having getters/setters for every private variable, you're exposing details about how the class is implemented. When people use getters/setters for your private variables, it becomes hard for you, the class creator, to change your implementation without breaking the public interface.

However, there are plenty of times where getters/setters (either via methods, or via properties) are necessary. These times might include things like checking on the status of an object, settings flags/parameters, etc... but maybe we have been too liberal with getters/setters by over-using them in situations when they're not entirely necessary?

Definitely a worthwhile read.

A hidden gem... or two

| 12 Comments | 2 TrackBacks

If you've been using Flash for awhile, you probably already know what an "enterFrame beacon" is. If not, Flash MX 2004 provides one for you... you just have to find it!

How often have you created an empty MovieClip on the stage somewhere just to define an onEnterFrame for it? The onEnterFrame function is only available to MovieClips, but a lot of time there is a need to define an onEnterFrame for an generic object, so a MovieClip is created for that sole purpose. Instead of creating multiple MovieClip's and wasting some memory, worrying about depth management, and trying to shuffle things around, you should consider taking advantage on the OnEnterFrameBeacon class.

To allow any object to define an onEnterFrame that gets called everytime an enterFrame event occurs, check out the following code:

// in the transitions package?  I think I would've put this in a util package...
import mx.transitions.OnEnterFrameBeacon;

// start the beacon, so we can listen for onEnterFrame 
OnEnterFrameBeacon.init();

var o:Object = new Object();
o.onEnterFrame = function() {
	trace("onEnterFrame outside of a MovieClip.. woohoo!");
}
// add the object as a MovieClip listener
MovieClip.addListener(o);
// you can also remove the listener as needed
// MovieClip.removeListener(o);

One thing to watch out for is that depth 9876 will be taken if you use the OnEnterFrameBeacon class. You can simply modify the class file and specify a different depth, if you need to.

This could also be done with setInterval and passing an interval time that mimics the frame rate. However, the interval might eventually get out of synch, depending on how much the player virtual machine needs to adjust the frame rate.

Note that instead of using AsBroadcaster to broadcast the "onEnterFrame" message, internally the OnEnterFrameBeacon uses "mx.transitions.BroadcasterMX" which mimics AsBroadcaster in functionality.

The interface for BroadcasterMX is the same as you're probably already familiar with...

import mx.transitions.BroadcasterMX;

obj = new Object();
// initialize the obj that will be broadcasting events
BroadcasterMX.initialize(obj); 
// create a listener to respond to broadcasted events
listenObj = new Object();
listenObj.onMessage = function (param1, param2) {
	trace("got onMessage " + arguments);
}
obj.addListener(listenObj);
obj.broadcastMessage("onMessage", "test param1", "test param2");
// you can also remove the listener:
// obj.removeListener(listenObj);

.. and there you have it - two hidden gems that come already written for you in Flash MX 2004. I know a lot of people have been using their own solutions for awhile, but I wanted to point out the classes that Macromedia has already provided. Hopefully this makes someone's life a little easier. :-)

MovieClip._location property

| 4 Comments | 1 TrackBack

It has been said that necessity is the mother of invention. It has been argued that annoyance, not necessity, fuels invention.

I'd like to start the year off with a little script brought to life by annoyance. To set the position of a MovieClip, you need two lines of code: one to set the _x position, and another to set the _y position. Many times I found myself wishing for a way to set a MovieClip's coordinates in one line. Enter the "_location" property. Use the code below to add the _location property to all of your MovieClips.

// pt is an object with an x and a y property
function $setLocation(pt) {
	this._x = pt.x;
	this._y = pt.y;
}
function $getLocation() {
	return {x:this._x, y:this._y};
}
MovieClip.prototype.addProperty("_location", $getLocation, $setLocation);

// constants for ASSetPropFlags
var HIDDEN:Number = 1;
var PROTECT_DELETE:Number = 2;
var PROTECT_OVERWRITE:Number = 4;

ASSetPropFlags(MovieClip.prototype,"_location", 
			HIDDEN | PROTECT_DELETE | PROTECT_OVERWRITE, 0);

Usage is simple - you can just write..

my_mc._location = {x:20, y:40};

.. and the MovieClip will adjust it's x and y positions.

Happy New Year Everyone!

Flex.org - The Directory for Flex

Archives