Note the arrangement of tiles – in numerical order, left to right, starting from the top left. Start game by clicking on start and then slide tiles back into the original positions to win. Slide a tile by clicking on it. There is a time limit set so click quick!
The code demonstrates many features of DXL that are not well documented.
// Tile Game /* The Tile Game for DOORS. Note the arrangement of tiles - in numerical order, left to right, starting from the top left. Start game by clicking on start and then slide tiles back into the original positions to win. Slide a tile by clicking on it. There is a time limit set so click quick! smartDXL.com 10 May 2005 */ DB dbMain = null DBE dbeCanvas = null DBE dbeStart = null int GRID_SIZE = 3 int TILE_SIZE = 50 int MARGIN = 4 int numPositions = GRID_SIZE * GRID_SIZE int gridPosition[numPositions] int emptyPosition = numPositions - 1 bool gameOver = true Date d = null int timeStart = 0 int timeNow = 0 int timeLimit = numPositions * 3 /************************************ startTimer ************************************/ void startTimer() { d = today timeStart = intOf(d) } /************************************ checkTimer ************************************/ void checkTimer() { d = today timeNow = intOf(d) if (timeNow - timeStart > timeLimit) { gameOver = true infoBox("GAME OVER") } } /************************************ isSolution ************************************/ bool isSolution() { int pos = 0 if (emptyPosition == numPositions - 1) { for (pos = 0; pos < numPositions - 1; pos++) { if (gridPosition[pos] != pos + 1) { return(false) } } return(true) } return(false) } /************************************ initialiseGrid Arrange the tiles in the grid in numerical order with the last grid position being empty. ************************************/ void initialiseGrid() { int pos = 0 for (pos = 0; pos < numPositions; pos++) { gridPosition[pos] = pos + 1 } emptyPosition = numPositions - 1 } /************************************ drawTile ************************************/ void drawTile(int pos) { int x = 0 int y = 0 int xAdj = 0 int yAdj = 0 // coordinates for grid around tile x = (pos % GRID_SIZE) * TILE_SIZE y = (pos / GRID_SIZE) * TILE_SIZE // Adjustment to coordinates for number on tile xAdj = (TILE_SIZE/2) - width(dbeCanvas, gridPosition[pos] "") / 2 yAdj = (TILE_SIZE/2) + height(dbeCanvas, gridPosition[pos] "") / 2 //print("draw tile at pos[" pos "] x=" x " y=" y "\n") // draw grid lines around tile realColor(dbeCanvas, realColor_Black) box(dbeCanvas, x, y, TILE_SIZE, TILE_SIZE) // draw the tile realColor(dbeCanvas, realColor_White) rectangle(dbeCanvas, x + (MARGIN / 2), y + (MARGIN / 2), TILE_SIZE - MARGIN, TILE_SIZE - MARGIN) // draw number on the tile font(dbeCanvas, 1, HeadingsFont) realColor(dbeCanvas, realColor_Red) draw(dbeCanvas, x + xAdj, y + yAdj, gridPosition[pos] "") } /************************************ moveTile move tile from oldPos to emptyPosition ************************************/ void moveTile(int oldPos) { //print("Move from " oldPos " to " emptyPosition "\n") gridPosition[emptyPosition] = gridPosition[oldPos] emptyPosition = oldPos } /************************************ doDrawCanvas Redraw the canvas. ************************************/ void doDrawCanvas(DBE dbeCanvas) { int pos = 0 // fill background realBackground(dbeCanvas, realColor_Grey66) // draw tiles for (pos = 0; pos < numPositions; pos++) { if (pos != emptyPosition) { drawTile(pos) } } } /************************************ doMouse Callback from user mouse click on the canvas. Move a tile and redraw the canvas. ************************************/ void doMouse(DBE dbeCanvas, int but, bool ctrl, int x, int y) { const int LEFT_MOUSE = 1 const int RIGHT_MOUSE = 3 int xEmpty = 0 int yEmpty = 0 int oldPos = 0 // only react if user is still in the game if (gameOver) { return } // only react to a left mouse click if (but != LEFT_MOUSE) { return } // corrdinates of emptyPosition xEmpty = (emptyPosition % GRID_SIZE) * TILE_SIZE + (MARGIN / 2) yEmpty = (emptyPosition / GRID_SIZE) * TILE_SIZE + (MARGIN / 2) // mouse click is valid if it is on tile next to the empty position if ((x < xEmpty - MARGIN) && (x > xEmpty - TILE_SIZE) && y > yEmpty && y < yEmpty + TILE_SIZE) { // click in tile to left of empty position oldPos = emptyPosition - 1 //print("Tile to left = " oldPos "\n") } else if ((x > xEmpty + TILE_SIZE + MARGIN) && (x < xEmpty + TILE_SIZE + TILE_SIZE) && y > yEmpty && y < yEmpty + TILE_SIZE) { // click in tile to right of empty position oldPos = emptyPosition + 1 //print("Tile to right = " oldPos "\n") } else if ((y < yEmpty - MARGIN) && (y > yEmpty - TILE_SIZE) && x > xEmpty && x < xEmpty + TILE_SIZE) { // click in tile above empty position oldPos = emptyPosition - GRID_SIZE //print("Tile above = " oldPos "\n") } else if ((y > yEmpty + TILE_SIZE + MARGIN) && (y < yEmpty + TILE_SIZE + TILE_SIZE) && x > xEmpty && x < xEmpty + TILE_SIZE) { // click in tile below empty position oldPos = emptyPosition + GRID_SIZE //print("Tile below = " oldPos "\n") } else { return } // move the tile to the empty position moveTile(oldPos) doDrawCanvas(dbeCanvas) if (isSolution()) { infoBox("CONGRATULATIONS!") } else { checkTimer() } } /************************************ doShuffleGrid Scatters the tiles in the grid. ************************************/ void doShuffleGrid(DB db) { int iterations = 0 int i = 0 int newPos = 0 iterations = GRID_SIZE * 20 for (i = 0; i < iterations; i++) { if (i % 2 == 0) { // move up/down for even iterations if (emptyPosition < GRID_SIZE) { // empty position is in the top row so we can only move down newPos = emptyPosition + GRID_SIZE } else if (emptyPosition >= numPositions - GRID_SIZE) { // empty position is in the bottom row so we can only move up newPos = emptyPosition - GRID_SIZE } else { // randomly select to move up or down if (random(2) == 0) { newPos = emptyPosition - GRID_SIZE } else { newPos = emptyPosition + GRID_SIZE } } } else { // move left/right for odd iterations if (emptyPosition % GRID_SIZE == 0) { // empty position is in the left-most column so we can only move right newPos = emptyPosition + 1 } else if (emptyPosition == GRID_SIZE - 1) { // empty position is in the right-most column of top row so we can only move left newPos = emptyPosition - 1 } else if ((emptyPosition % GRID_SIZE) + 1 == GRID_SIZE) { // empty position is in the right-most column so we can only move left newPos = emptyPosition - 1 } else { // randomly select to move left or right if (random(2) == 0) { newPos = emptyPosition - 1 } else { newPos = emptyPosition + 1 } } } // move the tile to the new position moveTile(newPos) } doDrawCanvas(dbeCanvas) gameOver = false startTimer() } /************************************ doCloseAction Clean up data structures when closing the dialog. ************************************/ void doCloseAction(DB db) { hide(dbMain) destroy(dbMain) dbMain = null } /************************************ MAIN ************************************/ initialiseGrid() dbMain = create("Tile Puzzle", styleCentered | styleFixed) dbeCanvas = canvas(dbMain, (GRID_SIZE * TILE_SIZE) + (GRID_SIZE * MARGIN), (GRID_SIZE * TILE_SIZE) + (GRID_SIZE * MARGIN), doDrawCanvas) dbeStart = apply(dbMain, "Start", doShuffleGrid) close(dbMain, true, doCloseAction) realize dbMain set(dbeCanvas, doMouse) doDrawCanvas(dbeCanvas) show dbMain