flash/src/com/caucho/games/sudoku/BoardComponent.mxml
<?xml version="1.0"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml"
width="250" height="250" creationComplete="onCreationComplete()"
addedToStage="onAddedToStage()">
<mx:Script>
<![CDATA[
import flash.display.*;
import mx.controls.*;
import com.caucho.bam.*;
import com.caucho.hmtp.*;
private const CELL_WIDTH:int = 40;
private var _currentX:int = 4;
private var _currentY:int = 4;
private var _board:SudokuBoard = null;
private var _client:HmtpClient;
private var _gameJid:String;
private var _playerId:String;
private var _scoreBoard:ScoreBoard;
private var _infoLabel:Label;
private function onCreationComplete() : void
{
width = CELL_WIDTH * 10;
height = CELL_WIDTH * 10;
render();
}
private function onAddedToStage() : void
{
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
}
protected function tryEntry(x:int, y:int, value:int):void
{
_client.querySet(_gameJid, new MoveQuery(x, y, value),
onQueryResult, onQueryError);
}
public function onKeyDown(event:KeyboardEvent) : void
{
if (_board == null)
return;
if (event.keyCode == Keyboard.UP) {
if (_currentY > 0)
_currentY--;
}
else if (event.keyCode == Keyboard.DOWN) {
if (_currentY < _board.size - 1)
_currentY++;
}
else if (event.keyCode == Keyboard.LEFT) {
if (_currentX > 0)
_currentX--;
}
else if (event.keyCode == Keyboard.RIGHT) {
if (_currentX < _board.size - 1)
_currentX++;
}
else {
var value:int = event.charCode - "0".charCodeAt();
if (value > 0 && value <= _board.size)
tryEntry(_currentX, _currentY, value);
}
render();
}
public function onMouseDown(event:MouseEvent) : void
{
if (_board == null)
return;
if (event.localX >= _board.size * CELL_WIDTH + CELL_WIDTH/2||
event.localY >= _board.size * CELL_WIDTH + CELL_WIDTH/2)
return;
var newX:int = (event.localX - CELL_WIDTH/2) / CELL_WIDTH;
var newY:int = (event.localY - CELL_WIDTH/2) / CELL_WIDTH;
if (newX != _currentX || newY != _currentY) {
_currentX = newX;
_currentY = newY;
render();
}
}
public function renderReset(event:Event):void
{
render();
}
public function labelReset(event:Event):void
{
_infoLabel.text = "";
}
public function render(x:int = -1, y:int = -1) : void
{
graphics.clear();
var size:int = 9;
if (_board != null)
size = _board.size;
graphics.beginFill(0xFFFFFF);
graphics.lineStyle(3, 0x000000);
graphics.drawRect(CELL_WIDTH/2, CELL_WIDTH/2,
size * CELL_WIDTH + 1, size * CELL_WIDTH + 1);
graphics.endFill();
var i:int;
// draw the vertical lines
for (i = 1; i < 9; i++) {
if (i % 3 == 0)
graphics.lineStyle(3, 0x000000);
else
graphics.lineStyle(1, 0x000000);
graphics.moveTo(CELL_WIDTH/2 + i * CELL_WIDTH, CELL_WIDTH/2);
graphics.lineTo(CELL_WIDTH/2 + i * CELL_WIDTH,
CELL_WIDTH/2 + size * CELL_WIDTH + 1);
}
// draw the horizontal lines
for (i = 1; i < 9; i++) {
if ((i % 3) == 0)
graphics.lineStyle(3, 0x000000);
else
graphics.lineStyle(1, 0x000000);
graphics.moveTo(CELL_WIDTH/2, CELL_WIDTH/2 + i * CELL_WIDTH);
graphics.lineTo(CELL_WIDTH/2 + size * CELL_WIDTH + 1,
CELL_WIDTH/2 + i * CELL_WIDTH);
}
graphics.beginFill(0xFFFF00, 0.5);
graphics.lineStyle(0);
graphics.drawRect(CELL_WIDTH/2 + CELL_WIDTH * _currentX,
CELL_WIDTH/2 + CELL_WIDTH * _currentY,
CELL_WIDTH, CELL_WIDTH);
graphics.endFill();
if (x >=0 && y >= 0) {
// x and y indicate a cell to flash red
graphics.beginFill(0xFF0000);
graphics.lineStyle(0, 0x000000);
graphics.drawRect(CELL_WIDTH/2 + x * CELL_WIDTH,
CELL_WIDTH/2 + y * CELL_WIDTH,
CELL_WIDTH, CELL_WIDTH);
graphics.endFill();
}
}
public function onQueryResult(to:String, from:String, value:Object):void
{
if (value is MoveResult) {
handleMoveResult(to, from, MoveResult(value));
}
}
public function onQueryError(to:String, from:String,
value:Object, error:BamError):void
{
trace("onQueryError(" + to + ", " + from + ", " +
value + ", " + error + ")");
if (error is MoveError) {
var query:MoveQuery = MoveQuery(value);
var me:MoveError = MoveError(error);
_infoLabel.text = me.text;
render(query.x, query.y);
// in 300ms, rerender without the red cell
var timer:Timer = new Timer(300);
timer.addEventListener(TimerEvent.TIMER, renderReset);
timer.start();
// in 1s, remove message
timer = new Timer(1000);
timer.addEventListener(TimerEvent.TIMER, labelReset);
timer.start();
}
}
private function handleMoveResult(to:String,
from:String,
result:MoveResult):void
{
var x:int = -1;
var y:int = -1;
if (result.success) {
board.setEntry(result.x, result.y, result.value);
if (result.playerId == _playerId)
renderEntry(result.x, result.y, result.value, 0x0000ff);
else
renderEntry(result.x, result.y, result.value, 0xff0000);
}
else {
// set the incorrect cell to flash
x = result.x;
y = result.y;
// in 300ms, rerender without the red cell
var timer:Timer = new Timer(300);
timer.addEventListener(TimerEvent.TIMER, renderReset);
timer.start();
// in 1s, remove message
timer = new Timer(1000);
timer.addEventListener(TimerEvent.TIMER, labelReset);
timer.start();
_infoLabel.text = "Incorrect!";
}
if (result.playerId == _playerId)
_scoreBoard.yourScore = result.score;
else
_scoreBoard.opponentScore = result.score;
render(x, y);
}
public function get board():SudokuBoard
{
return _board;
}
public function set board(b:SudokuBoard):void
{
_board = b;
width = CELL_WIDTH * (_board.size + 1);
height = CELL_WIDTH * (_board.size + 1);
removeAllChildren();
for (var x:int = 0; x < _board.size; x++) {
for (var y:int = 0; y < _board.size; y++) {
var entry:int = _board.getEntry(x, y);
if (entry != 0)
renderEntry(x, y, entry);
}
}
render();
}
private function renderEntry(x:int, y:int, value:int,
color:uint = 0x000000):void
{
var label:Label = new Label();
label.text = value.toString();
label.x = CELL_WIDTH/2 + x * CELL_WIDTH + CELL_WIDTH / 4;
label.y = CELL_WIDTH/2 + y * CELL_WIDTH;
label.setStyle("color", color);
label.setStyle("fontSize", 30);
label.setStyle("fontFamily", "Arial");
addChild(label);
}
public function set client(c:HmtpClient):void
{
_client = c;
_client.addMessageListener(MoveResult, handleMoveResult);
}
public function set playerId(id:String):void
{
_playerId = id;
}
public function get playerId():String
{
return _playerId;
}
public function set gameJid(jid:String):void
{
_gameJid = jid;
}
public function get gameJid():String
{
return _gameJid;
}
public function set scoreBoard(sb:ScoreBoard):void
{
_scoreBoard = sb;
}
public function set infoLabel(label:Label):void
{
_infoLabel = label;
}
]]>
</mx:Script>
</mx:Canvas>