15 puzzle game: Difference between revisions

m
(Last fix C#. Ideal now :D)
(47 intermediate revisions by 12 users not shown)
Line 144:
{{out}}
The same as in Python.
 
 
=={{header|68000 Assembly}}==
Line 3,238 ⟶ 3,237:
 
=={{header|BASIC}}==
==={{header|Applesoft BASIC}}===
<syntaxhighlight lang="basic"> 100 GOSUB 500INITIALIZE
110 FOR Q = 1 TO 1
120 IF I <> X OR J <> Y THEN GOSUB 200MOVE
130 ON W GOSUB 330,450
140 LET I = K(0, K) + X
150 LET J = K(1, K) + Y
160 LET Q = K(2, K) OR W = 3
170 NEXT Q
180 VTAB T + 3
190 END
 
REM MOVE
200 IF I < 0 THEN RETURN
210 IF I > 3 THEN RETURN
220 IF J < 0 THEN RETURN
230 IF J > 3 THEN RETURN
240 LET M = (I + J * 4) * 3
250 LET N = (X + Y * 4) * 3
260 IF N > M GOTO 290SWAP
270 LET N = M
280 LET M = (X + Y * 4) * 3
REM SWAP
290 LET A$ = MID$(A$, 1, M) + MID$(A$, N + 1, 2) + MID$(A$,M + 3, N - M - 2) + MID$(A$, M + 1, 2) + MID$(A$, N + 3)
300 LET X = I
310 LET Y = J
320 ON W GOTO 440,400
 
REM RANDOM MOVE
330 VTAB T + 3
340 HTAB 2
350 PRINT MID$(S$, S + 1, 10);
360 LET S = NOT S
370 LET K = INT(RND(1) * 4) + 1
380 IF PEEK(49152) < 128 OR A$ = W$ THEN RETURN
390 LET K = PEEK(49168) * 0
REM SHOW
400 VTAB T
410 HTAB 1
420 PRINT A$;
430 LET W = (A$ = W$) + 2
REM DON'T SHOW
440 RETURN
 
REM GET KEY
450 VTAB T + Y
460 HTAB X * 3 + 2
470 GET K$
480 LET K = ASC (K$)
490 RETURN
 
REM INITIALIZE
500 PRINT " 15-PUZZLE"
 
REM KEYBOARD
 
REM ARROW KEYS TWO HANDED CLASSIC T REVERSE T SEQUENCED
REM ^K A I G ^C
REM ^H ^J ^U , Z . J K L H T F ^B ^D ^A
 
REM RIGHT , J H ^A
510 DATA8,44,74,106,72,104,1
 
REM LEFT . L F ^B
520 DATA21,46,76,108,70,102,2
 
REM DOWN A I G ^C
530 DATA11,65,97,73,105,71,103,3
 
REM UP Z K T ^D
540 DATA10,90,122,75,107,84,116,4
 
REM QUIT ^Q ESC
550 DATA0,17,27,0
560 DIM K(2,127)
570 FOR V = 0 TO 2
580 FOR D = - 1 TO 1 STEP 2
590 FOR R = 1 TO 1
600 READ K
610 LET K(V,K) = D
620 LET R = K < 5
630 NEXT R,D,V
640 LET A$ = " 1 2 3 4"
650 LET M$ = CHR$ (13)
660 LET L$ = " 5 6 7 8"
670 LET A$ = A$ + M$ + L$
680 LET L$ = " 9 10 11 12"
690 LET A$ = A$ + M$ + L$
700 LET L$ = "13 14 15 "
710 LET A$ = A$ + M$ + L$
720 LET W$ = A$
730 DATA3,3,3,3,1,0
740 READ X,Y,I,J,W,k(2, 0)
750 PRINT "PRESS A KEY"
760 PRINT " TO STOP"
770 LET S$ = " SHUFFLING "
780 LET T = PEEK(37) - 2
790 RETURN</syntaxhighlight>
==={{header|Commodore BASIC}}===
<syntaxhighlight lang="basic">10 REM 15-PUZZLE GAME
Line 4,617 ⟶ 4,714:
(aref *board* (first zpos) (second zpos))))))
(format t "You win!~%"))</syntaxhighlight>
 
=={{header|Craft Basic}}==
[[File:15 puzzle craft basic.png|thumb]]
<syntaxhighlight lang="basic">rem 15 Puzzle example game
rem written in Craft Basic
rem by Gemino Smothers 2023
rem www.lucidapogee.com
 
define size = 16, correct = 0, moves = 0
define click = 0, start = 0
 
dim list[size]
 
gosub setup
gosub game
 
end
 
sub setup
 
title "15 Puzzle"
 
bgcolor 0,128,0
cls graphics
 
resize 0, 0, 170, 270
center
 
let x = 0
let y = 30
 
for i = 0 to size - 1
 
if x = 112 then
 
let x = 0
let y = y + 25
 
endif
 
let x = x + 28
 
formid i + 1
formtext ""
buttonform x, y, 25, 20
 
next i
 
formid 17
formtext "
staticform 40, 130, 100, 20
bgcolor 0, 128, 0
fgcolor 255, 255, 0
colorform
 
formid 18
formtext ""
staticform 40, 150, 100, 20
bgcolor 0, 128, 0
fgcolor 255, 255, 0
colorform
 
formid 19
formtext "New"
buttonform 1, 1, 50, 20
 
formid 20
formtext "Help"
buttonform 55, 1, 50, 20
 
formid 21
formtext "About"
buttonform 110, 1, 50, 20
 
formid 22
formtext "Welcome."
staticform 40, 170, 120, 20
bgcolor 0, 128, 0
fgcolor 255, 255, 0
colorform
 
return
 
sub shuffle
 
let start = 1
 
formid 22
formtext "shuffling..."
updateform
 
for i = 0 to size - 1
 
formid i + 1
formtext ""
updateform
 
let list[i] = 0
 
next i
 
let t = 0
let i = 0
 
do
 
if i = 14 then
 
let n = 120 - t
 
formid i + 1
formtext n
updateform
 
let list[i] = n
 
break
 
endif
 
for f = 0 to size - 1
 
let n = int(rnd * 15) + 1
let s = 0
 
for c = 0 to i - 1
 
if n = list[c] then
 
let s = 1
break c
 
endif
 
next c
 
if s = 0 and list[i] = 0 then
 
