My First Flex App: Tic-Tac-Toe

So, at the insistence of my co-worker Mario I’ve been reading up a bit on Flex. I can’t say it’s been love at first site, but I’m giving it a solid chance and I’ll post my thoughts on the tech after I’ve solidified on the matter.

Anywho, here’s my first app. It’s a simple Tic-Tac-Toe game, which took longer, and is uglier than it should be, since I haven’t quite figured out what I’m doing yet. Not that that’s ever stopped me from posting before.

Amazing eh?

The MXML File:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
	xmlns:mx         = "http://www.adobe.com/2006/mxml"
	layout           = "absolute"
	width            = "220"
	height           = "190"
	creationComplete = "reset(this)"
>
	<mx:Script source = "TicTacToe.as" />
</mx:Application>

My Tile Class

package components {
	import flash.events.MouseEvent;
	import mx.controls.Button;

	public class Tile extends Button {
		public function Tile(x:int,y:int,click:Function) {
			super();
			this.x     = x;
			this.y     = y;
			this.label = "";
			this.addEventListener(MouseEvent.CLICK,click);
		}
		public function belongsTo(player:String):Boolean {
			return this.label == player;
		}
		public function isEmpty():Boolean {
			return belongsTo("");
		}
	}
}

And finally, my actual game code:

import components.*;

import mx.controls.Alert;

private const START_X:int     = 90;
private const START_Y:int     = 80;
private const TILE_SIZE:int   = 50;
private const TILE_BUFFER:int = 5;
private const BOARD_SIZE:int  = 3;

private const PLAYER_X:String = "X";
private const PLAYER_O:String = "O";

private var turn:String;
private var container:DisplayObjectContainer;
private var board:Array;

private function isValidMove(tile:Tile):Boolean {
	return(tile.label == ""); 
}

private function takeTurn(tile:Tile):void {
	tile.label = turn;
	if(turn == PLAYER_X) {
		turn = PLAYER_O;
	} else {
		turn = PLAYER_X;
	}
}

private function toggle(e:MouseEvent):void {
	var tile:Tile = Tile(e.target);

	if(!isValidMove(tile)) {
		return;
	}

	takeTurn(tile);

	if(playerWon(PLAYER_X)) {
		endGame("Yay, " + PLAYER_X + "  won!");
	}
	if(playerWon(PLAYER_O)) {
		endGame("Yay, " + PLAYER_O + "  won!");
	}
	if(!movesAreAvailable()) {
		endGame("Everybody loses. Losers.");
	}
}

private function endGame(message:String):void {
	Alert.show(message);
	reset(container);	
}

private function movesAreAvailable():Boolean {
	var i:int, j:int;
	for(i = 0; i < BOARD_SIZE; i++) {
		for(j = 0; j < BOARD_SIZE; j++) {
			if(board[i][j].isEmpty()) {
				return true;
			}
		}
	}
	return false;
}

private function playerWon(player:String):Boolean {
	var i:int, j:int;
	var status:Boolean;

	for(i = 0; i < BOARD_SIZE; i++) {
		status = true;
		for(j = 0; j < BOARD_SIZE; j++) {
			status = status && board[i][j].belongsTo(player);
		}
		if(status) {
			return status;
		}
	}

	for(i = 0; i < BOARD_SIZE; i++) {
		status = true;
		for(j = 0; j < BOARD_SIZE; j++) {
			status = status && board[j][i].belongsTo(player);
		}
		if(status) {
			return status;
		}
	}

	status = true;
	for(i = 0; i < BOARD_SIZE; i++) {
		status = status && board[i][i].belongsTo(player);
	}
	if(status) {
		return status;
	}

	status = true;
	for(i = 0; i < BOARD_SIZE; i++) {
		status = status && board[i][BOARD_SIZE - (i + 1)].belongsTo(player);
	}
	return status;
}

private function reset(applicationContainer:DisplayObjectContainer):void {
	var tile:Tile;

	board     = new Array(BOARD_SIZE);
	container = applicationContainer;
	turn      = PLAYER_X;

	while(container.numChildren) {
		container.removeChildAt(0);
	}

	for(var i:int = 0; i < BOARD_SIZE; i++) {
		board[i] = new Array(BOARD_SIZE);
		for(var j:int = 0; j < BOARD_SIZE; j++) {
			board[i][j] = new Tile(
				START_X + j * (TILE_SIZE + TILE_BUFFER),
				START_Y + i * (TILE_SIZE + TILE_BUFFER),
				toggle
			);
			container.addChild(board[i][j]);
		}
	}
}

You can also just download it

On a side note, big thanks to Alex Gorbatchev for my new syntax highlighter plugin and a round of applause for Mark Walters for the AS3 extension to said excellent plugin.

Project Euler: Problem 19 in Ruby

