15 puzzle game in 3D: Difference between revisions
Thundergnat (talk | contribs) m (Thundergnat moved page 15 Puzzle Game in 3D to 15 puzzle game in 3D: Follow normal task title capitalization policy) |
(Added Wren) |
||
Line 621: | Line 621: | ||
exit # Exit from the Events Loop |
exit # Exit from the Events Loop |
||
</lang> |
</lang> |
||
=={{header|Wren}}== |
|||
{{trans|Go}} |
|||
{{libheader|DOME}} |
|||
{{libheader|Wren-polygon}} |
|||
{{libheader|Go-fonts}} |
|||
The palette is somewhat different from the Go example and, if the player is eventually successful in assembling the cubes in order, the white cube changes to gold and displays the number 16. |
|||
<lang ecmascript>import "dome" for Window |
|||
import "graphics" for Canvas, Color, Font |
|||
import "input" for Keyboard |
|||
import "random" for Random |
|||
import "math" for Math |
|||
import "./polygon" for Polygon |
|||
var Palette = [ |
|||
Color.purple, |
|||
Color.darkblue, |
|||
Color.darkpurple, |
|||
Color.darkgreen, |
|||
Color.brown, |
|||
Color.darkgray, |
|||
Color.lightgray, |
|||
Color.red, |
|||
Color.orange, |
|||
Color.yellow, |
|||
Color.green, |
|||
Color.blue, |
|||
Color.indigo, |
|||
Color.pink, |
|||
Color.peach, |
|||
Color.white |
|||
] |
|||
var Rand = Random.new() |
|||
class FifteenPuzzle3d { |
|||
construct new() { |
|||
Window.resize(960, 840) |
|||
Canvas.resize(960, 840) |
|||
Window.title = "15-puzzle game using 3D cubes" |
|||
_radius = Canvas.height / 14 |
|||
// see Go-fonts page |
|||
Font.load("Go-Regular20", "Go-Regular.ttf", 20) |
|||
Canvas.font = "Go-Regular20" |
|||
_blank = 15 |
|||
_moves = 0 |
|||
_gameOver = false |
|||
} |
|||
init() { |
|||
_centers = List.filled(16, null) |
|||
_cubes = List.filled(15, 0) |
|||
for (i in 0..14) _cubes[i] = i |
|||
Rand.shuffle(_cubes) |
|||
_cubes.add(15) |
|||
var x = Canvas.width / 10 |
|||
var y = _radius |
|||
for (i in 0..3) { |
|||
var cx = 2 * x * (i + 1) |
|||
for (j in 0..3) { |
|||
var cy = (x + y) * (j + 1) |
|||
_centers[j * 4 + i] = [cx, cy] |
|||
} |
|||
} |
|||
for (i in 0..15) drawCube(_cubes[i], i) |
|||
} |
|||
drawCube(n, pos) { |
|||
var cx = _centers[pos][0] |
|||
var cy = _centers[pos][1] |
|||
var angle = Num.pi / 6 |
|||
var incr = 2 * angle |
|||
var hexagon = Polygon.regular(6, cx, cy, _radius, 90) |
|||
hexagon.drawfill(Palette[n]) |
|||
for (i in [1, 3, 5]) { |
|||
var vx = (_radius * Math.cos(angle + i*incr) + cx).floor |
|||
var vy = (_radius * Math.sin(angle + i*incr) + cy).floor |
|||
Canvas.line(cx, cy, vx, vy, Color.black) |
|||
} |
|||
var ns = (n < 15 || _gameOver) ? (n + 1).toString : "" |
|||
var hr = _radius * 0.5 |
|||
var er = _radius * 0.125 |
|||
var tqr = _radius * 0.75 |
|||
Canvas.print(ns, cx + hr - er, cy, Color.white) |
|||
Canvas.print(ns, cx - hr - er, cy, Color.white) |
|||
Canvas.print(ns, cx - er, cy - tqr, Color.white) |
|||
} |
|||
completed { |
|||
for (i in 0..15) { |
|||
if (_cubes[i] != i) return false |
|||
} |
|||
Palette[15] = Color.rgb(255, 215, 0) // gold |
|||
return true |
|||
} |
|||
update() { |
|||
var changed = false |
|||
if (Keyboard["Left"].justPressed) { |
|||
if (_blank%4 != 0) { |
|||
_cubes.swap(_blank, _blank-1) |
|||
_blank = _blank - 1 |
|||
_moves =_moves + 1 |
|||
changed = true |
|||
} |
|||
} else if (Keyboard["Right"].justPressed) { |
|||
if ((_blank+1)%4 != 0) { |
|||
_cubes.swap(_blank, _blank+1) |
|||
_blank = _blank + 1 |
|||
_moves = _moves + 1 |
|||
changed = true |
|||
} |
|||
} else if (Keyboard["Up"].justPressed) { |
|||
if (_blank > 3) { |
|||
_cubes.swap(_blank, _blank-4) |
|||
_blank = _blank - 4 |
|||
_moves = _moves + 1 |
|||
changed = true |
|||
} |
|||
} else if (Keyboard["Down"].justPressed) { |
|||
if (_blank < 12) { |
|||
_cubes.swap(_blank, _blank+4) |
|||
_blank = _blank + 4 |
|||
_moves = _moves + 1 |
|||
changed = true |
|||
} |
|||
} |
|||
if (changed) { |
|||
Canvas.cls(Color.black) |
|||
_gameOver = completed |
|||
for (i in 0..15) drawCube(_cubes[i], i) |
|||
if (!_gameOver) { |
|||
var m = "Moves = %(_moves)" |
|||
Canvas.print(m, 0.4 * Canvas.width, 13 * _radius, Color.white) |
|||
} else { |
|||
var m = "You've completed the puzzle in %(_moves) moves!" |
|||
Canvas.print(m, 0.3 * Canvas.width, 13 * _radius, Color.white) |
|||
} |
|||
} |
|||
} |
|||
draw(alpha) {} |
|||
} |
|||
var Game = FifteenPuzzle3d.new()</lang> |
Revision as of 16:48, 24 August 2021
- Task
Create either a 15 puzzle game or an 8 puzzle game in your language using cubes rather than squares to represent the tiles (including the blank tile). The 'cuboid look' may be simulated rather than using actual 3D graphics and the cubes may either rotate or remain static.
This should be a playable game as opposed to a program which automatically attempts to find a solution without user intervention.
- References
- Article: Wikipedia 15 puzzle.
- Video: 15 Puzzle Game in 3D for the Ring entry.
- Necessary files: Files for 15 Puzzle Game in 3D as used by the Ring entry.
Go
Despite the name of the task, it appears that the author's Ring entry is actually producing an '8 puzzle' game and that the 3D aspect is handled by replacing the usual squares with colored, numbered cubes which rotate in space.
The following produces instead a '15 puzzle' game and the 3D aspect is again handled by using colored, numbered cubes. However, the cubes do not rotate (I found this very distracting when playing the game) and the 3D look is simulated by drawing regular hexagons with inner lines drawn between the appropriate vertices to make them look like cubes. A white numberless cube represents the blank square in a normal game.
The game is controlled by the arrow keys (mouse movement is not supported) which move the white cube left, right, up or down exchanging positions with the colored cube already occupying that position. The number of moves is continually updated and, if the player is eventually successful in assembling the cubes in order, an appropriate message is displayed, the white cube changes to dark green and displays the number 16. <lang go>package main
import (
"fmt" "github.com/gen2brain/raylib-go/raylib" "math" "math/rand" "strconv" "time"
)
var palette = []rl.Color{
rl.Blue, rl.Green, rl.Red, rl.SkyBlue, rl.Magenta, rl.Gray, rl.Lime, rl.Purple, rl.Violet, rl.Pink, rl.Gold, rl.Orange, rl.Maroon, rl.Beige, rl.Brown, rl.RayWhite,
}
var (
screenWidth = int32(960) screenHeight = int32(840) radius = screenHeight / 14 fontSize = 2 * radius / 5 angle = math.Pi / 6 incr = 2 * angle blank = 15 moves = 0 gameOver = false
)
var (
centers [16]rl.Vector2 cubes [16]int
)
func init() {
for i := 0; i < 16; i++ { cubes[i] = i }
}
func drawCube(n, pos int) {
r := float32(radius) rl.DrawPoly(centers[pos], 6, r, 0, palette[n]) cx, cy := centers[pos].X, centers[pos].Y for i := 1; i <= 5; i += 2 { fi := float64(i) vx := int32(r*float32(math.Cos(angle+fi*incr)) + cx) vy := int32(r*float32(math.Sin(angle+fi*incr)) + cy) rl.DrawLine(int32(cx), int32(cy), vx, vy, rl.Black) } ns := "" if n < 15 || gameOver { ns = strconv.Itoa(n + 1) } hr, er, tqr := r/2, r/8, 0.75*r rl.DrawText(ns, int32(cx+hr-er), int32(cy), fontSize, rl.RayWhite) rl.DrawText(ns, int32(cx-hr-er), int32(cy), fontSize, rl.RayWhite) rl.DrawText(ns, int32(cx-er), int32(cy-tqr), fontSize, rl.RayWhite)
}
func updateGame() {
if gameOver { return } else if rl.IsKeyPressed(rl.KeyLeft) { if blank%4 != 0 { cubes[blank], cubes[blank-1] = cubes[blank-1], cubes[blank] blank-- moves++ } } else if rl.IsKeyPressed(rl.KeyRight) { if (blank+1)%4 != 0 { cubes[blank], cubes[blank+1] = cubes[blank+1], cubes[blank] blank++ moves++ } } else if rl.IsKeyPressed(rl.KeyUp) { if blank > 3 { cubes[blank], cubes[blank-4] = cubes[blank-4], cubes[blank] blank -= 4 moves++ } } else if rl.IsKeyPressed(rl.KeyDown) { if blank < 12 { cubes[blank], cubes[blank+4] = cubes[blank+4], cubes[blank] blank += 4 moves++ } }
}
func completed() bool {
for i := 0; i < 16; i++ { if cubes[i] != i { return false } } palette[15] = rl.DarkGreen gameOver = true return true
}
func main() {
rand.Seed(time.Now().UnixNano()) rand.Shuffle(15, func(i, j int) { cubes[i], cubes[j] = cubes[j], cubes[i] }) rl.InitWindow(screenWidth, screenHeight, "15-puzzle game using 3D cubes") rl.SetTargetFPS(60) var x, y = float32(screenWidth) / 10, float32(radius) for i := 0; i < 4; i++ { cx := 2 * x * float32(i+1) for j := 0; j < 4; j++ { cy := (x + y) * float32(j+1) centers[j*4+i] = rl.NewVector2(cx, cy) } }
for !rl.WindowShouldClose() { rl.BeginDrawing() rl.ClearBackground(rl.Black) for i := 0; i < 16; i++ { drawCube(cubes[i], i) }
if !completed() { m := fmt.Sprintf("Moves = %d", moves) rl.DrawText(m, 4*int32(x), 13*int32(y), fontSize, rl.RayWhite) } else { m := fmt.Sprintf("You've completed the puzzle in %d moves!", moves) rl.DrawText(m, 3*int32(x), 13*int32(y), fontSize, rl.RayWhite) } rl.EndDrawing() updateGame() }
rl.CloseWindow()
}</lang>
Ring
<lang ring> /*
- Project : 15 Puzzle Game in 3D
- /
- Load Libraries
load "gamelib.ring" # RingAllegro Library load "opengl21lib.ring" # RingOpenGL Library
butSize = 3 texture = list(9) cube = list(9) rnd = list(9) rndok = 0
for n=1 to 9
rnd[n] = 0
next
for n=1 to 9
while true rndok = 0 ran = random(8) + 1 for nr=1 to 9 if rnd[nr] = ran rndok = 1 ok next if rndok = 0 rnd[n] = ran exit ok end
next
for n=1 to 9
if rnd[n] = 9 empty = n ok
next
- ==============================================================
- To Support MacOS X
al_run_main() func al_game_start # Called by al_run_main() main() # Now we call our main function
- ==============================================================
func main new TicTacToe3D { start() }
class TicTacToe3D from GameLogic
FPS = 60 TITLE = "CalmoSoft Fifteen Puzzle Game 3D"
oBackground = new GameBackground oGameSound = new GameSound oGameCube = new GameCube oGameInterface = new GameInterface
func loadresources oGameSound.loadresources() oBackGround.loadresources() oGameCube.loadresources()
func drawScene oBackground.update() oGameInterface.update(self)
func MouseClickEvent oGameInterface.MouseClickEvent(self)
class GameInterface
func Update oGame prepare() cubes(oGame)
func Prepare w = 1024 h = 768 ratio = w / h glViewport(0, 0, w, h) glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective(-120,ratio,1,120) glMatrixMode(GL_MODELVIEW) glLoadIdentity() glEnable(GL_TEXTURE_2D) glShadeModel(GL_SMOOTH) glClearColor(0.0, 0.0, 0.0, 0.5) glClearDepth(1.0) glEnable(GL_DEPTH_TEST) glEnable(GL_CULL_FACE) glDepthFunc(GL_LEQUAL) glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
func Cubes oGame oGame.oGameCube { aGameMap = oGame.aGameMap
cube[1] = cube( 5 , -3 , -5 , texture[rnd[1]] )
cube[2] = cube( 0 , -3 , -5 , texture[rnd[2]] ) cube[3] = cube( -5 , -3 , -5 , texture[rnd[3]] ) cube[4] = cube( 5 , 1 , -5 , texture[rnd[4]] ) cube[5] = cube( 0 , 1 , -5 , texture[rnd[5]] ) cube[6] = cube( -5 , 1 , -5 , texture[rnd[6]] ) cube[7] = cube( 5 , 5 , -5 , texture[rnd[7]] ) cube[8] = cube( 0 , 5 , -5 , texture[rnd[8]] ) cube[9] = cube( -5 , 5 , -5 , texture[rnd[9]] )
rotate()
}
func MouseClickEvent oGame oGame { aBtn = Point2Button(Mouse_X,Mouse_Y)
move = 0
nRow = aBtn[1] nCol = aBtn[2]
tile = (nRow-1)*3 + nCol up = (empty = (tile - butSize)) down = (empty = (tile + butSize)) left = ((empty = (tile- 1)) and ((tile % butSize) != 1)) right = ((empty = (tile + 1)) and ((tile % butSize) != 0)) move = up or down or left or right if move = 1 temp = rnd[empty] rnd[empty] = rnd[tile] rnd[tile] = temp empty = tile oGame.oGameCube {
aGameMap = oGame.aGameMap
cube[1] = cube( 5 , -3 , -5 , texture[rnd[1]] )
cube[2] = cube( 0 , -3 , -5 , texture[rnd[2]] ) cube[3] = cube( -5 , -3 , -5 , texture[rnd[3]] ) cube[4] = cube( 5 , 1 , -5 , texture[rnd[4]] ) cube[5] = cube( 0 , 1 , -5 , texture[rnd[5]] ) cube[6] = cube( -5 , 1 , -5 , texture[rnd[6]] ) cube[7] = cube( 5 , 5 , -5 , texture[rnd[7]] ) cube[8] = cube( 0 , 5 , -5 , texture[rnd[8]] ) cube[9] = cube( -5 , 5 , -5 , texture[rnd[9]] )
rotate()
}
ok
}
Class GameLogic from GraphicsAppBase
aGameMap = [ [ :n , :n , :n ] , [ :n , :n , :n ] , [ :n , :n , :n ] ]
aGameButtons = [ # x1,y1,x2,y2
[176,88,375,261], # [1,1]
[423,88,591,261], # [1,2] [645,88,876,261], # [1,3]
[176,282,375,428], # [2,1]
[423,282,591,428], # [2,2] [645,282,876,428], # [2,3]
[176,454,375,678], # [3,1]
[423,454,591,678], # [3,2] [645,454,876,678] # [3,3] ]
cActivePlayer = :x
func point2button x,y nRow = 0 nCol = 0 for t = 1 to len(aGameButtons) rect = aGameButtons[t] if x >= rect[1] and x <= rect[3] and y >= rect[2] and y <= rect[4] switch t on 1 nRow = 1 nCol = 1 on 2 nRow = 1 nCol = 2 on 3 nRow = 1 nCol = 3 on 4 nRow = 2 nCol = 1 on 5 nRow = 2 nCol = 2 on 6 nRow = 2 nCol = 3 on 7 nRow = 3 nCol = 1 on 8 nRow = 3 nCol = 2 on 9 nRow = 3 nCol = 3 off exit ok next return [nRow,nCol]
class GameCube
bitmap bitmap2 bitmap3 textureX textureO textureN
xrot = 0.0 yrot = 0.0 zrot = 0.0
func loadresources bitmp1 = al_load_bitmap("image/n1.jpg") texture[1] = al_get_opengl_texture(bitmp1) bitmp2 = al_load_bitmap("image/n2.jpg") texture[2] = al_get_opengl_texture(bitmp2) bitmp3 = al_load_bitmap("image/n3.jpg") texture[3] = al_get_opengl_texture(bitmp3) bitmp4 = al_load_bitmap("image/n4.jpg") texture[4] = al_get_opengl_texture(bitmp4) bitmp5 = al_load_bitmap("image/n5.jpg") texture[5] = al_get_opengl_texture(bitmp5) bitmp6 = al_load_bitmap("image/n6.jpg") texture[6] = al_get_opengl_texture(bitmp6) bitmp7 = al_load_bitmap("image/n7.jpg") texture[7] = al_get_opengl_texture(bitmp7) bitmp8 = al_load_bitmap("image/n8.jpg") texture[8] = al_get_opengl_texture(bitmp8) bitmp9 = al_load_bitmap("image/empty.png") texture[9] = al_get_opengl_texture(bitmp9)
func cube(x,y,z,nTexture) glLoadIdentity() glTranslatef(x,y,z) glRotatef(xrot,1.0,0.0,0.0) glRotatef(yrot,0.0,1.0,0.0) glRotatef(zrot,0.0,0.0,1.0) setCubeTexture(nTexture) drawCube()
func setCubeTexture cTexture glBindTexture(GL_TEXTURE_2D, cTexture)
func Rotate xrot += 0.3 * 5 yrot += 0.2 * 5 zrot += 0.4 * 5
func drawcube glBegin(GL_QUADS) // Front Face glTexCoord2f(0.0, 0.0) glVertex3f(-1.0, -1.0, 1.0) glTexCoord2f(1.0, 0.0) glVertex3f( 1.0, -1.0, 1.0) glTexCoord2f(1.0, 1.0) glVertex3f( 1.0, 1.0, 1.0) glTexCoord2f(0.0, 1.0) glVertex3f(-1.0, 1.0, 1.0) // Back Face glTexCoord2f(1.0, 0.0) glVertex3f(-1.0, -1.0, -1.0) glTexCoord2f(1.0, 1.0) glVertex3f(-1.0, 1.0, -1.0) glTexCoord2f(0.0, 1.0) glVertex3f( 1.0, 1.0, -1.0) glTexCoord2f(0.0, 0.0) glVertex3f( 1.0, -1.0, -1.0) // Top Face glTexCoord2f(0.0, 1.0) glVertex3f(-1.0, 1.0, -1.0) glTexCoord2f(0.0, 0.0) glVertex3f(-1.0, 1.0, 1.0) glTexCoord2f(1.0, 0.0) glVertex3f( 1.0, 1.0, 1.0) glTexCoord2f(1.0, 1.0) glVertex3f( 1.0, 1.0, -1.0) // Bottom Face glTexCoord2f(1.0, 1.0) glVertex3f(-1.0, -1.0, -1.0) glTexCoord2f(0.0, 1.0) glVertex3f( 1.0, -1.0, -1.0) glTexCoord2f(0.0, 0.0) glVertex3f( 1.0, -1.0, 1.0) glTexCoord2f(1.0, 0.0) glVertex3f(-1.0, -1.0, 1.0)
// Right face glTexCoord2f(1.0, 0.0) glVertex3f( 1.0, -1.0, -1.0) glTexCoord2f(1.0, 1.0) glVertex3f( 1.0, 1.0, -1.0) glTexCoord2f(0.0, 1.0) glVertex3f( 1.0, 1.0, 1.0) glTexCoord2f(0.0, 0.0) glVertex3f( 1.0, -1.0, 1.0)
// Left Face glTexCoord2f(0.0, 0.0) glVertex3f(-1.0, -1.0, -1.0) glTexCoord2f(1.0, 0.0) glVertex3f(-1.0, -1.0, 1.0) glTexCoord2f(1.0, 1.0) glVertex3f(-1.0, 1.0, 1.0) glTexCoord2f(0.0, 1.0) glVertex3f(-1.0, 1.0, -1.0) glEnd()
class GameBackground
nBackX = 0 nBackY = 0 nBackDiffx = -1 nBackDiffy = -1 nBackMotion = 1 aBackMotionList = [ [ -1, -1 ] , # Down - Right [ 0 , 1 ] , # Up [ -1, -1 ] , # Down - Right [ 0 , 1 ] , # Up [ 1 , -1 ] , # Down - Left [ 0 , 1 ] , # Up [ 1 , -1 ] , # Down - Left [ 0 , 1 ] # Up ]
bitmap
func Update draw() motion()
func draw al_draw_bitmap(bitmap,nBackX,nBackY,1)
func motion nBackX += nBackDiffx nBackY += nBackDiffy if (nBackY = -350) or (nBackY = 0) nBackMotion++ if nBackMotion > len(aBackMotionList) nBackMotion = 1 ok nBackDiffx = aBackMotionList[nBackMotion][1] nBackDiffy = aBackMotionList[nBackMotion][2] ok
func loadResources bitmap = al_load_bitmap("image/back.jpg")
class GameSound
sample sampleid
func loadresources sample = al_load_sample( "sound/music1.wav" ) sampleid = al_new_allegro_sample_id() al_play_sample(sample, 1.0, 0.0,1.0,ALLEGRO_PLAYMODE_LOOP,sampleid)
class GraphicsAppBase
display event_queue ev timeout timer redraw = true FPS = 60 SCREEN_W = 1024 SCREEN_H = 700 KEY_UP = 1 KEY_DOWN = 2 KEY_LEFT = 3 KEY_RIGHT = 4 Key = [false,false,false,false] Mouse_X = 0 Mouse_Y = 0 TITLE = "Graphics Application" PRINT_MOUSE_XY = False
func start SetUp() loadResources() eventsLoop() destroy()
func setup al_init() al_init_font_addon() al_init_ttf_addon() al_init_image_addon() al_install_audio() al_init_acodec_addon() al_reserve_samples(1) al_set_new_display_flags(ALLEGRO_OPENGL) display = al_create_display(SCREEN_W,SCREEN_H) al_set_window_title(display,TITLE) al_clear_to_color(al_map_rgb(0,0,0)) event_queue = al_create_event_queue() al_register_event_source(event_queue, al_get_display_event_source(display)) ev = al_new_allegro_event() timeout = al_new_allegro_timeout() al_init_timeout(timeout, 0.06) timer = al_create_timer(1.0 / FPS) al_register_event_source(event_queue, al_get_timer_event_source(timer)) al_start_timer(timer) al_install_mouse() al_register_event_source(event_queue, al_get_mouse_event_source()) al_install_keyboard() al_register_event_source(event_queue, al_get_keyboard_event_source())
func eventsLoop while true al_wait_for_event_until(event_queue, ev, timeout) switch al_get_allegro_event_type(ev) on ALLEGRO_EVENT_DISPLAY_CLOSE CloseEvent() on ALLEGRO_EVENT_TIMER redraw = true on ALLEGRO_EVENT_MOUSE_AXES mouse_x = al_get_allegro_event_mouse_x(ev) mouse_y = al_get_allegro_event_mouse_y(ev) if PRINT_MOUSE_XY see "x = " + mouse_x + nl see "y = " + mouse_y + nl ok on ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY mouse_x = al_get_allegro_event_mouse_x(ev) mouse_y = al_get_allegro_event_mouse_y(ev) on ALLEGRO_EVENT_MOUSE_BUTTON_UP MouseClickEvent() on ALLEGRO_EVENT_KEY_DOWN switch al_get_allegro_event_keyboard_keycode(ev) on ALLEGRO_KEY_UP key[KEY_UP] = true on ALLEGRO_KEY_DOWN key[KEY_DOWN] = true on ALLEGRO_KEY_LEFT key[KEY_LEFT] = true on ALLEGRO_KEY_RIGHT key[KEY_RIGHT] = true off on ALLEGRO_EVENT_KEY_UP switch al_get_allegro_event_keyboard_keycode(ev) on ALLEGRO_KEY_UP key[KEY_UP] = false on ALLEGRO_KEY_DOWN key[KEY_DOWN] = false on ALLEGRO_KEY_LEFT key[KEY_LEFT] = false on ALLEGRO_KEY_RIGHT key[KEY_RIGHT] = false on ALLEGRO_KEY_ESCAPE exit off off if redraw and al_is_event_queue_empty(event_queue) redraw = false drawScene() al_flip_display() ok callgc() end
func destroy al_destroy_timer(timer) al_destroy_allegro_event(ev) al_destroy_allegro_timeout(timeout) al_destroy_event_queue(event_queue) al_destroy_display(display) al_exit()
func loadresources
func drawScene
func MouseClickEvent exit # Exit from the Events Loop
func CloseEvent exit # Exit from the Events Loop </lang>
Wren
The palette is somewhat different from the Go example and, if the player is eventually successful in assembling the cubes in order, the white cube changes to gold and displays the number 16. <lang ecmascript>import "dome" for Window import "graphics" for Canvas, Color, Font import "input" for Keyboard import "random" for Random import "math" for Math import "./polygon" for Polygon
var Palette = [
Color.purple, Color.darkblue, Color.darkpurple, Color.darkgreen, Color.brown, Color.darkgray, Color.lightgray, Color.red, Color.orange, Color.yellow, Color.green, Color.blue, Color.indigo, Color.pink, Color.peach, Color.white
]
var Rand = Random.new()
class FifteenPuzzle3d {
construct new() { Window.resize(960, 840) Canvas.resize(960, 840) Window.title = "15-puzzle game using 3D cubes" _radius = Canvas.height / 14 // see Go-fonts page Font.load("Go-Regular20", "Go-Regular.ttf", 20) Canvas.font = "Go-Regular20" _blank = 15 _moves = 0 _gameOver = false }
init() { _centers = List.filled(16, null) _cubes = List.filled(15, 0) for (i in 0..14) _cubes[i] = i Rand.shuffle(_cubes) _cubes.add(15) var x = Canvas.width / 10 var y = _radius for (i in 0..3) { var cx = 2 * x * (i + 1) for (j in 0..3) { var cy = (x + y) * (j + 1) _centers[j * 4 + i] = [cx, cy] } } for (i in 0..15) drawCube(_cubes[i], i) }
drawCube(n, pos) { var cx = _centers[pos][0] var cy = _centers[pos][1] var angle = Num.pi / 6 var incr = 2 * angle var hexagon = Polygon.regular(6, cx, cy, _radius, 90) hexagon.drawfill(Palette[n]) for (i in [1, 3, 5]) { var vx = (_radius * Math.cos(angle + i*incr) + cx).floor var vy = (_radius * Math.sin(angle + i*incr) + cy).floor Canvas.line(cx, cy, vx, vy, Color.black) } var ns = (n < 15 || _gameOver) ? (n + 1).toString : "" var hr = _radius * 0.5 var er = _radius * 0.125 var tqr = _radius * 0.75 Canvas.print(ns, cx + hr - er, cy, Color.white) Canvas.print(ns, cx - hr - er, cy, Color.white) Canvas.print(ns, cx - er, cy - tqr, Color.white) }
completed { for (i in 0..15) { if (_cubes[i] != i) return false } Palette[15] = Color.rgb(255, 215, 0) // gold return true }
update() { var changed = false if (Keyboard["Left"].justPressed) { if (_blank%4 != 0) { _cubes.swap(_blank, _blank-1) _blank = _blank - 1 _moves =_moves + 1 changed = true } } else if (Keyboard["Right"].justPressed) { if ((_blank+1)%4 != 0) { _cubes.swap(_blank, _blank+1) _blank = _blank + 1 _moves = _moves + 1 changed = true } } else if (Keyboard["Up"].justPressed) { if (_blank > 3) { _cubes.swap(_blank, _blank-4) _blank = _blank - 4 _moves = _moves + 1 changed = true } } else if (Keyboard["Down"].justPressed) { if (_blank < 12) { _cubes.swap(_blank, _blank+4) _blank = _blank + 4 _moves = _moves + 1 changed = true } } if (changed) { Canvas.cls(Color.black) _gameOver = completed for (i in 0..15) drawCube(_cubes[i], i) if (!_gameOver) { var m = "Moves = %(_moves)" Canvas.print(m, 0.4 * Canvas.width, 13 * _radius, Color.white) } else { var m = "You've completed the puzzle in %(_moves) moves!" Canvas.print(m, 0.3 * Canvas.width, 13 * _radius, Color.white) } } }
draw(alpha) {}
}
var Game = FifteenPuzzle3d.new()</lang>