formid i + 1
formtext n
updateform
 
let list[i] = n
let t = t + n
let i = i + 1
 
endif
 
wait
 
next f
 
loop i < size - 1
 
formid 22
formtext ""
updateform
 
return
 
sub game
 
do
 
let click = forms
 
if click > 0 and click < 17 and start = 1 then
 
let moves = moves + 1
 
formid 17
formtext "Moves: ", moves
updateform
 
gosub checkspaces
gosub checkorder
 
endif
 
if click = 19 then
 
gosub shuffle
 
let moves = 0
let correct = 0
 
formid 17
formtext "Moves:"
updateform
 
formid 18
formtext "Correct:"
updateform
 
endif
 
if click = 20 then
 
alert "Click the numbers to move them in the correct order."
 
endif
 
if click = 21 then
 
alert "15 Puzzle", newline, "by Gemino Smothers 2023 ", newline, " www.lucidapogee.com"
 
endif
 
button k, 27
 
wait
 
loop k = 0
 
return
 
sub checkspaces
 
let click = click - 1
let top = click - 4
let right = click + 1
let bottom = click + 4
let left = click - 1
 
if top >= 0 then
 
if list[top] = 0 then
 
let n = top
gosub swap
 
endif
 
endif
 
if right <= size - 1 then
 
if list[right] = 0 then
 
let n = right
gosub swap
 
endif
 
endif
 
if bottom <= size - 1 then
 
if list[bottom] = 0 then
 
let n = bottom
gosub swap
 
endif
 
endif
 
if left >= 0 then
 
if list[left] = 0 then
 
let n = left
gosub swap
 
endif
 
endif
 
return
 
sub swap
 
let t = list[click]
let list[n] = list[click]
let list[click] = 0
 
let click = click + 1
formid click
formtext ""
updateform
 
let n = n + 1
formid n
formtext t
updateform
 
return
 
sub checkorder
 
let correct = 0
 
for i = 0 to size - 2
 
if list[i] = i + 1 then
 
let correct = correct + 1
 
endif
 
next i
 
formid 18
formtext "Correct: ", correct
updateform
 
if correct = size - 1 then
 
wait
alert "You win! Moves: ", moves
 
endif
 
return</syntaxhighlight>
 
=={{header|Delphi}}==
{{works with|Delphi|6.0}}
{{libheader|Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Grids, MMSystem}}
 
This is a pure Delphi version of the program. Rather than use a console based
display, this version uses a Delphi Form for the game and a string grid
for the display. The users selects a move by clicking on the a particular
cell in the grid.
 
<syntaxhighlight lang="Delphi">
 
const BoardWidth = 4; BoardHeight = 4;
const CellCount = BoardWidth * BoardHeight;
 
var GameBoard: array [0..BoardWidth-1,0..BoardHeight-1] of integer;
 
 
procedure BuildBoard;
{Put all number in the game board}
var I,X,Y: integer;
begin
for I:=0 to CellCount-1 do
begin
Y:=I div BoardHeight;
X:=I mod BoardWidth;
GameBoard[X,Y]:=I;
end;
end;
 
 
function IsWinner: boolean;
{Check to see if tiles are winning in order}
var I,X,Y: integer;
begin
Result:=False;
for I:=1 to CellCount-1 do
begin
Y:=(I-1) div BoardHeight;
X:=(I-1) mod BoardWidth;
if GameBoard[X,Y]<>I then exit;
end;
Result:=True;
end;
 
 
procedure DisplayGameBoard(Grid: TStringGrid);
{Display game on TStringGrid component}
var Tile,X,Y: integer;
var S: string;
begin
for Y:=0 to High(GameBoard) do
begin
S:='';
for X:=0 to High(GameBoard[0]) do
begin
Tile:=GameBoard[X,Y];
if Tile=0 then Form1.GameGrid.Cells[X,Y]:=''
else Grid.Cells[X,Y]:=IntToStr(GameBoard[X,Y]);
end;
end;
end;
 
 
 
procedure ExchangePieces(P1,P2: TPoint);
{Exchange the pieces specified by P1 and P2}
var T: integer;
begin
T:=GameBoard[P1.X,P1.Y];
GameBoard[P1.X,P1.Y]:=GameBoard[P2.X,P2.Y];
GameBoard[P2.X,P2.Y]:=T;
end;
 
 
procedure Randomize;
{Scramble piece by exchanging random pieces}
var I: integer;
var P1,P2: TPoint;
begin
for I:=0 to 100 do
begin
P1:=Point(Random(BoardWidth),Random(BoardHeight));
P2:=Point(Random(BoardWidth),Random(BoardHeight));
ExchangePieces(P1,P2);
end;
end;
 
 
procedure NewGame;
{Initiate new game by randomizing tiles}
begin
BuildBoard;
Randomize;
DisplayGameBoard(Form1.GameGrid);
end;
 
 
 
function FindEmptyNeighbor(P: TPoint): TPoint;
{Find the empty neighbor cell if any}
{Returns Point(-1,-1) if none found}
begin
Result:=Point(-1,-1);
if (P.X>0) and (GameBoard[P.X-1,P.Y]=0) then Result:=Point(P.X-1,P.Y)
else if (P.X<(BoardWidth-1)) and (GameBoard[P.X+1,P.Y]=0) then Result:=Point(P.X+1,P.Y)
else if (P.Y>0) and (GameBoard[P.X,P.Y-1]=0) then Result:=Point(P.X,P.Y-1)
else if (P.Y<(BoardHeight-1)) and (GameBoard[P.X,P.Y+1]=0) then Result:=Point(P.X,P.Y+1);
end;
 
 
 
procedure ShowStatus(S: string; BellCount: integer);
{Display status string and ring bell specified number of times}
var I: integer;
begin
Form1.StatusMemo.Lines.Add(S);
for I:=1 to BellCount do PlaySound('DeviceFail', 0, SND_SYNC);
end;
 
 
 
procedure HandleMouseClick(X,Y: integer; Grid: TStringGrid);
{Handle mouse click on specified grid}
var Pos,Empty: TPoint;
var Item: integer;
begin
Grid.MouseToCell(X, Y,Pos.X, Pos.Y);
Item:=GameBoard[Pos.X,Pos.Y];
Empty:=FindEmptyNeighbor(Pos);
if (Item>0) and (Empty.X>=0) then
begin
ExchangePieces(Empty,Pos);
DisplayGameBoard(Grid);
if IsWinner then ShowStatus('Winner', 5);
end
else ShowStatus('Invalid Command.', 1);
end;
 
 
 