Although it felt dirty, I used Ruby’s baked-in date class. I’d written some day-of-week code when I first started coding, before I knew better, and it’s annoying. Besides, this was my last problem to do before level 1. That’s right…

LEVEL 1!!!!

Bravo, thejoezack! Now that you have solved 25 problems you have achieved what 79.52% of members have failed to do and have advanced to level 1. Good luck as you continue.”

I’m proud. I found a few of the problems to be really hard and it feels really good to have finally hit a milestone. I’ve actually had a much easier time with the problems as I’ve gone on, as I’ve learned a lot about solving these problems and perhaps even problem solving in general. Kudos and thanks, Project Euler!

Oh yeah…and here’s my solution:

Problem #19

How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?

require 'date'

start = Date.new 1901, 1, 1
total = 0

(100 * 12 - 1).times do |i|
  total += 1 if (start >> i).wday == 0
end

puts total

Project Euler: Problem 22 in Ruby

Cake. I really hate hard-coding that ascii value in there, but it made it easier for me to get it working in different versions of Ruby.

Problem #22

What is the total of all the name scores in the file?

def convert word
  total = 0
  word.each_byte do |i|
    total += i - 64
  end
  total
end

file  = File.new("files/names.txt", "r")
names = eval("[" + file.gets + "]").sort
total = 0

file.close

names.each_with_index do |name, i|
  total += convert(name) * (i + 1)
end

puts total

Project Euler: Problem 21 in Ruby

Pretty standard Project Euler solution. You only need to check up to the square of each number, and you can cache each calculation as you go along.

Problem 21

Let d(n) be defined as the sum of proper divisors of n (numbers less than n which divide evenly into n).
If d(a) = b and d(b) = a, where a ≠ b, then a and b are an amicable pair and each of a and b are called amicable numbers.

Evaluate the sum of all the amicable numbers under 10000.

def d(n)
  total = 1
  (2..Math.sqrt(n)).each do |i|
    if n % i == 0
      total += n / i + i
    end
  end
  total
end

def amicable?(a, repo)
  repo[a] = b = d(a)
  a != b and a == repo[b]
end

repo  = {}
total = 0

10_000.times do |i|
  if amicable?(i, repo)
    total += (i + repo[i])
  end
end

puts total

Project Euler: Problem 48 in Ruby

I realized the other day, that you can sort the Project Euler problems by difficulty. For the most part it sticks pretty closely to the problem number, but this one was an outlier. Most of the solutions didn’t actually trim out the extraneous characters, but I thought that was the “hardest” part of this problem since I actually had to check the docs.

Problem #48

Find the last ten digits of the series, 1^(1) + 2^(2) + 3^(3) + … + 1000^(1000).

sum = 0

(1..1_000).each do |i|
  sum += i**i
end

puts (sum % 10**10).to_s[-10, 10]

Project Euler: Problem 20 in Ruby

I cheesed out on this one, pretty much just did what the problem called for. No magic. Looking through the forums, however, it was pretty much par for the course.

Problem #20

Find the sum of the digits in the number 100!

product, sum = 1, 0

100.times do |i|
  product *= i + 1
end

while product > 0
  sum += (product /= 10) % 10
end

puts sum

Project Euler: Problem 67 in Ruby

I guess my solution to #18 was good enough since it worked for #67 as well.

Problem #67

Find the maximum total from top to bottom of the triangle below:

input = # triangle goes here

tree = []
cache = []

input.split("n").each do |row|
  tree << []
  cache << []
  row.split("s").each do |i|
    tree.last << i.to_i
  end
end

def sum tree, cache, row, index, total

  if tree[row] == nil or tree[row][index] == nil
    return 0
  end

  if cache[row][index] != nil
    return total += cache[row][index]
  end
  
  left  = sum( tree, cache, row + 1, index, total )
  right = sum( tree, cache, row + 1, index + 1, total )

  cache[row][index] = [left, right].max + tree[row][index]

end

puts sum( tree, cache, 0, 0, 0 )

Ran pretty fast in 1.8.6

$ time ruby 18.rb
real	0m0.012s
user	0m0.008s
sys	0m0.004s

$ time ruby 67.rb
real	0m0.115s
user	0m0.104s
sys	0m0.012s

And a little worse in 1.9

$ time ruby1.9 18.rb
real	0m0.028s
user	0m0.016s
sys	0m0.008s

$ time ruby1.9 67.rb
real	0m0.116s
user	0m0.104s
sys	0m0.004s

Project Euler: Problem 18 in Ruby

I found this one to be very similar to problem #15, so it “clicked” pretty quickly. I basically just store the solutions so I don’t have to do any re-computing.

I saw a pretty slick method in the forums that made use of Ruby’s Enumerable module which I’ll have to give a go next time I run into something like this.

