主要源码如下

/* This code is from "ActionScript 3.0 Game Programming University" by Gary Rosenzweig
Copyright 2007
http://flashgameu.com
See the book or site for more information */

package {
	import flash.display.*;
	import flash.events.*;
	import flash.text.*;
	import flash.utils.Timer;
	
	public class MatchThree extends MovieClip {
		// constants
		static const numPieces:uint = 7;
		static const spacing:Number = 45;
		static const offsetX:Number = 120;
		static const offsetY:Number = 30;
		
		// game grid and mode
		private var grid:Array;
		private var gameSprite:Sprite;
		private var firstPiece:Piece;
		private var isDropping,isSwapping:Boolean;
		private var gameScore:int;
		
		// set up grid and start game
		public function startMatchThree() {
			
			// create grid array
			grid = new Array();
			for(var gridrows:int=0;gridrows<8;gridrows++) {
				grid.push(new Array());
			}
			setUpGrid();
			isDropping = false;
			isSwapping = false;
			gameScore = 0;
			addEventListener(Event.ENTER_FRAME,movePieces);
		}
		
		public function setUpGrid() {
			// loop until valid starting grid
			while (true) {
				// create sprite
				gameSprite = new Sprite();
				
				// add 64 random pieces
				for(var col:int=0;col<8;col++) {
					for(var row:int=0;row<8;row++) {
						addPiece(col,row);
					}
				}
				
				// try again if matches are present
				if (lookForMatches().length != 0) continue;
				
				// try again if no possible moves
				if (lookForPossibles() == false) continue;
				
				// no matches, but possibles exist: good board found
				break;
			} 
			
			// add sprite
			addChild(gameSprite);
		}
		
		// create a random piece, add to sprite and grid
		public function addPiece(col,row:int):Piece {
			var newPiece:Piece = new Piece();
			newPiece.x = col*spacing+offsetX;
			newPiece.y = row*spacing+offsetY;
			newPiece.col = col;
			newPiece.row = row;
			newPiece.type = Math.ceil(Math.random()*7);
			newPiece.gotoAndStop(newPiece.type);
			newPiece.select.visible = false;
			gameSprite.addChild(newPiece);
			grid[col][row] = newPiece;
			newPiece.addEventListener(MouseEvent.CLICK,clickPiece);
			return newPiece;
		}
		
		// player clicks on a piece
		public function clickPiece(event:MouseEvent) {
			var piece:Piece = Piece(event.currentTarget);
			
			// first one selected
			if (firstPiece == null) {
				piece.select.visible = true;
				firstPiece = piece;
				
			// clicked on first piece again
			} else if (firstPiece == piece) {
				piece.select.visible = false;
				firstPiece = null;
			
			// clicked on second piece
			} else {
				firstPiece.select.visible = false;
				
				// same row, one column over
				if (firstPiece.row == piece.row) {
					if (Math.abs(firstPiece.col-piece.col) == 1) {
						makeSwap(firstPiece,piece);
						firstPiece = null;
					}
					
				// same column, one row over
				} else if (firstPiece.col == piece.col) {
					if (Math.abs(firstPiece.row-piece.row) == 1) {
						makeSwap(firstPiece,piece);
						firstPiece = null;
					}
					
				// bad move, reassign first piece
				} else {
					firstPiece = piece;
					firstPiece.select.visible = true;
				}
			}
		}

		// start animated swap of two pieces
		public function makeSwap(piece1,piece2:Piece) {
			swapPieces(piece1,piece2);
			
			// check to see if move was fruitful
			if (lookForMatches().length == 0) {
				swapPieces(piece1,piece2);
			} else {
				isSwapping = true;
			}
		}
		
		// swap two pieces
		public function swapPieces(piece1,piece2:Piece) {
			// swap row and col values
			var tempCol:uint = piece1.col;
			var tempRow:uint = piece1.row;
			piece1.col = piece2.col;
			piece1.row = piece2.row;
			piece2.col = tempCol;
			piece2.row = tempRow;
			
			// swap grid positions
			grid[piece1.col][piece1.row] = piece1;
			grid[piece2.col][piece2.row] = piece2;
			
		}

		// if any pieces are out of place, move them a step closer to being in place
		// happens when pieces are swapped, or they are dropping
		public function movePieces(event:Event) {
			var madeMove:Boolean = false;
			for(var row:int=0;row<8;row++) {
				for(var col:int=0;col<8;col++) {
					if (grid[col][row] != null) {
						
						// needs to move down
						if (grid[col][row].y < grid[col][row].row*spacing+offsetY) {
							grid[col][row].y += 5;
							madeMove = true;
							
						// needs to move up
						} else if (grid[col][row].y > grid[col][row].row*spacing+offsetY) {
							grid[col][row].y -= 5;
							madeMove = true;
							
						// needs to move right
						} else if (grid[col][row].x < grid[col][row].col*spacing+offsetX) {
							grid[col][row].x += 5;
							madeMove = true;
							
						// needs to move left
						} else if (grid[col][row].x > grid[col][row].col*spacing+offsetX) {
							grid[col][row].x -= 5;
							madeMove = true;
						}
					}
				}
			}
			
			// if all dropping is done
			if (isDropping && !madeMove) {
				isDropping = false;
				findAndRemoveMatches();
				
			// if all swapping is done
			} else if (isSwapping && !madeMove) {
				isSwapping = false;
				findAndRemoveMatches();
			}
		}
				
		
		// gets matches and removes them, applies points
		public function findAndRemoveMatches() {
			// get list of matches
			var matches:Array = lookForMatches();
			for(var i:int=0;i<matches.length;i++) {
				var numPoints:Number = (matches[i].length-1)*50;
				for(var j:int=0;j<matches[i].length;j++) {
					if (gameSprite.contains(matches[i][j])) {
						var pb = new PointBurst(this,numPoints,matches[i][j].x,matches[i][j].y);
						addScore(numPoints);
						gameSprite.removeChild(matches[i][j]);
						grid[matches[i][j].col][matches[i][j].row] = null;
						affectAbove(matches[i][j]);
					}
				}
			}
			
			// add any new piece to top of board
			addNewPieces();
			
			// no matches found, maybe the game is over?
			if (matches.length == 0) {
				if (!lookForPossibles()) {
					endGame();
				}
			}
		}
		
		//return an array of all matches found
		public function lookForMatches():Array {
			var matchList:Array = new Array();
			
			// search for horizontal matches
			for (var row:int=0;row<8;row++) {
				for(var col:int=0;col<6;col++) {
					var match:Array = getMatchHoriz(col,row);
					if (match.length > 2) {
						matchList.push(match);
						col += match.length-1;
					}
				}
			}
			
			// search for vertical matches
			for(col=0;col<8;col++) {
				for (row=0;row<6;row++) {
					match = getMatchVert(col,row);
					if (match.length > 2) {
						matchList.push(match);
						row += match.length-1;
					}
						
				}
			}
			return matchList;
		}
		
		// look for horizontal matches starting at this point
		public function getMatchHoriz(col,row):Array {
			var match:Array = new Array(grid[col][row]);
			for(var i:int=1;col+i<8;i++) {
				if (grid[col][row].type == grid[col+i][row].type) {
					match.push(grid[col+i][row]);
				} else {
					return match;
				}
			}
			return match;
		}

		// look for vertical matches starting at this point
		public function getMatchVert(col,row):Array {
			var match:Array = new Array(grid[col][row]);
			for(var i:int=1;row+i<8;i++) {
				if (grid[col][row].type == grid[col][row+i].type) {
					match.push(grid[col][row+i]);
				} else {
					return match;
				}
			}
			return match;
		}
		
		// tell all pieces above this one to move down
		public function affectAbove(piece:Piece) {
			for(var row:int=piece.row-1;row>=0;row--) {
				if (grid[piece.col][row] != null) {
					grid[piece.col][row].row++;
					grid[piece.col][row+1] = grid[piece.col][row];
					grid[piece.col][row] = null;
				}
			}
		}
		
		// if there are missing pieces in a column, add one to drop
		public function addNewPieces() {
			for(var col:int=0;col<8;col++) {
				var missingPieces:int = 0;
				for(var row:int=7;row>=0;row--) {
					if (grid[col][row] == null) {
						var newPiece:Piece = addPiece(col,row);
						newPiece.y = offsetY-spacing-spacing*missingPieces++;
						isDropping = true;
					}
				}
			}
		}
		
		// look to see if a possible move is on the board
		public function lookForPossibles() {
			for(var col:int=0;col<8;col++) {
				for(var  row:int=0;row<8;row++) {
					
					// horizontal possible, two plus one
					if (matchPattern(col, row, [[1,0]], [[-2,0],[-1,-1],[-1,1],[2,-1],[2,1],[3,0]])) {
						return true;
					}
					
					// horizontal possible, middle
					if (matchPattern(col, row, [[2,0]], [[1,-1],[1,1]])) {
						return true;
					}
					
					// vertical possible, two plus one
					if (matchPattern(col, row, [[0,1]], [[0,-2],[-1,-1],[1,-1],[-1,2],[1,2],[0,3]])) {
						return true;
					}
					
					// vertical possible, middle
					if (matchPattern(col, row, [[0,2]], [[-1,1],[1,1]])) {
						return true;
					}
				}
			}
			
			// no possible moves found
			return false;
		}
		
		public function matchPattern(col,row:uint, mustHave, needOne:Array) {
			var thisType:int = grid[col][row].type;
			
			// make sure this has all must-haves
			for(var i:int=0;i<mustHave.length;i++) {
				if (!matchType(col+mustHave[i][0], row+mustHave[i][1], thisType)) {
					return false;
				}
			}
			
			// make sure it has at least one need-ones
			for(i=0;i<needOne.length;i++) {
				if (matchType(col+needOne[i][0], row+needOne[i][1], thisType)) {
					return true;
				}
			}
			return false;
		}
		
		public function matchType(col,row,type:int) {
			// make sure col and row aren't beyond the limit
			if ((col < 0) || (col > 7) || (row < 0) || (row > 7)) return false;
			return (grid[col][row].type == type);
		}
		
		public function addScore(numPoints:int) {
			gameScore += numPoints;
			MovieClip(root).scoreDisplay.text = String(gameScore);
		}
		
		public function endGame() {
			// move to back
			setChildIndex(gameSprite,0);
			// go to end game
			gotoAndStop("gameover");
		}
		
		public function cleanUp() {
			grid = null;
			removeChild(gameSprite);
			gameSprite = null;
			removeEventListener(Event.ENTER_FRAME,movePieces);
		}
	}
}