procedure TForm1.NewGameBtnClick(Sender: TObject);
{Create new game when button pressed}
begin
NewGame;
end;
 
 
procedure TForm1.GameGridMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
{Use the mouse click event to select a move}
begin
HandleMouseClick(X,Y,GameGrid);
end;
 
procedure TForm1.FormCreate(Sender: TObject);
{Start new game when the program starts running}
begin
NewGame;
end;
</syntaxhighlight>
{{out}}
[[File:Delphi15Puzzle.png|frame|none]]
 
=={{header|EasyLang}}==
 
[https://easylang.onlinedev/apps/15-puzzle.html?v1 Run it]
 
<syntaxhighlight lang="text">background 432
sys topleft
background 432
textsize 13
len f[] 16
funcproc draw . .
clear
for i = 1 to 16
h = f[i]
if h < 16
x = (i - 1) mod 4 * 24 + 3
y = (i - 1) div 4 * 24 + 3
color 210
move x y
rect 22 22
move x + 4 y + 6
if h < 10
move x + 6 y + 6
.
color 885
text h
.
.
color 885
text h
.
.
.
global done .
funcproc initsmiley . .
done s = 03.5
for ix = 1 to 1686
f[i]y = i86
move x y
.
# shufflecolor 983
for icircle =2.8 15* downto 2s
color 000
r = random i
move swapx f[r]- f[i]s y - s
circle s / 3
.
move x + 3.5 y - 3.5
# make it solvable
inv =circle 0s / 3
for ilinewidth =s 1/ to 153
curve for[ jx =- 1s toy i+ -s x y + 2 * s x + s y + s 1]
.
if f[j] > f[i]
proc init . .
inv += 1
done = 0
for i = 1 to 16
f[i] = i
.
# shuffle
for i = 15 downto 2
r = randint i
swap f[r] f[i]
.
# make it solvable
inv = 0
for i = 1 to 15
for j = 1 to i - 1
if f[j] > f[i]
inv += 1
.
.
.
if inv mod 2 <> 0
.
if inv mod 2 <>swap 0f[1] f[2]
.
swap f[1] f[2]
textsize 12
.
draw
textsize 12
call draw
.
funcproc move_tile . .
c = mouse_x div 25
r = mouse_y div 25
i = r * 4 + c + 1
if c > 0 and f[i - 1] = 16
swap f[i] f[i - 1]
elif r > 0 and f[i - 4] = 16
swap f[i] f[i - 4]
elif r < 3 and f[i + 4] = 16
swap f[i] f[i + 4]
elif c < 3 and f[i + 1] = 16
swap f[i] f[i + 1]
.
call draw
done for i = 1 to 15
for if f[i] => 1f[i to+ 151]
if f[i] > f[i + 1]return
done = 0.
.
done = 1
.
if donetimer = 10.5
clear
move 10 30
text "Well done!"
.
.
on mouse_down
if done = 10
call init move_tile
elif done = 3
else
call move_tile init
.
.
on timer
call init</syntaxhighlight>
if done = 1
smiley
done = 2
timer 2
else
done = 3
.
.
init
</syntaxhighlight>
 
=={{header|F_Sharp|F#}}==
Line 5,173 ⟶ 5,770:
print
drawboard B()</syntaxhighlight>
 
 
 
=={{header|FutureBasic}}==
<syntaxhighlight lang="FutureBasic">
// 15 Puzzle // 26 september 2023 //
 
begin globals
CFMutableStringRef board : board = fn MutableStringNew
end globals
 
 
void local fn buildUI
Long i, j, k = 1 // k is button number
window 1, @"15 Puzzle", ( 0, 0, 200, 200 ), 3
for j = 3 to 0 step -1 : for i = 0 to 3 // Top to bottom, left to right
button k, Yes, 1, @"", ( 20 + 40 * i, 20 + 40 * j , 40, 40 ), , NSBezelStyleShadowlessSquare
ControlSetFont(k, fn FontSystemFontOfSize( 21 ) )
ControlSetAlignment( k, NSTextAlignmentCenter )
k ++
next : next
menu 1, , 1, @"File": menu 1, 1, , @"Close", @"w" : MenuItemSetAction( 1, 1, @"performClose:" )
editmenu 2 : menu 2, 0, No : menu 3, , , @"Level"
for i = 1 to 8 : menu 3, i, , str( i ) : next
MenuSetOneItemOnState( 3, 3 )
end fn
 
 
void local fn newGame
CFStringRef s
Long i, m, n = 16, p = 0 // n is empty starting tile, p holds previous move
Bool ok
MutableStringSetString (board, @" 123456789ABCDEF " )
for i = 1 to fn MenuSelectedItem( 3 )^2 // Number of shuffles is square of level
do : ok = Yes
m = n + int( 2.6 * rnd( 4 ) - 6.5 ) // Choose a random move, but
if m < 1 or m > 16 or m == p then ok = No // not of bounds or previous,
if n mod 4 = 0 and m = n + 1 then ok = No // and don't exchange eg tile 4 and 5
if n mod 4 = 1 and m = n - 1 then ok = No // or 9 and 8
until ok = Yes // Found a move, swap in board string
s = mid( board, m, 1 ) : mid( board, m, 1 ) = @" " : mid( board, n, 1 ) = s
p = n : n = m
next
for i = 1 to 16 // Stamp the buttons, p is unicode of board char, s is button title
p = (Long) fn StringCharacterAtIndex( board, i )
if p > 64 then s = fn StringWithFormat ( @"%d", p - 55 ) else s = mid( board, i, 1 )
button i, Yes, 1, s
if fn StringIsEqual( s, @" ") == Yes then button i, No
next
end fn
 
 
void local fn move ( n as Long )
CFStringRef s
Long i, m, x = -1 // x is empty plot
Bool ok
for i = 1 to 4 // see if clicked button is next to empty plot
m = n + int( 2.6 * i - 6.5 ) // -4. -1, +1, +4
ok = Yes
if m < 1 or m > 16 then ok = No // Not out of bounds etc
if n mod 4 = 0 and m = n + 1 then ok = No
if n mod 4 = 1 and m = n - 1 then ok = No
if ok == Yes
if fn StringIsEqual( mid( board, m, 1 ), @" " ) then x = m
end if
next
if x > -1 // Swap places in board string and button titles
s = mid( board, n, 1 ) : mid( board, n, 1 ) = @" " : mid( board, x, 1 ) = s
button x, Yes, 1 , fn ButtonTitle( n ) : button n, No, 1, @" "
end if
if fn StringIsEqual( board, @" 123456789ABCDEF " )
alert 112, , @"Well done.", @"Another game?", @"Yes;No", Yes
end if
end fn
 
 
void local fn doMenu( mnu as Long, itm as Long )
if mnu == 3 then MenuSetOneItemOnState( 3, itm ) : fn newGame
end fn
 
 
void local fn DoDialog( evt as Long, tag as Long )
select evt
case _btnClick : fn move( tag )
case _alertDidEnd : if tag == NSAlertFirstButtonReturn then fn newGame else end
end select
end fn
 
fn buildUI
fn newGame
 
on dialog fn doDialog
on menu fn doMenu
handleevents
</syntaxhighlight>
 
[[File:FB 15.png]]
 
 
=={{header|Gambas}}==
Line 6,515 ⟶ 7,210:
Possible moves are: ["13", "12", "9"], 0 to exit. Your move? =>
</pre>
 
=={{header|Koka}}==
Imperative Version
{{trans|C}}
<syntaxhighlight lang="koka">
import std/num/random
import std/os/readline
struct board
cells: vector<vector<int>>
hole-pos: (int, int)
size: (int, int)
 
type move
MUp
MDown
MLeft
MRight
 
fun delta(move: move): (int, int)
match move
MUp -> (0, 1)
MDown -> (0, -1)
MLeft -> (1, 0)
MRight -> (-1, 0)
 
inline extern unsafe-assign : forall<a> ( v : vector<a>, i : ssize_t, x : a ) -> total ()
c "kk_vector_unsafe_assign"
 
fun update(game: board, move: move): exn board
val (dx, dy) = move.delta
val (hx, hy) = game.hole-pos
val (nx, ny) = (hx + dx, hy + dy)
val (w, h) = game.size
if nx >= 0 && nx < w && ny >= 0 && ny < h then
game.cells[hx].unsafe-assign(hy.ssize_t, game.cells[nx][ny])
game.cells[nx].unsafe-assign(ny.ssize_t, 0)
game(hole-pos=(nx, ny))
else
game
 
val num_shuffles = 100
 
fun random-move(): random move
match random-int() % 4
0 -> MUp
1 -> MDown
2 -> MLeft
_ -> MRight
 
fun setup(size: (int, int)): <exn,random> board
val (w, h) = size
val cells = vector-init(w, fn(x) vector-init(h, fn(y) x*h + y + 1))
var game := Board(cells, (w - 1, h - 1), size)
for(0,num_shuffles) fn(_)
game := game.update(random-move())
game
 
effect break<a>
final ctl break(a: a) : b
 
fun finished(game: board): exn bool
val (w, h) = game.size
var i := 1
with final ctl break(a:bool)
a
for(0,w - 1) fn(x)
for(0,h - 1) fn(y)
if game.cells[x][y] != i then
break(False)
else
i := i + 1
True
 
fun display(game: board): <console,exn> ()
println("")
val (w, h) = game.size
for(0, h - 1) fn(y)
for(0, w - 1) fn(x)
val c = game.cells[x][y]
if c == 0 then
print(" ")
else
print(" " ++ c.show ++ " ")
println("")
println("")
 
fun get_move(): <div,console,exn,break<string>> move
val c = readline()
match c.trim()
"w" -> MUp
"s" -> MDown
"a" -> MLeft
"d" -> MRight
"q" -> break("Finished")
_ -> get_move()
 
fun main()
var game := setup((4, 4))
with final ctl break(a:string)
a.println
while {!game.finished}
game.display
val move = get_move()
game := game.update(move)
println("You won!")
</syntaxhighlight>
 
=={{header|Kotlin}}==
Line 7,324 ⟶ 8,125:
Seed = time(NULL);
").</syntaxhighlight>
 
=={{header|MiniScript}}==
===Text-based version===
Text-based game that works with both command-line and [http://miniscript.org/MiniMicro Mini Micro] versions of MiniScript. The Mini Micro has animation showing the changes in the board when the tiles are being shuffled or a move is made.
<syntaxhighlight lang="miniscript">
isMiniMicro = version.hostName == "Mini Micro"
 
// These coordinates are [row,col] not [x,y]
Directions = {"up": [-1,0], "right": [0,1], "down": [1, 0], "left": [0,-1]}
TileNum = range(1, 15)
Puzzle15 = {"grid":[[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]],
"blankPos": [3,3]}
 
Puzzle15.__setTile = function(position, value)
row = position[0]; col = position[1]
self.grid[row][col] = value
end function
 
Puzzle15.__getTile = function(position)
row = position[0]; col = position[1]
return self.grid[row][col]
end function
 
Puzzle15.__getOppositeDirection = function(direction)
directions = Directions.indexes
oppix = (directions.indexOf(direction) + 2) % 4
return directions[oppix]
end function
 
Puzzle15.getState = function
return self.grid
end function
 
Puzzle15.getBlankPos = function
return self.blankPos
end function
 
Puzzle15.hasWon = function
count = 1
for r in range(0, 3)
for c in range(0, 3)
if self.grid[r][c] != count then return false
count += 1
end for
end for
return true
end function
 
Puzzle15.move = function(direction)
if not Directions.hasIndex(direction) then return false
move = Directions[direction]
curPos = self.blankPos[:]
newPos = [curPos[0] + move[0], curPos[1] + move[1]]
if (-1 < newPos[0] < 4) and (-1 < newPos[1] < 4) then
value = self.__getTile(newPos)
self.__setTile(curPos, value)
self.__setTile(newPos, 16) // 16 is the blank tile
self.blankPos = newPos
return true
else
return false
end if
end function
 
Puzzle15.shuffle = function(n)
lastMove = ""
directions = Directions.indexes
for i in range(1, 50)
while true
moveTo = directions[floor(rnd * 4)]
oppMove = self.__getOppositeDirection(moveTo)
if self.__getOppositeDirection(moveTo) != lastMove and self.move(moveTo) then
lastMove = moveTo
if isMiniMicro then
self.displayBoard
wait 1/33
end if
break
end if
end while
end for
end function
 
Puzzle15.displayBoard = function
if isMiniMicro then clear
for r in range(0, 3)
for c in range(0, 3)
grid = self.getState
if grid[r][c] == 16 then
s = " "
else
s = (" " + grid[r][c])[-3:]
end if
print s, ""
end for
print
end for
end function
 
Puzzle15.shuffle
 
while not Puzzle15.hasWon
if isMiniMicro then
clear
else
print
end if
Puzzle15.displayBoard
while true
print
move = input("Enter the direction to move the blank in (up, down, left, right): ")
move = move.lower
if Directions.hasIndex(move) and Puzzle15.move(move) then break
print "Please enter a valid move."
end while
end while
print "Congratulations! You solved the puzzle!"</syntaxhighlight>
 
===Fully animated version===
This fully animated implementation is for use with [http://miniscript.org/MiniMicro Mini Micro]. It uses assets that come with the Mini Micro as well as a sound file of wood blocks scrapping and hitting each other that is separate from this code. This scrip will still run without it and will not simulate the sound of the tiles moving. You may find this file on [https://github.com/chinhouse/MiniScript/blob/main/Puzzle-15/small_wooden_bricks_movement.mp3 Github].
<syntaxhighlight lang="miniscript">
woodSound = file.loadSound("small_wooden_bricks_movement.mp3")
puzzleTiles = function
gfx.scale = 2
woodImg = file.loadImage("/sys/pics/textures/Wood.png")
gfx.drawImage woodImg,0,0
gfx.color = color.black
gfx.drawRect 6,6, 244,244
bgBoard = new Sprite
bgBoard.image = gfx.getImage(0, 0, 256, 256)
bgBoard.scale = 1.6
bgBoard.x = (960 - 1.6 * 256) / 2 + 128 * 1.6
bgBoard.y = (640 - 1.6 * 256) / 2 + 128 * 1.6
bgBoard.tint = color.rgb(102,51,0)
sprites = [bgBoard]
gfx.clear
gfx.drawImage woodImg,0,0
positions = range(1,15)
positions.shuffle
spriteScale = 1.5
spriteSize = 64
tileXOffset = (960 - 3 * spriteSize * spriteScale) / 2
tileYOffset = (640 - 3 * spriteSize * spriteScale) / 2
for i in range(0,14)
s = str(i+1)
pos = positions[i]
x = pos % 4
y = floor(pos / 4)
xp = x * spriteSize + (spriteSize - (s.len * 14 + 2)) / 2
yp = y * spriteSize + 20
gfx.print s, xp, yp, color.black, "normal"
sprite = new Sprite
sprite.image = gfx.getImage(x * spriteSize, y * spriteSize, spriteSize, spriteSize)
sprite.scale = spriteScale
xs = i % 4; ys = 3 - floor(i / 4)
sprite.x = spriteSize * (xs) * spriteScale + tileXOffset
sprite.y = spriteSize * ys * spriteScale + tileYOffset
sprite.localBounds = new Bounds
sprite.localBounds.width = spriteSize
sprite.localBounds.height = spriteSize
// tint the blocks with different shades of brown
sat = floor(rnd * 47 - 10) * 3
sprite.tint = color.rgb(153 + sat, 102 + sat, 51 + sat)
sprites.push(sprite)
end for
return sprites
end function
 
moveTiles = function(sprites, instructions, t = 6, mute = false)
direction = instructions[0]
delta = Directions[direction]
if not mute and woodSound and direction then woodSound.play 0.1
for i in range(96, 1, -t)
for tile in instructions[1:]
sprites[tile].x += delta[1] * t
sprites[tile].y += -delta[0] * t
end for
wait 1/3200
end for
end function
// These coordinates are [row,col] not [x,y]
Directions = {"up": [-1,0], "right": [0,1], "down": [1, 0], "left": [0,-1]}
TileNum = range(1, 15)
Puzzle15 = {"grid":[[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]],
"blankPos": [3,3], "movesToShuffled": [], "movesMade": [], "moveCount": 0}
 
Puzzle15.__setTile = function(position, value)
row = position[0]; col = position[1]
self.grid[row][col] = value
end function
 
Puzzle15.__getTile = function(position)
row = position[0]; col = position[1]
return self.grid[row][col]
end function
 
Puzzle15.__getOppositeDirection = function(direction)
directions = Directions.indexes
oppix = (directions.indexOf(direction) + 2) % 4
return directions[oppix]
end function
 
Puzzle15.__getDirectionToTile = function(n)
for row in range(0, 3)
for col in range(0, 3)
if self.grid[row][col] == n then
dr = row - self.getBlankPos[0]
dc = col - self.getBlankPos[1]
return Directions.indexOf([sign(dr), sign(dc)])
end if
end for
end for
return null
end function
 
Puzzle15.getState = function
return self.grid
end function
 
Puzzle15.getBlankPos = function
return self.blankPos
end function
 
Puzzle15.hasWon = function
count = 1
for r in range(0, 3)
for c in range(0, 3)
if self.grid[r][c] != count then return false
count += 1
end for
end for
return true
end function
 
Puzzle15.move = function(direction)
if not Directions.hasIndex(direction) then return false
move = Directions[direction]
curPos = self.blankPos[:]
newPos = [curPos[0] + move[0], curPos[1] + move[1]]
if (-1 < newPos[0] < 4) and (-1 < newPos[1] < 4) then
value = self.__getTile(newPos)
self.__setTile(curPos, value)
self.__setTile(newPos, 16) // 16 is the blank tile
self.blankPos = newPos
if self.movesMade.len > 0 then
lastMove = self.movesMade[-1]
else
lastMove = ""
end if
if lastMove != "" and self.__getOppositeDirection(lastMove) == direction then
self.movesMade.pop
else
self.movesMade.push(direction)
end if
self.moveCount += 1
return value // return tile that was moved
else
return false
end if
end function
 
Puzzle15.moveNumber = function(n)
direction = Puzzle15.__getDirectionToTile(n)
origDir = direction
if direction == null then return 0
tiles = [self.__getOppositeDirection(direction)]
while origDir == direction
tileNum = self.move(origDir)
tiles.insert(1, tileNum)
direction = self.__getDirectionToTile(n)
end while
return tiles
end function
 
Puzzle15.shuffle = function(n, sprites)
lastMove = ""
directions = Directions.indexes
cnt = 0
instructions = []
while self.movesToShuffled.len < n
if self.movesToShuffled.len == 0 then
lastMove = ""
else
lastMove = self.movesToShuffled[-1]
end if
moveTo = directions[floor(rnd * 4)]
cnt += 1
oppMove = self.__getOppositeDirection(moveTo)
tileMoved = self.move(moveTo)
if oppMove != lastMove and tileMoved then
instructions.push([oppMove, tileMoved])
lastMove = moveTo
self.movesToShuffled.push(moveTo)
else if oppMove == lastMove then
self.movesToShuffled.pop
instructions.pop
end if
end while
for i in instructions
moveTiles(sprites, i, 96, true)
end for
end function
 
clear
display(4).sprites = puzzleTiles
gfx.clear
Puzzle15.shuffle(200, display(4).sprites)
 
while not Puzzle15.hasWon
if mouse.button and not wasPressed then
tile = 16
for i in range(1, 15)
sprite = display(4).sprites[i]
//print sprite.localBounds
if sprite.contains(mouse) then tile = i
end for
if tile != 16 then
instructions = Puzzle15.moveNumber(tile)
if instructions then moveTiles(display(4).sprites, instructions)
end if
end if
wasPressed = mouse.button
yield
end while
fanfare = file.loadSound("/sys/sounds/fanfare.wav")
fanfare.play 0.25
while fanfare.isPlaying
end while
key.get
</syntaxhighlight>
 
=={{header|MUMPS}}==
Line 8,207 ⟶ 9,350:
=== console only ===
Kept simple. Obviously, increase the 5 random moves for more of a challenge.
<!--(phixonline)-->
<!--<syntaxhighlight lang="phix">-->
<syntaxhighlight lang="phix">
<span style="color: #008080;">constant</span> <span style="color: #000000;">ESC<span style="color: #0000FF;">=<span style="color: #000000;">27<span style="color: #0000FF;">,</span> <span style="color: #000000;">UP<span style="color: #0000FF;">=<span style="color: #000000;">328<span style="color: #0000FF;">,</span> <span style="color: #000000;">LEFT<span style="color: #0000FF;">=<span style="color: #000000;">331<span style="color: #0000FF;">,</span> <span style="color: #000000;">RIGHT<span style="color: #0000FF;">=<span style="color: #000000;">333<span style="color: #0000FF;">,</span> <span style="color: #000000;">DOWN<span style="color: #0000FF;">=<span style="color: #000000;">336</span>
constant ESC=27, UP=328, LEFT=331, RIGHT=333, DOWN=336
<span style="color: #004080;">sequence</span> <span style="color: #000000;">board</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">tagset<span style="color: #0000FF;">(<span style="color: #000000;">15<span style="color: #0000FF;">)<span style="color: #0000FF;">&<span style="color: #000000;">0<span style="color: #0000FF;">,</span> <span style="color: #000000;">solve</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">board</span>
sequence board = tagset(15)&0, solve = board
<span style="color: #004080;">integer</span> <span style="color: #000000;">pos</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">16</span>
integer pos = 16
<span style="color: #008080;">procedure</span> <span style="color: #000000;">print_board<span style="color: #0000FF;">(<span style="color: #0000FF;">)</span>
procedure print_board()
<span style="color: #008080;">for</span> <span style="color: #000000;">i<span style="color: #0000FF;">=<span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length<span style="color: #0000FF;">(<span style="color: #000000;">board<span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
for i=1 to length(board) do
<span style="color: #7060A8;">puts<span style="color: #0000FF;">(<span style="color: #000000;">1<span style="color: #0000FF;">,<span style="color: #008080;">iff<span style="color: #0000FF;">(<span style="color: #000000;">i<span style="color: #0000FF;">=<span style="color: #000000;">pos<span style="color: #0000FF;">?<span style="color: #008000;">" "<span style="color: #0000FF;">:<span style="color: #7060A8;">sprintf<span style="color: #0000FF;">(<span style="color: #008000;">"%3d"<span style="color: #0000FF;">,<span style="color: #0000FF;">{<span style="color: #000000;">board<span style="color: #0000FF;">[<span style="color: #000000;">i<span style="color: #0000FF;">]<span style="color: #0000FF;">}<span style="color: #0000FF;">)<span style="color: #0000FF;">)<span style="color: #0000FF;">)</span>
puts(1,iff(i=pos?" ":sprintf("%3d",{board[i]})))
<span style="color: #008080;">if</span> <span style="color: #7060A8;">mod<span style="color: #0000FF;">(<span style="color: #000000;">i<span style="color: #0000FF;">,<span style="color: #000000;">4<span style="color: #0000FF;">)<span style="color: #0000FF;">=<span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #7060A8;">puts<span style="color: #0000FF;">(<span style="color: #000000;">1<span style="color: #0000FF;">,<span style="color: #008000;">"\n"<span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if mod(i,4)=0 then puts(1,"\n") end if
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end for
<span style="color: #7060A8;">puts<span style="color: #0000FF;">(<span style="color: #000000;">1<span style="color: #0000FF;">,<span style="color: #008000;">"\n"<span style="color: #0000FF;">)</span>
puts(1,"\n")
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
end procedure
<span style="color: #008080;">procedure</span> <span style="color: #000000;">move<span style="color: #0000FF;">(<span style="color: #004080;">integer</span> <span style="color: #000000;">d<span style="color: #0000FF;">)</span>
procedure move(integer d)
<span style="color: #004080;">integer</span> <span style="color: #000000;">new_pos</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">pos<span style="color: #0000FF;">+<span style="color: #0000FF;">{<span style="color: #0000FF;">+<span style="color: #000000;">4<span style="color: #0000FF;">,<span style="color: #0000FF;">+<span style="color: #000000;">1<span style="color: #0000FF;">,<span style="color: #0000FF;">-<span style="color: #000000;">1<span style="color: #0000FF;">,<span style="color: #0000FF;">-<span style="color: #000000;">4<span style="color: #0000FF;">}<span style="color: #0000FF;">[<span style="color: #000000;">d<span style="color: #0000FF;">]</span>
integer new_pos = pos+{+4,+1,-1,-4}[d]
<span style="color: #008080;">if</span> <span style="color: #000000;">new_pos<span style="color: #0000FF;">>=<span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">new_pos<span style="color: #0000FF;"><=<span style="color: #000000;">16</span>
if new_pos>=1 and new_pos<=16
<span style="color: #008080;">and</span> <span style="color: #0000FF;">(<span style="color: #7060A8;">mod<span style="color: #0000FF;">(<span style="color: #000000;">pos<span style="color: #0000FF;">,<span style="color: #000000;">4<span style="color: #0000FF;">)<span style="color: #0000FF;">=<span style="color: #7060A8;">mod<span style="color: #0000FF;">(<span style="color: #000000;">new_pos<span style="color: #0000FF;">,<span style="color: #000000;">4<span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- same col, or row:</span>
and (mod(pos,4)=mod(new_pos,4) -- same col, or row:
<span style="color: #008080;">or</span> <span style="color: #7060A8;">floor<span style="color: #0000FF;">(<span style="color: #0000FF;">(<span style="color: #000000;">pos<span style="color: #0000FF;">-<span style="color: #000000;">1<span style="color: #0000FF;">)<span style="color: #0000FF;">/<span style="color: #000000;">4<span style="color: #0000FF;">)<span style="color: #0000FF;">=<span style="color: #7060A8;">floor<span style="color: #0000FF;">(<span style="color: #0000FF;">(<span style="color: #000000;">new_pos<span style="color: #0000FF;">-<span style="color: #000000;">1<span style="color: #0000FF;">)<span style="color: #0000FF;">/<span style="color: #000000;">4<span style="color: #0000FF;">)<span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
or floor((pos-1)/4)=floor((new_pos-1)/4)) then
<span style="color: #0000FF;">{<span style="color: #000000;">board<span style="color: #0000FF;">[<span style="color: #000000;">pos<span style="color: #0000FF;">]<span style="color: #0000FF;">,<span style="color: #000000;">board<span style="color: #0000FF;">[<span style="color: #000000;">new_pos<span style="color: #0000FF;">]<span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{<span style="color: #000000;">board<span style="color: #0000FF;">[<span style="color: #000000;">new_pos<span style="color: #0000FF;">]<span style="color: #0000FF;">,<span style="color: #000000;">0<span style="color: #0000FF;">}</span>
{board[pos],board[new_pos]} = {board[new_pos],0}
<span style="color: #000000;">pos</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">new_pos</span>
pos = new_pos
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
end procedure
<span style="color: #008080;">for</span> <span style="color: #000000;">i<span style="color: #0000FF;">=<span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">5</span> <span style="color: #008080;">do</span> <span style="color: #000000;">move<span style="color: #0000FF;">(<span style="color: #7060A8;">rand<span style="color: #0000FF;">(<span style="color: #000000;">4<span style="color: #0000FF;">)<span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
for i=1 to 5 do move(rand(4)) end for
<span style="color: #008080;">while</span> <span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
while 1 do
<span style="color: #000000;">print_board<span style="color: #0000FF;">(<span style="color: #0000FF;">)</span>
print_board()
<span style="color: #008080;">if</span> <span style="color: #000000;">board<span style="color: #0000FF;">=<span style="color: #000000;">solve</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if board=solve then exit end if
<span style="color: #004080;">integer</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find<span style="color: #0000FF;">(<span style="color: #7060A8;">wait_key<span style="color: #0000FF;">(<span style="color: #0000FF;">)<span style="color: #0000FF;">,<span style="color: #0000FF;">{<span style="color: #000000;">ESC<span style="color: #0000FF;">,<span style="color: #000000;">UP<span style="color: #0000FF;">,<span style="color: #000000;">LEFT<span style="color: #0000FF;">,<span style="color: #000000;">RIGHT<span style="color: #0000FF;">,<span style="color: #000000;">DOWN<span style="color: #0000FF;">}<span style="color: #0000FF;">)<span style="color: #0000FF;">-<span style="color: #000000;">1</span>
integer c = find(wait_key(),{ESC,UP,LEFT,RIGHT,DOWN})-1
<span style="color: #008080;">if</span> <span style="color: #000000;">c<span style="color: #0000FF;">=<span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if c=0 then exit end if
<span style="color: #000000;">move<span style="color: #0000FF;">(<span style="color: #000000;">c<span style="color: #0000FF;">)</span>
move(c)
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
end while
<span style="color: #7060A8;">puts<span style="color: #0000FF;">(<span style="color: #000000;">1<span style="color: #0000FF;">,<span style="color: #008000;">"solved!\n"<span style="color: #0000FF;">)
puts(1,"solved!\n")
<!--</syntaxhighlight>-->
</syntaxhighlight>
{{out}}
<pre>
Line 8,269 ⟶ 9,413:
solved!
</pre>
 
=== GUI version ===
{{libheader|Phix/pGUI}}
Line 9,196 ⟶ 10,341:
line(self.x + 2, self.y + 1, self.x +
piece_side_length - 1, self.y + 1)</syntaxhighlight>
 
 
=={{header|Prolog}}==
Works with SWI-Prolog
<syntaxhighlight lang="prolog">
% map the sequence of cells
next_cell(1,Y,2,Y).
next_cell(2,Y,3,Y).
next_cell(3,Y,4,Y).
next_cell(4,1,1,2).
next_cell(4,2,1,3).
next_cell(4,3,1,4).
 
% map the game items, and how to print
item(1,2, ' 1 ').
item(2,3, ' 2 ').
item(3,4, ' 3 ').
item(4,5, ' 4 ').
item(5,6, ' 5 ').
item(6,7, ' 6 ').
item(7,8, ' 7 ').
item(8,9, ' 8 ').
item(9,10, ' 9 ').
item(10,11, ' 10 ').
item(11,12, ' 11 ').
item(12,13, ' 12 ').
item(13,14, ' 13 ').
item(14,15, ' 14 ').
item(15,0, ' 15 ').
 
% Move - find the current blank space, and the new place and swap them
move_1(1,2).
move_1(2,3).
move_1(3,4).
 
move(up, X, Y, X, Y1) :- move_1(Y1,Y).
move(down, X, Y, X, Y1) :- move_1(Y, Y1).
move(left, X, Y, X1, Y) :- move_1(X1, X).
move(right, X, Y, X1, Y) :- move_1(X, X1).
 
move(Dir, Board, [p(X1,Y1,0),p(X,Y,P)|B2]) :-
select(p(X, Y, 0), Board, B1),
move(Dir, X,Y,X1,Y1),
select(p(X1, Y1, P), B1, B2).
 
% Solved - the game is solved if running through the next_cell sequence produces the item sequence.
solved(Board) :-
select(p(1,1,1),Board,Remaining),
solved(Remaining,p(1,1,1)).
solved([p(4,4,0)], p(_,_,15)).
solved(Board,p(Xp,Yp,Prev)) :-
item(Prev,P,_),
select(p(X,Y,P),Board,Remaining),
next_cell(Xp,Yp,X,Y),
solved(Remaining, p(X,Y,P)).
 
% Print - run through the next_cell sequence printing the found items.
print(Board) :-
select(p(1,1,P),Board,Remaining),
nl, write_cell(P),
print(Remaining,p(1,1)).
print([],_) :- nl.
print(Board,p(X,Y)) :-
next_cell(X,Y,X1,Y1),
select(p(X1,Y1,P),Board,Remaining),
write_cell(P),
end_line_or_not(X1),
print(Remaining,p(X1,Y1)).
 
write_cell(0) :- write(' ').
write_cell(P) :- item(P,_,W), write(W).
 
end_line_or_not(1).
end_line_or_not(2).
end_line_or_not(3).
end_line_or_not(4) :- nl.
 
% Next Move - get the player input.
next_move_by_player(Move) :-
repeat,
get_single_char(Char),
key_move(Char, Move).
 
key_move(119, up). % 'w'
key_move(115, down). % 'd'
key_move(97, left). % 'a'
key_move(100, right). % 'd'
 
% Play - loop over the player moves until solved.
play(Board) :-
solved(Board) -> (
print(Board),
write('You Win!\n'))
; (
print(Board),
next_move_by_player(Move),
move(Move, Board, NewBoard),
play(NewBoard)).
 
play :-
test_board(Board),
play(Board),
!.
test_board(
[p(1,1,9),p(2,1,1),p(3,1,4),p(4,1,7),
p(1,2,6),p(2,2,5),p(3,2,3),p(4,2,2),
p(1,3,13),p(2,3,10),p(3,3,0),p(4,3,8),
p(1,4,14),p(2,4,15),p(3,4,11),p(4,4,12)]).
</syntaxhighlight>
 
=={{header|PureBasic}}==
Line 11,166 ⟶ 12,421:
 
[https://youtu.be/IZqpYctv8Zs CalmoSoft Fifteen Puzzle Game in Ring - video]
 
=== newer version ===
This was added, out of place, 3rd November 2023, but dated a year earlier than the one last updated 29th September 2021...
<syntaxhighlight lang="ring">
/*
**
** Game : CalmoSoft Fifteen Puzzle Game 3D
** Date : 2017/09/01
** Author : CalmoSoft <calmosoft@gmail.com>, Mahmoud Fayed
**
*/
 
# 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
 
</syntaxhighlight>
[https://youtu.be/xvhNKTZKi8U CalmoSoft Fifteen Puzzle Game in 3D]
 
=={{header|Ruby}}==
Line 11,457 ⟶ 13,171:
=={{header|Rust}}==
{{libheader|rand}}
<syntaxhighlight lang="rust">extern crate rand;
extern crate rand;
 
use clearscreen::clear;
use std::collections::HashMap;
use std::fmt;
use std::io::{self, Write};
 
use rand::seq::SliceRandom;
Line 11,528 ⟶ 13,244:
let pos = board
.iter()
.position(|&cell| match matches!(cell, Cell::Card(value) if value == {i))
Cell::Card(value) if value == i => true,
_ => false,
})
.unwrap();
 
Line 11,608 ⟶ 13,321:
for turns in 1.. {
println!("{p15}");
match ask_action(&p15.get_moves(), true) {
Action::Move(direction) => {
p15.play(&direction);
print!clear().expect("\x1B[2J\x1B[1;1Hfailed to clear screen");
}
Action::Quit => {
print!clear().expect("\x1B[2J\x1B[1;1Hfailed to clear screen");
 
println!("Bye !");
break;
}
Line 11,622 ⟶ 13,335:
 
if p15.is_complete() {
println!("Well done ! You won in {turns} turns");
break;
}
Line 11,628 ⟶ 13,341:
}
 
fn ask_action(moves: &HashMap<Direction, Cell>, render_list: bool) -> Action {
use std::io::{self, Write};
use Action::*;
use Direction::*;
 
if render_list {
println!("Possible moves:");
println!("Possible moves:");
 
if let Some(&Cell::Card(value)) = moves.get(&Up) {
println!("\tU) {value}");
}
if let Some(&Cell::Card(value)) = moves.get(&Left) {
println!("\tL) {value}");
}
if let Some(&Cell::Card(value)) = moves.get(&Right) {
println!("\tR) {value}");
}
if let Some(&Cell::Card(value)) = moves.get(&Down) {
println!("\tD) {value}");
}
println!("\tQ) Quit");
print!("Choose your move: ");
io::stdout().flush().unwrap();
} else {
print!("Unknown move, try again: ");
io::stdout().flush().unwrap();
}
if let Some(&Cell::Card(value)) = moves.get(&Down) {
println!("\tD) {value}");
}
println!("\tQ) Quit");
print!("Choose your move : ");
io::stdout().flush().unwrap();
 
let mut action = String::new();
Line 11,660 ⟶ 13,377:
"Q" => Quit,
_ => {
println!if unknown_action("Unknown action:) {action}");
ask_action(moves, true)
} else {
ask_action(moves, false)
}
}
}
}
}</syntaxhighlight>
 
fn unknown_action() -> bool {
use crossterm::{
cursor::MoveToPreviousLine,
terminal::{Clear, ClearType},
ExecutableCommand,
};
std::io::stdout().execute(MoveToPreviousLine(1)).unwrap();
std::io::stdout()
.execute(Clear(ClearType::CurrentLine))
.unwrap();
false
}
 
</syntaxhighlight>
 
=={{header|Scala}}==
Line 14,152 ⟶ 15,887:
{{libheader|Wren-ioutil}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="ecmascriptwren">import "random" for Random
import "./dynamic" for Enum
import "./ioutil" for Input
import "./fmt" for Fmt
 
var Move = Enum.create("Move", ["up", "down", "right", "left"])
1,973

edits