Problem #18

Find the maximum total from top to bottom of the triangle below:

input = # triangle goes here

tree = []
cache = []

input.split("n").each do |row|
  tree << []
  cache << []
  row.split("s").each do |i|
    tree.last << i.to_i
  end
end

def sum tree, cache, row, index, total

  if tree[row] == nil or tree[row][index] == nil
    return 0
  end

  if cache[row][index] != nil
    return total += cache[row][index]
  end
  
  left  = sum( tree, cache, row + 1, index, total )
  right = sum( tree, cache, row + 1, index + 1, total )

  cache[row][index] = [left, right].max + tree[row][index]

end

puts sum( tree, cache, 0, 0, 0 )

When is a Struct not a Struct?

I’ve run into an annoying problem trying to get some older java code working under ColdFusion 8. The problem method accepts two arguments, java.util.Hashmap and java.util.Vector, but the signature isn’t matching.

Here’s the set up:

<cfset classpath = [
  CreateObject( "java","java.net.URL" ).init( "file:#cfusion#" ),
  CreateObject( "java","java.net.URL" ).init( "file:#testfile#" )
] />

<cfset loader  = CreateObject( "java","java.net.URLClassLoader" ).Init(
  classpath
) />
<cfset example = loader.LoadClass( "ProblemExample" ).NewInstance() />

<cfset cfarray  = ArrayNew(1) />
<cfset cfstruct = StructNew() />

<cfdump var="#example#" />

My sample method looks good…

public void originalMethod(java.util.Hashtable h,java.util.Vector v){}

The dump looks greatdump

But I’m getting a “method was not found” error

I did a bit of googling, and found a great post about the differences between CF7 and CF8 structs and arrays. Perfect…right?

I wrote a little test method to accept a coldfusion.util.FastHashtable:

public void takeFastHashtable(coldfusion.util.FastHashtable fh){}
method was not found"

I wrote a little script, to see what I was dealing with:

<cfoutput>
  #cfstruct.getClass().getName()# == #example.inspect(cfstruct)#
  => #cfstruct.getClass().getName() EQ example.inspect(cfstruct)#
</cfoutput>

using

public String inspect( Object o ) {
  return o.getClass().getName();
}

And my output was as expected:
coldfusion.runtime.Struct == coldfusion.runtime.Struct => YES

So I wrote a up a simple test method for coldfusion.runtime.Struct:

public void testStruct(coldfusion.runtime.Struct s){}
<cfset example.testStruct(s) />

You guessed it:

"method was not found"

Okay….let’s try casting….

public coldfusion.runtime.Struct castAsStruct(Object o) {
  return (coldfusion.runtime.Struct) o;
}

This time the error’s a little different…

coldfusion.runtime.Struct cannot be cast to coldfusion.runtime.Struct
W T F

Granted, I’m trying to use underlying undocumented code, and I’m no Java expert, but there’s something here that’s not adding up. Is this a bug? Am I missing something stupid? At this point I’ll be moving on to alternative solutions, but any help would be still greatly appreciated.

You can download some sample code I’ve been using, just make sure to compile with the appropriate classpath for your environment.

Here’s my command

javac ProblemExample.java -classpath /opt/coldfusion8/lib/cfusion.jar

Project Euler: Problem 17 in Ruby

I overrode the Fixnum class, and there’s a teensy bit of recursion going on, but over all it was really simple. The hardest part was writing out all the unique numbers for my word hash.

Problem #17

If all the numbers from 1 to 1000 (one thousand) inclusive were written out in words, how many letters would be used?

words = {
  1 => "one",
  2 => "two",
  3 => "three",
  4 => "four",
  5 => "five",
  6 => "six",
  7 => "seven",
  8 => "eight",
  9 => "nine",
  10 => "ten",
  11 => "eleven",
  12 => "twelve",
  13 => "thirteen",
  14 => "fourteen",
  15 => "fifteen",
  16 => "sixteen",
  17 => "seventeen",
  18 => "eighteen",
  19 => "nineteen",
  20 => "twenty",
  30 => "thirty",
  40 => "forty",
  50 => "fifty",
  60 => "sixty",
  70 => "seventy",
  80 => "eighty",
  90 => "ninety"
}

class Fixnum

  def to_english words
    str = ""
    if self >= 100
      str = "#{words[(self / 100)]}hundred"
      if self % 100 > 0
        str = "#{str}and#{(self % 100).to_english(words)}"
      end
    elsif self > 20
      str = '#{words[(self / 10) * 10]}#{words[ self % 10 ]}'
    elsif self == 1000
      str = 'onethousand'
    else
      str = words[self]
    end
    str
  end

end

total = 0

(1..1000).each do |i|
  total += i.to_english(words).size
end

puts total