Movatterモバイル変換


[0]ホーム

URL:


Jump to content
Rosetta Code
Search

16 puzzle game

From Rosetta Code
16 puzzle game is adraft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in itstalk page.

16 numbered pieces of the puzzle are placed out of order on a 4 X 4 grid. The correct order to win is to order the piecesas 1 through 16, read left to right, top to bottom:

  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16

How to Play: The aim is to get the pieces back in order by clicking on the yellow arrows (choosing a location to rotate a row or column) to slide the pieces left or right, up or down.

  1 14  3  4          1  2  3  4  5  2  7  8   -->    5  6  7  8  9  6 11 12          9 10 11 12 13 10 15 16         13 14 15 16     ^

The Easy puzzle target is 3 moves, for the Hard puzzle it is 12 moves (or less!). Can it be that simple?

Task

Create 16 Puzzle Game.


See details:[1]


Video:16 Puzzle Game


Related task



AutoHotkey

With Solver, See16_puzzle_game/autohotkey

FreeBASIC

Translation of:Wren
Consteasy=1,hard=4DimSharedAsByten(1To16)SubinitGrid()ForiAsByte=0To15n(i)=i+1NextEndSubSubrotate(ix()AsByte)DimAsBytelast=n(ix(3))ForiAsByte=3To1Step-1n(ix(i))=n(ix(i-1))Nextn(ix(0))=lastEndSubFunctionhasWon()AsBooleanForiAsByte=0To15Ifn(i)<>i+1ThenReturnFalseNextReturnTrueEndFunctionSubsetDiff(levelAsByte)DimAsBytemoves=Iif(level=easy,3,12)DimAsByterc(),j,iFori=0TomovesRedimAsByterc(20)DimAsByter=Int(Rnd*2)DimAsBytes=Int(Rnd*4)Ifr=0Then' rotate random rowForj=s*4To(s+1)*4rc(j)=jNextElse' rotate random columnForj=sTos+16Step4rc(j)=jNextEndIfrotate(rc())IfhasWon()Then' do it againi=-1EndIfi+=1NextPrintUsing!"\nTarget is ## moves.";movesEndSubSubdrawGrid()Print!"\n     D1   D2   D3   D4"Print"   +-------------------+"PrintUsing"R1 | ## | ## | ## | ## | L1";n(0);n(1);n(2);n(3)Print"   |----+----+----+----|"PrintUsing"R2 | ## | ## | ## | ## | L2";n(4);n(5);n(6);n(7)Print"   |----+----+----+----|"PrintUsing"R3 | ## | ## | ## | ## | L3";n(8);n(9);n(10);n(11)Print"   |----+----+----+----|"PrintUsing"R4 | ## | ## | ## | ## | L4";n(12);n(13);n(14);n(15)Print"   +-------------------+"Print!"      U1   U2   U3   U4\n"EndSub'--- Programa Principal ---RandomizeTimerDimAsBytelevel=easyDimAsStringdiffPrint"Enter difficulty level easy or hard E/H: ";DoInput;"",diffLoopUntilInstr("eEhH",diff)IfUcase(diff)="H"Thenlevel=hardClsPrint"Sixteen Puzzle"initGrid()setDiff(level)DimAsByteix(0To3)Print"When entering moves, you can also enter Q to quit or S to start again."DimAsBytec,moves=0DimAsString*2moveDodrawGrid()IfhasWon()ThenPrint"Congratulations, you have won the game in";moves;" moves!!"WhileInkey="":WendExitDoEndIfDoPrint"Moves so far = ";movesInput"Enter move : ",moveSelectCaseTrim(Ucase(move))Case"D1","D2","D3","D4"c=Cint(Right(move,1))-49ix(0)=0+cix(1)=4+cix(2)=8+cix(3)=12+crotate(ix())moves+=1ExitDoCase"L1","L2","L3","L4"c=Cint(Right(move,1))-49ix(0)=3+4*cix(1)=2+4*cix(2)=1+4*cix(3)=0+4*crotate(ix())moves+=1ExitDoCase"U1","U2","U3","U4"c=Cint(Right(move,1))-49ix(0)=12+cix(1)=8+cix(2)=4+cix(3)=0+crotate(ix())moves+=1ExitDoCase"R1","R2","R3","R4"c=Cint(Right(move,1))-49ix(0)=0+4*cix(1)=1+4*cix(2)=2+4*cix(3)=3+4*crotate(ix())moves+=1ExitDoCase"Q"ExitDo,DoCase"S"ClsinitGrid()setDiff(level)moves=0ExitDoCaseElsePrint"Invalid move, try again."EndSelectLoopLoop'--------------------------Sleep

FutureBasic

begin enum  _down = 1  _right  _up  _left  _new  = 100  _restrt  _help  _endend enumstr63 board, startPos, winBoardvoid local fn init  window 1,,(0,0,340,340)  int x  for x = 1 to 4    button 10+x,,,@"⬇️",(x*50+20,270,50,50),,NSBezelStyleTexturedSquare    ControlSetFontWithName( 10+x, @"Menlo", 32 )    button 30+x,,,@"⬆️",(x*50+20, 20,50,50),,NSBezelStyleTexturedSquare    ControlSetFontWithName( 30+x, @"Menlo", 32 )    button 25-x,,,@"➡️",( 20,x*50+20,50,50),,NSBezelStyleTexturedSquare    ControlSetFontWithName( 25-x, @"Menlo", 32 )    button 45-x,,,@"⬅️",(270,x*50+20,50,50),,NSBezelStyleTexturedSquare    ControlSetFontWithName( 45-x, @"Menlo", 32 )  next  button _new   ,,,@"New",   ( 20,270,50,50),,NSBezelStyleTexturedSquare  button _end   ,,,@"Quit",  ( 20, 20,50,50),,NSBezelStyleTexturedSquare  button _restrt,,,@"Redo",  (270,270,50,50),,NSBezelStyleTexturedSquare  button _help  ,,,@"Help",  (270, 20,50,50),,NSBezelStyleTexturedSquare  for x = 1 to 16    winBoard += chr$(x)  next  board = winBoardend fnvoid local fn drawBoard  int c = 1, x, y, z  cls  for y = 70 to 220 step 50    for x = 70 to 220 step 50      rect fill (x,y,48,48), fn coloryellow      if board[c] > 9 then z = x-3 else z = x+6      print %(z,y+6) str(board[c]);      c++    next  nextend fnvoid local fn move( tag as int )  int r, d, rc = (tag mod 10)  select tag / 10    case _up    : d = +4            case _right : d = -1 : rc *= 4         case _down  : d = -4 : rc += 12        case else   : d = +1 : rc  = rc * 4 - 3   end select  for r = rc to rc + 2 * d step d    swap board[r], board[r+d]  next  if board == winBoard then window 1, @"!!! YOU WON !!!" : text,,fn colorRed  fn drawBoardend fnvoid local fn newGame  window 1, @"16 PUZZLE GAME"  int r  for r = 1 to 16    swap board[r], board[rnd(16)]  next  startPos = board  text @"Arial bold", 32, fn colorblue  fn drawBoardend fnvoid local fn ask( tag as long )  CFStringRef s1, s2 : int btn  select tag    case _help      s1  = @"Use the arrow buttons to move numbers in rows and columns.\n¬      Win by arranging the numbers in order, left to right, top to bottom:"      s2  = @" 1   2   3   4 \n 5   6   7   8 \n 9  10  11  12\n 13 14 15 16"      btn = alert 1, NSAlertStyleInformational, s1, s2, @"Okay"    case _new : if board == winBoard then fn newGame : exit fn      s1  = @"Leave this puzzle\nand start a new one?"      btn = alert 1, NSAlertStyleInformational, s1,,@"New puzzle;Cancel"      if btn == NSAlertFirstButtonReturn then fn newGame    case _restrt      s1  = @"Restart this puzzle\nfrom the beginning?"      btn = alert 1, NSAlertStyleInformational,s1,,@"Restart;Cancel"      if btn == NSAlertFirstButtonReturn then board = startPos : fn drawBoard    case _end      btn = alert 1, NSAlertStyleInformational,@"Quit 16 GAME?",,@"Quit;Cancel"      if btn == NSAlertFirstButtonReturn then end  end selectend fnvoid local fn doDialog(ev as long, tag as long)  select ev    case _btnClick : if tag < _new then fn move( tag ) else fn ask( tag )    case _windowWillClose : end  end selectend fnon dialog fn doDialogfn initfn newGamehandleevents
Output:

Go

packagemainimport("bufio""fmt""log""math/rand""os""strings""time")const(easy=1hard=4)varn[16]intfuncinitGrid(){fori:=0;i<16;i++{n[i]=i+1}}funcsetDiff(levelint){moves:=3iflevel==hard{moves=12}rc:=make([]int,0,4)fori:=0;i<moves;i++{rc=rc[:0]r:=rand.Intn(2)s:=rand.Intn(4)ifr==0{// rotate random rowforj:=s*4;j<(s+1)*4;j++{rc=append(rc,j)}}else{// rotate random columnforj:=s;j<s+16;j+=4{rc=append(rc,j)}}varrca[4]intcopy(rca[:],rc)rotate(rca)ifhasWon(){// do it againi=-1}}fmt.Println("Target is",moves,"moves.")}funcdrawGrid(){fmt.Println()fmt.Println("     D1   D2   D3   D4")fmt.Println("   ╔════╦════╦════╦════╗")fmt.Printf("R1 ║ %2d ║ %2d ║ %2d ║ %2d ║ L1\n",n[0],n[1],n[2],n[3])fmt.Println("   ╠════╬════╬════╬════╣")fmt.Printf("R2 ║ %2d ║ %2d ║ %2d ║ %2d ║ L2\n",n[4],n[5],n[6],n[7])fmt.Println("   ╠════╬════╬════╬════╣")fmt.Printf("R3 ║ %2d ║ %2d ║ %2d ║ %2d ║ L3\n",n[8],n[9],n[10],n[11])fmt.Println("   ╠════╬════╬════╬════╣")fmt.Printf("R4 ║ %2d ║ %2d ║ %2d ║ %2d ║ L4\n",n[12],n[13],n[14],n[15])fmt.Println("   ╚════╩════╩════╩════╝")fmt.Println("     U1   U2   U3   U4\n")}funcrotate(ix[4]int){last:=n[ix[3]]fori:=3;i>=1;i--{n[ix[i]]=n[ix[i-1]]}n[ix[0]]=last}funchasWon()bool{fori:=0;i<16;i++{ifn[i]!=i+1{returnfalse}}returntrue}funccheck(errerror){iferr!=nil{log.Fatal(err)}}funcmain(){initGrid()rand.Seed(time.Now().UnixNano())level:=easyscanner:=bufio.NewScanner(os.Stdin)for{fmt.Print("Enter difficulty level easy or hard E/H : ")scanner.Scan()diff:=strings.ToUpper(strings.TrimSpace(scanner.Text()))ifdiff!="E"&&diff!="H"{fmt.Println("Invalid response, try again.")}else{ifdiff=="H"{level=hard}break}}check(scanner.Err())setDiff(level)varix[4]intfmt.Println("When entering moves, you can also enter Q to quit or S to start again.")moves:=0outer:for{drawGrid()ifhasWon(){fmt.Println("Congratulations, you have won the game in",moves,"moves!!")return}for{fmt.Println("Moves so far =",moves,"\n")fmt.Print("Enter move : ")scanner.Scan()move:=strings.ToUpper(strings.TrimSpace(scanner.Text()))check(scanner.Err())switchmove{case"D1","D2","D3","D4":c:=int(move[1]-49)ix[0]=0+cix[1]=4+cix[2]=8+cix[3]=12+crotate(ix)moves++continueoutercase"L1","L2","L3","L4":c:=int(move[1]-49)ix[0]=3+4*cix[1]=2+4*cix[2]=1+4*cix[3]=0+4*crotate(ix)moves++continueoutercase"U1","U2","U3","U4":c:=int(move[1]-49)ix[0]=12+cix[1]=8+cix[2]=4+cix[3]=0+crotate(ix)moves++continueoutercase"R1","R2","R3","R4":c:=int(move[1]-49)ix[0]=0+4*cix[1]=1+4*cix[2]=2+4*cix[3]=3+4*crotate(ix)moves++continueoutercase"Q":returncase"S":initGrid()setDiff(level)moves=0continueouterdefault:fmt.Println("Invalid move, try again.")}}}}
Output:

Sample game:

Enter difficulty level easy or hard E/H : eTarget is 3 moves.When entering moves, you can also enter Q to quit or S to start again.     D1   D2   D3   D4   ╔════╦════╦════╦════╗R1 ║  1 ║  2 ║  3 ║  4 ║ L1   ╠════╬════╬════╬════╣R2 ║  7 ║  8 ║  5 ║  6 ║ L2   ╠════╬════╬════╬════╣R3 ║  9 ║ 10 ║ 11 ║ 12 ║ L3   ╠════╬════╬════╬════╣R4 ║ 16 ║ 13 ║ 14 ║ 15 ║ L4   ╚════╩════╩════╩════╝     U1   U2   U3   U4Moves so far = 0 Enter move : l4     D1   D2   D3   D4   ╔════╦════╦════╦════╗R1 ║  1 ║  2 ║  3 ║  4 ║ L1   ╠════╬════╬════╬════╣R2 ║  7 ║  8 ║  5 ║  6 ║ L2   ╠════╬════╬════╬════╣R3 ║  9 ║ 10 ║ 11 ║ 12 ║ L3   ╠════╬════╬════╬════╣R4 ║ 13 ║ 14 ║ 15 ║ 16 ║ L4   ╚════╩════╩════╩════╝     U1   U2   U3   U4Moves so far = 1 Enter move : l2     D1   D2   D3   D4   ╔════╦════╦════╦════╗R1 ║  1 ║  2 ║  3 ║  4 ║ L1   ╠════╬════╬════╬════╣R2 ║  8 ║  5 ║  6 ║  7 ║ L2   ╠════╬════╬════╬════╣R3 ║  9 ║ 10 ║ 11 ║ 12 ║ L3   ╠════╬════╬════╬════╣R4 ║ 13 ║ 14 ║ 15 ║ 16 ║ L4   ╚════╩════╩════╩════╝     U1   U2   U3   U4Moves so far = 2 Enter move : l2     D1   D2   D3   D4   ╔════╦════╦════╦════╗R1 ║  1 ║  2 ║  3 ║  4 ║ L1   ╠════╬════╬════╬════╣R2 ║  5 ║  6 ║  7 ║  8 ║ L2   ╠════╬════╬════╬════╣R3 ║  9 ║ 10 ║ 11 ║ 12 ║ L3   ╠════╬════╬════╬════╣R4 ║ 13 ║ 14 ║ 15 ║ 16 ║ L4   ╚════╩════╩════╩════╝     U1   U2   U3   U4Congratulations, you have won the game in 3 moves!!

J

Assumes a recent release of jqt:

require'ide/qt/gl2'coinsert'jgl2'NB. event handlersgame_reset_button=:{{drawCOUNT=:#SETUP=:EMPTY[BOARD=:WIN}}game_restart_button=:{{drawCOUNT=:0[rotate"1SETUP[BOARD=:WIN}}game_easy_button=:{{setup3}}game_hard_button=:{{setup15}}game_board_mbldown=:{{loc=.(20+40*i.5)I.2{._".sysdataif.1=#ndx=.loc-.05do.side=.2#.<:>.loc%4NB. _2: left, _1 top, 1 bottom, 2 rightdrawrotateside,ndxend.}}NB. game logicBOARD=:WIN=:1+i.44message=:{{color=.(COUNT>#SETUP){::;:'black red'A=.'<span style="color: ',color,'">'[Z=.'</span>'if.BOARD-:WINdo.A,'You win',Zreturn.end.A,(":COUNT),Z,' of ',":#SETUP}}setup=:{{game_restart_buttonSETUP=:(_2_112{~?y#4),.1+?y#4}}rotate=:{{COUNT=:COUNT+1'side ndx'=.y-01flip=.|:if.2=|sidedo.flip=.]end.BOARD=:flip((*side)|.ndx{flipBOARD)ndx}flipBOARD}}NB. renderingwd{{)npcgamecloseok;ccboardisidraw;setboardwh200200;ccmsgstaticcenter;binh;cceasybutton;seteasytooltipstartgamewhichcanbecompletedin3moves;cchardbutton;sethardtooltipstartgamewhichcanbecompletedin15moves;binz;binh;ccrestartbutton;ccresetbutton;setresettooltipsetboardtoinitialposition,endinganycurrentgame;pshow;}}draw=:{{glclear''glbrushglrgb3#224NB. silverglrect00200200glbrushglrgb00255NB. blueglrectT=:20204040+"1]40*4411#:i.44glbrushglrgb2552550NB. yellowglpolygon(,200-])(,;"1@(_2<@|.\"1]))0300501040+"1(i.4)*/6$040gltextcolorglrgb3#255NB. whiteglfont'"lucidia console" 16'BOARD{{gltext":x[gltextxyy+50*_1^1<#":x}}"_2(30+40*44#:|:i.44)if.EMPTY-:SETUPdo.wd{{)nsetmsgtext<b>easy</b>or<b>hard</b>tostart;setrestartenable0;setrestartcaption;}}else.wd{{)nsetmsgtextMESSAGE;setrestartenable1;setrestartcaptionrestart;}}rplc'MESSAGE';message''end.glpaint''}}NB. start:game_reset_button''

JavaScript

Try ithere.

You'll also need a html file:

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <link href="https://fonts.googleapis.com/css?family=Ubuntu+Mono&display=swap" rel="stylesheet"> <link rel="stylesheet" type="text/css" media="screen" href="./css/main.css"> <title>16 Puzzle</title></head><body> <div>WELL DONE!</div> <div></div> <div></div> <button>SHUFFLE</button> <script src="./src/index.js" type="module"></script></body></html>

And css file:

* { margin: 0; border: 0; text-align: center; font-family: 'Ubuntu Mono', monospace; user-select: none;}button { border-radius: 5px; width: 300px; height: 80px; font-size: 40px; margin-top: 60px;}#board { width: 410px; height: 410px; margin: 120px auto 30px auto;}#done { font-size: 140px; padding: 20px; color: #fff; background-color: rgba(0, 23, 56, .5); border: 1px solid rgb(0, 90, 220); width: 700px; position: absolute; top: 250px; left: calc(50% - 380px);}#moves { font-size: 40px; line-height: 80px; height: 80px; width: 300px; margin: auto; border: 1px solid #000; border-radius: 5px;}.btn,.numbers,.hide { float: left; width: 64px; height: 64px; line-height: 65px; font-size: 40px; border: 1px solid black; color: black; background-color: white; cursor: none; margin: 1px; transition: all .3s;}.btn:hover { background-color: rgba(71, 231, 71, 0.5); cursor: pointer;}.hide { border: 1px solid white; cursor: none;}
classPuzzle{constructor(){this.moves;this.started;this.board=document.getElementById("board");document.getElementById("shuffle").addEventListener("click",()=>{this.shuffle();});this.reset();}reset(){while(this.board.hasChildNodes()){this.board.removeChild(this.board.firstChild);}this.moves=0;this.started=false;document.getElementById("moves").innerText=this.moves;document.getElementById("done").style.visibility="hidden";lett=1;for(lety=0;y<6;y++){for(letx=0;x<6;x++){constd=document.createElement("div");d.id=`${x}_${y}`;if(y===0||x===0||y===5||x===5){if(((y===0||y===5)&&(x===0||x===5))){d.className="hide";}else{d.className="btn";if(y===0){d.innerText="🡇";d.func=()=>{this.rollDownRight(x,true);};}elseif(y===5){d.innerText="🡅";d.func=()=>{this.rollUpLeft(x,true);};}if(x===0){d.innerText="🡆";d.func=()=>{this.rollDownRight(y,false);};}elseif(x===5){d.innerText="🡄";d.func=()=>{this.rollUpLeft(y,false);};}d.addEventListener("click",(ev)=>{ev.srcElement.func();})}}else{d.className="numbers";d.innerText=`${t}`;t++;}this.board.appendChild(d);}}document.getElementById("shuffle").innerText="SHUFFLE";}shuffle(){if(this.started){this.reset();}else{this.started=true;conste=Math.floor(Math.random()*30)+30;for(letz=0;z<e;z++){switch(Math.floor(Math.random()*4)){case0:this.rollDownRight(Math.floor(Math.random()*4)+1,false);break;case1:this.rollUpLeft(Math.floor(Math.random()*4)+1,true);break;case2:this.rollUpLeft(Math.floor(Math.random()*4)+1,false);break;case3:this.rollDownRight(Math.floor(Math.random()*4)+1,true);break;}}this.moves=0;document.getElementById("moves").innerText=this.moves;document.getElementById("shuffle").innerText="RESTART";}}getElements(l,col){constz=Array.from(document.querySelectorAll(".numbers"));for(lete=15;e>-1;e--){if(z[e].id[(col?0:2)]!=l){z.splice(e,1)}}returnz;}rollDownRight(x,col){if(!this.started)return;constz=this.getElements(x,col),a=z[3].innerText;for(letr=3;r>0;r--){z[r].innerText=z[r-1].innerText;}z[0].innerText=a;this.updateMoves();this.checkSolved();}rollUpLeft(x,col){if(!this.started)return;constz=this.getElements(x,col),a=z[0].innerText;for(letr=0;r<3;r++){z[r].innerText=z[r+1].innerText;}z[3].innerText=a;this.updateMoves();this.checkSolved();}updateMoves(){this.moves++;document.getElementById("moves").innerText=this.moves;}checkSolved(){functioncheck(){constz=document.querySelectorAll(".numbers");letu=1;for(letrofz){if(r.innerText!=u)returnfalse;u++;}returntrue;}if(this.started&&check()){document.getElementById("done").style.visibility="visible";}}}newPuzzle();

jq

Adapted fromWren

Works with jq, the C implementation of jq

Works with gojq, the Go implementation of jq (*)

The following implementation illustrates the use of "stderr"to simplify interaction with the user.

The program also illustrates the use of the MRG32k3a pseudo-randomnumber generator, a jq implementation of which which is available fromRosettaCode.org.An alternative that would probably be acceptable here wouldbe simply to use the built-in `now`.

include "MRG32k3a" {search: "."};  # see comment above### Generic functionsdef lpad($len): tostring | ($len - length) as $l | (" " * $l) + .;def inform(msg):  . as $in  | msg | stderr | $in;### The 16-Puzzle Gamedef easy: 1;def hard: 4;def drawGrid:  def row($left; $array; $right):    ([$left, ($array[] | lpad(2) ), $right] | join(" ║ ")) + "\n";  inform(    "     D1   D2   D3   D4\n"   + "   ╔════╦════╦════╦════╗\n"  +  row("R1"; .n[0:4]; "L1")  + "   ╠════╬════╬════╬════╣\n"  +  row("R2"; .n[4:8]; "L2")  + "   ╠════╬════╬════╬════╣\n"  +  row("R3"; .n[8:12];" L3")   + "   ╠════╬════╬════╬════╣\n"  +  row("R4"; .n[12:16];"L4")   + "   ╚════╩════╩════╩════╝\n"  + "     U1   U2   U3   U4\n"  );# If $check is a string, interpret it as a regex to be checked.# Otherwise, allow any non-blank inputdef prompt($prompt; $check):  def p:    inform($prompt)    | try input catch halt    | if ($check|type) == "string"      then if (try test($check) catch false) then .           else p           end      elif trim != "" then .      else p      end;  p;  def initGrid:  {n: [range ( 0; 16) | . + 1]};# Input: {n}# $ix should be an array of length 4def rotate($ix):  .n[$ix[3]] as $last  | reduce range (3; 0; -1) as $i (.; .n[$ix[$i]] = .n[$ix[$i-1]])  | .n[$ix[0]] = $last;def hasWon:  .n as $n  | all( range(0;15); . as $i | $n[$i] == $i + 1);# Input: {prng} as per MRG32k3a# Output: {prng, prn} where .prn is randomly selected from range(0;$n)def prn($n):  .prng |= nextFloat  | .prn = (.prng|.nextFloat * $n | trunc) ;# Set difficulty level# Input: {n}def setDiff($level):  (if $level == easy then 3 else 12 end) as $moves  | .rc = []  | .i = 0  | .prng = (seed(now | tostring | sub("^.*[.]";"") | tonumber))  | until(.i >= $moves;      .rc = []      | prn(2)   | .prn as $r      | prn(4)   | .prn as $s      | if ($r == 0)        then reduce range($s*4; ($s+1)*4) as $j (.; .rc += [$j] )        else  # rotate random column             reduce range($s; $s+16; 4) as $j (.; .rc += [$j] )        end      | rotate(.rc)      | if hasWon        then # start again         .i = -1        end      | .i +=  1    )  | inform("Target is \($moves) moves.\n");def play:  def trim: gsub(" ";"");   def difficulty:    prompt("Enter difficulty level (E for easy, H for hard): "; "^[eEhH]")    | .[:1]    | ascii_upcase;  initGrid  | .level = (if difficulty == "H" then hard else easy end)  | setDiff(.level)  | inform("When entering moves, you can also enter Q to quit or S to start again.\n")  | .moves = 0  | label $out  | recurse(      drawGrid        | if hasWon        then inform( "Congratulations, you have won the game in \(.moves) moves!\n")        | break $out        end      | inform("Moves so far = \(.moves)\n")      | (prompt("Enter move : "; "^ *([qsQS]|[drluDRLU] *[1234])")         | ascii_upcase | trim) as $move      | $move[:1] as $a      | (if $a | test("[SQ]")         then null         else (($move[1:]|explode[0]) - 49)         end ) as $c      | if $a == "D"        then rotate([0,4,8,12] | map(. + $c))        | .moves += 1        elif $a == "L"        then rotate([3,2,1,0] | map(. + 4*$c))        | .moves += 1        elif $a == "U"        then rotate([12,8,4,0] | map(. + $c))        | .moves += 1        elif $a == "R"        then rotate([0,1,2,3] | map(. + 4*$c))        | .moves += 1        elif $move == "Q"        then break $out        elif $move == "S"        then inform("Restarting...\n")        | initGrid        | setDiff(.level)        | .moves = 0        else inform("Invalid move, try again.\n")        end )  | empty ;    play
Output:

Invocation: jq -nRr -f 16-puzzle-game.jq

Enter difficulty level (E for easy, H for hard): eTarget is 3 moves.When entering moves, you can also enter Q to quit or S to start again.     D1   D2   D3   D4   ╔════╦════╦════╦════╗R1 ║  4 ║  1 ║ 13 ║  3 ║ L1   ╠════╬════╬════╬════╣R2 ║  5 ║  2 ║  7 ║  8 ║ L2   ╠════╬════╬════╬════╣R3 ║  9 ║  6 ║ 11 ║ 12 ║  L3   ╠════╬════╬════╬════╣R4 ║ 16 ║ 10 ║ 14 ║ 15 ║ L4   ╚════╩════╩════╩════╝     U1   U2   U3   U4Moves so far = 0Enter move : d1     D1   D2   D3   D4   ╔════╦════╦════╦════╗R1 ║ 16 ║  1 ║ 13 ║  3 ║ L1   ╠════╬════╬════╬════╣R2 ║  4 ║  2 ║  7 ║  8 ║ L2   ╠════╬════╬════╬════╣R3 ║  5 ║  6 ║ 11 ║ 12 ║  L3   ╠════╬════╬════╬════╣R4 ║  9 ║ 10 ║ 14 ║ 15 ║ L4   ╚════╩════╩════╩════╝     U1   U2   U3   U4Moves so far = 1Enter move : u1     D1   D2   D3   D4   ╔════╦════╦════╦════╗R1 ║  4 ║  1 ║ 13 ║  3 ║ L1   ╠════╬════╬════╬════╣R2 ║  5 ║  2 ║  7 ║  8 ║ L2   ╠════╬════╬════╬════╣R3 ║  9 ║  6 ║ 11 ║ 12 ║  L3   ╠════╬════╬════╬════╣R4 ║ 16 ║ 10 ║ 14 ║ 15 ║ L4   ╚════╩════╩════╩════╝     U1   U2   U3   U4Moves so far = 2Enter move : sRestarting...Target is 12 moves.     D1   D2   D3   D4   ╔════╦════╦════╦════╗R1 ║  1 ║  9 ║  6 ║  4 ║ L1   ╠════╬════╬════╬════╣R2 ║  8 ║  5 ║ 10 ║ 14 ║ L2   ╠════╬════╬════╬════╣R3 ║  3 ║  7 ║  2 ║ 13 ║  L3   ╠════╬════╬════╬════╣R4 ║ 11 ║ 16 ║ 12 ║ 15 ║ L4   ╚════╩════╩════╩════╝     U1   U2   U3   U4Moves so far = 0Enter move : q

Julia

usingGtk,Randomfunctionpuzzle16app(bsize)aclock,clock="\u27f2","\u27f3"win=GtkWindow("16 Game",300,300)|>(GtkFrame()|>(box=GtkBox(:v)))toolbar=GtkToolbar()newgame=GtkToolButton("New Game")set_gtk_property!(newgame,:label,"New Game")set_gtk_property!(newgame,:is_important,true)push!(toolbar,newgame)grid=GtkGrid()map(w->push!(box,w),[toolbar,grid])buttons=Array{Gtk.GtkButtonLeaf,2}(undef,bsize+2,bsize+2)foriin1:bsize+2,jin1:bsize+2grid[i,j]=buttons[i,j]=GtkButton()set_gtk_property!(buttons[i,j],:expand,true)endinorder=string.(reshape(1:bsize*bsize,bsize,bsize))puzzle=shuffle(inorder)rotatecol(puzzle,col,n)=puzzle[:,col].=circshift(puzzle[:,col],n)rotaterow(puzzle,row,n)=puzzle[row,:].=circshift(puzzle[row,:],n)iswon()=puzzle==inorderwon=falsefunctionfindrowcol(button)foriin1:bsize+2,jin1:bsize+2ifbuttons[i,j]==buttonreturni,jendendreturn0,0endfunctionplayerclicked(button)if!woni,j=findrowcol(button)ifi==1rotatecol(puzzle,j-1,1)elseifi==bsize+2rotatecol(puzzle,j-1,-1)elseifj==1rotaterow(puzzle,i-1,1)elseifj==bsize+2rotaterow(puzzle,i-1,-1)endendupdate!()endfunctionsetup!()foriin1:bsize+2,jin1:bsize+2if1<j<bsize+2ifi==1signal_connect(playerclicked,buttons[i,j],"clicked")elseifi==bsize+2signal_connect(playerclicked,buttons[i,j],"clicked")endelseif1<i<bsize+2ifj==1signal_connect(playerclicked,buttons[i,j],"clicked")elseifj==bsize+2signal_connect(playerclicked,buttons[i,j],"clicked")endendendendfunctionupdate!()foriin1:bsize+2,jin1:bsize+2if1<j<bsize+2ifi==1set_gtk_property!(buttons[i,j],:label,clock)elseifi==bsize+2set_gtk_property!(buttons[i,j],:label,aclock)elseset_gtk_property!(buttons[i,j],:label,puzzle[i-1,j-1])endelseif1<i<bsize+2ifj==1set_gtk_property!(buttons[i,j],:label,clock)elseifj==bsize+2set_gtk_property!(buttons[i,j],:label,aclock)endendendifiswon()won=trueinfo_dialog("Game over.\nScore:$score",win)endshowall(win)endfunctioninitialize!(w)puzzle=shuffle(inorder)won=falseupdate!()endsetup!()condition=Condition()endit(w)=notify(condition)signal_connect(initialize!,newgame,:clicked)signal_connect(endit,win,:destroy)initialize!(win)showall(win)wait(condition)endpuzzle16app(4)

Nim

Translation of:Julia
Library:nim-gtk2

Not a direct translation as there are a lot of differences, but the logic is the same.

importstd/[random,sequtils,strformat]importgtk2,glib2constBoardSize=4GridSize=BoardSize+2Right="⇨"Left="⇦"Up="⇧"Down="⇩"typeValue=1..16Puzzle=array[BoardSize,array[BoardSize,Value]]PuzzleApp=objectwindow:PWindow# Main window.inOrder:Puzzle# Target grid.puzzle:Puzzle# Current grid.buttons:array[GridSize,array[GridSize,PButton]]# Button grid.won:bool# True if game won.moves:Natural# Count of moves.procinitPuzzle(puzzle:varPuzzle;data:openArray[Value])=## Initialize the puzzle with a list of values.vari=0forrowinpuzzle.mitems:forcellinrow.mitems:cell=data[i]inciprocshowMessage(app:PuzzleApp)=## Show winning message.letmsg=&"You won in {app.moves} moves"letdialog=messageDialogNew(app.window,DIALOG_DESTROY_WITH_PARENT,MESSAGE_INFO,BUTTONS_CLOSE,msg.cstring)discarddialog.run()dialog.destroy()proconQuit(button:PWidget)=## Procedure called when clicking quit button.mainQuit()procrotateRow(puzzle:varPuzzle;row:Natural;left:bool)=## Rotate a row left or right.ifleft:letfirst=puzzle[row][0]foriin1..puzzle.high:puzzle[row][i-1]=puzzle[row][i]puzzle[row][^1]=firstelse:letlast=puzzle[row][^1]foriincountdown(puzzle.high,1):puzzle[row][i]=puzzle[row][i-1]puzzle[row][0]=lastprocrotateCol(puzzle:varPuzzle;col:Natural;up:bool)=## Rotate a column up or down.ifup:letfirst=puzzle[0][col]foriin1..puzzle.high:puzzle[i-1][col]=puzzle[i][col]puzzle[^1][col]=firstelse:letlast=puzzle[^1][col]foriincountdown(puzzle[0].high,1):puzzle[i][col]=puzzle[i-1][col]puzzle[0][col]=lastprocfindRowCol(app:PuzzleApp;button:PButton):(int,int)=## Find the row and column of a button.forrowin0..BoardSize+1:forcolin0..Boardsize+1:ifapp.buttons[row][col]==button:return(row,col)procupdate(app:varPuzzleApp)=## Update the grid.forrowin0..BoardSize+1:forcolin0..BoardSize+1:ifcolin1..BoardSize:ifrow==0:app.buttons[row][col].setLabel(Down)elifrow==BoardSize+1:app.buttons[row][col].setLabel(Up)else:app.buttons[row][col].setLabel(cstring($app.puzzle[row-1][col-1]))elifrowin1..BoardSize:ifcol==0:app.buttons[row][col].setLabel(Right)elifcol==BoardSize+1:app.buttons[row][col].setLabel(Left)ifapp.puzzle==app.inOrder:app.won=trueapp.showMessage()proconClick(button:PButton;app:varPuzzleApp)=## Procedure called when the user clicked a grid button.ifnotapp.won:incapp.moveslet(row,col)=app.findRowCol(button)ifrow==0:app.puzzle.rotateCol(col-1,false)elifrow==BoardSize+1:app.puzzle.rotateCol(col-1,true)elifcol==0:app.puzzle.rotateRow(row-1,false)elifcol==BoardSize+1:app.puzzle.rotateRow(row-1,true)app.update()procnewGame(button:PWidget;app:varPuzzleApp)=## Prepare a new game.varvalues=toSeq(Value.low..Value.high)values.shuffle()app.puzzle.initPuzzle(values)app.won=falseapp.update()proconDestroyEvent(widget:PWidget;data:pointer):gboolean{.cdecl.}=## Quit the application.mainQuit()randomize()nimInit()varapp:PuzzleAppapp.window=windowNew(WINDOW_TOPLEVEL)app.window.setTitle("16 puzzle game")app.window.setSizeRequest(328,365)discardapp.window.signalConnect("destroy",SIGNAL_FUNC(onDestroyEvent),nil)letvbox=vboxNew(false,0)app.window.addvboxlettoolbar=toolbarNew()discardtoolbar.insertItem("New game",nil,nil,nil,SIGNAL_FUNC(newGame),app.addr,0)discardtoolbar.insertItem("Quit",nil,nil,nil,SIGNAL_FUNC(onQuit),nil,1)vbox.packStart(toolbar,false,false,0)lethbox=hboxNew(false,5)vbox.packEnd(hbox,true,true,0)letgrid=tableNew(GridSize,GridSize,true)grid.setRowSpacings(5)grid.setColSpacings(5)hbox.packStart(grid,true,true,10)forrowinguint(0)..(BoardSize+1):forcolinguint(0)..(BoardSize+1):if(row,col)in[(0.guint,0.guint),(0,BoardSize+1),(BoardSize+1,0),(BoardSize+1,BoardSize+1)]:continueletbutton=buttonNew()button.setSizeRequest(45,45)app.buttons[row][col]=buttongrid.attach(button,col,col+1,row,row+1,0,0,1,1)varvalues=toSeq(Value.low..Value.high)app.inOrder.initPuzzle(values)values.shuffle()app.puzzle.initPuzzle(values)forrowin[0,BoardSize+1]:forcolin1..BoardSize:discardapp.buttons[row][col].signalConnect("clicked",SIGNAL_FUNC(onClick),app.addr)forcolin[0,BoardSize+1]:forrowin1..BoardSize:discardapp.buttons[row][col].signalConnect("clicked",SIGNAL_FUNC(onClick),app.addr)app.won=falseapp.update()app.window.showAll()main()

Perl

#!/usr/bin/perlusestrict;# http://www.rosettacode.org/wiki/16_Puzzle_Gameusewarnings;useList::Utilqw( any );useTk;my$size=$ARGV[0]//4;my$width=length$size**2;my$message='';my$steps;my@board;my@again;my$easy=3;my$mw=MainWindow->new(-title=>'16 Puzzle in Tk');$mw->geometry('+470+300');$mw->optionAdd('*font'=>'sans 14');my$frame=$mw->Frame(-bg=>'gray',-relief=>'ridge',-borderwidth=>5)->pack;my$label=$mw->Label(-textvariable=>\$message,-font=>'times-bold 30',)->pack;$mw->Button(-text=>"Exit",-command=>sub{$mw->destroy},)->pack(-side=>'right');$mw->Button(-text=>"Reset",-command=>sub{@board=@again;show();$message=$steps=0;$label->configure(-fg=>'black');},)->pack(-side=>'right');$mw->Button(-text=>"Easy",-command=>sub{$easy=3;generate()},)->pack(-side=>'left');$mw->Button(-text=>"Hard",-command=>sub{$easy=12;generate()},)->pack(-side=>'left');my@cells=map{$frame->Label(-text=>$_,-relief=>'sunken',-borderwidth=>2,-fg=>'white',-bg=>'blue',-font=>'sans 24',-padx=>7,-pady=>7,-width=>$width,)->grid(-row=>int($_/$size+2),-column=>$_%$size+2,-sticky=>"nsew",)}0..$size**2-1;formy$i(1..$size){$frame->Button(-text=>">",-command=>sub{move("R$i")},)->grid(-row=>$i+1,-column=>1,-sticky=>"nsew");$frame->Button(-text=>"<",-command=>sub{move("L$i")},)->grid(-row=>$i+1,-column=>$size+2,-sticky=>"nsew");$frame->Button(-text=>"v",-command=>sub{move("D$i")},)->grid(-row=>1,-column=>$i+1,-sticky=>"nsew");$frame->Button(-text=>"^",-command=>sub{move("U$i")},)->grid(-row=>$size+2,-column=>$i+1,-sticky=>"nsew");}generate();MainLoop;-M$0<0andexec$0,@ARGV;# restart if source file modified since startsubrandommove{move(qw(U D L R)[rand4].int1+rand$size)}subshow{$cells[$_]->configure(-text=>$board[$_])for0..$size**2-1}subsuccess{notany{$_+1!=$board[$_]}0..$size**2-1}submove{my($dir,$index)=split//,shift;$index--;my@from=map{$dir=~ /L|R/i?$_+$size*$index:$_*$size+$index}0..$size-1;@board[@from]=(@board[@from])[($dir=~ /L|U/i||-1)..$size-1,0];show();$message=++$steps;$label->configure(-fg=>success()?'red':'black');success()and$message="Solved in $steps";}subgenerate{@board=1..$size**2;randommove()for1..1+intrand$easy;success()andrandommove();@again=@board;$message=$steps=0;}

Phix

NB arrow keys not tested on linux, but "UDLR" should work...

constantlevel=5,ESC=27,UP=328,DOWN=336,LEFT=331,RIGHT=333sequenceboard=tagset(16),solve=boardprocedureprint_board()printf(1,"    1  2  3  4\n")forr=1to4doprintf(1,"%d: %2d %2d %2d %2d\n",r&board[r*4-3..r*4])endforputs(1,"\n")endprocedureproceduremove(integerd,rc)-- d is 1..4 for up/down/left/right    -- rc is 1..4 for row(d>=3)/column(d<=2)sequenceidx=repeat(0,4),tiles=repeat(0,4)fori=1to4doidx[i]=iff(d<=2?rc+(i-1)*4:(rc-1)*4+i)tiles[i]=board[idx[i]]endfor--  ?{d,rc,idx}idx=iff(mod(d,2)?idx[4]&idx[1..3]:idx[2..4]&idx[1])fori=1to4doboard[idx[i]]=tiles[i]endforendprocedurefori=1toleveldomove(rand(4),rand(4))endforwhile1doprint_board()ifboard=solvethenputs(1,"Solved!\n")exitendifputs(1,"Your move (escape|Up/Down|Left/Right & 1/2/3/4):")integerd,rcwhiletruedowhiletruedod=find(upper(wait_key()),{ESC,UP,DOWN,LEFT,RIGHT}&"UDLR")-1ifd!=-1thenexitendifendwhileifd=0thenputs(1,"\n\nYou gave up!\n")exitendififd>4thend-=4endifputs(1,"UDLR"[d])whiletruedorc=find(upper(wait_key()),ESC&"1234UDLR"&{UP,DOWN,LEFT,RIGHT})-1ifrc>4thenifrc>8thenrc-=4endifd=rc-4puts(1,"\b \b"&"UDLR"[d])elseifrc!=-1thenexitendifendifendwhileifrc=0thenputs(1,"\b \b")elseprintf(1,"%d\n\n",rc)move(d,rc)exitendifendwhileifd=0thenexitendifendwhile
Output:

(a level 2 game)

    1  2  3  41:  1  2  7  42:  5  6 11  83:  9 10 16 124: 14 15  3 13Your move (escape|Up/Down|Left/Right & 1/2/3/4):D3    1  2  3  41:  1  2  3  42:  5  6  7  83:  9 10 11 124: 14 15 16 13Your move (escape|Up/Down|Left/Right & 1/2/3/4):R4    1  2  3  41:  1  2  3  42:  5  6  7  83:  9 10 11 124: 13 14 15 16Solved!

Raku

For brevity, changed to zero-based and skipped some error handling.

Translation of:Go
# 20210914 Raku programming solutionmy (\easy,\hard) =1,4 ;my@n = ^16;my \level = $ =easy ;my \moves = $ =0;subhasWon {@neq ^16 }subsetDiff($level) {say"\nTarget is ", (moves =$level ==hard ??12 !!3 ).Str," moves.";for ^moves {my \s = (^4).roll;@n[ ( [s,s+4 ...s+12 ] , [s*4 ..s*4+3 ] ).roll ] .=rotate ;redoifhasWon   }}subdrawGrid {say"\n     U1   U2   U3   U4";say"   ╔════╦════╦════╦════╗";printf"L1 ║ %2d ║ %2d ║ %2d ║ %2d ║ R1\n",@n[0..3];say"   ╠════╬════╬════╬════╣";printf"L2 ║ %2d ║ %2d ║ %2d ║ %2d ║ R2\n",@n[4..7];say"   ╠════╬════╬════╬════╣";printf"L3 ║ %2d ║ %2d ║ %2d ║ %2d ║ R3\n",@n[8..11];say"   ╠════╬════╬════╬════╣";printf"L4 ║ %2d ║ %2d ║ %2d ║ %2d ║ R4\n",@n[12..15];say"   ╚════╩════╩════╩════╝";say"     D1   D2   D3   D4\n"}subinit {loop {print"Enter difficulty level easy or hard E/H : ";given$*IN.get.uc {when'E'|'H' {level =$_eq'H' ??hard !!easy ;last  }default      {say"Invalid response, try again." }      }   }setDiff(level);moves =0;}init;loop {drawGrid;ifhasWon() {say"Congratulations, you have won the game in {moves} moves.\n"andexit   }say"When entering moves, you can also enter Q to quit or S to start again.";say"\nMoves so far = {moves}\n";print"Enter move : " ;given$*IN.get.uc {my \c = .substr(*-1).ord -49 ;moves++ ;when'D1'|'D2'|'D3'|'D4' {@n[ (12,8,4,0) >>+>>c   ] .=rotate }when'L1'|'L2'|'L3'|'L4' {@n[ (0,1,2,3)  >>+>>4*c ] .=rotate }when'U1'|'U2'|'U3'|'U4' {@n[ (0,4,8,12) >>+>>c   ] .=rotate }when'R1'|'R2'|'R3'|'R4' {@n[ (3,2,1,0)  >>+>>4*c ] .=rotate }when'Q'                 {exit }when'S'                 {init }default                  {say"\nInvalid move, try again."andmoves-- }   }}

REXX

This REXX version allows the user to choose the grid size for the  16   game (puzzle),   aswell as the difficulty of the puzzle.
The user's responses may have optional whitespace in the answer, and the answer can be in any case (lower or uppercase).
Not all errors are checked so as to keep the program simpler.

/*REXX pgm implements the  16  game;  displays game grid, prompts for a move, game won? */sep=copies("─",8);pad=left('',1+length(sep))/*pad=9 blanks.   SEP is used for msgs.*/parseargNhardseed./*obtain optional arguments from the CL*/er='***error***'/*literal used to indicate an error msg*/ifN==''|N==","thenN=4/*Not specified?  Then use the default.*/ifhard==''|hard==","thenhard=2/* "      "         "   "   "     "    */if\isInt(N)thendo;sayseper"grid size isn't an integer: "N;exit1;endifN<2|N>9thendo;sayseper"grid size is out of range: "N;exit1;endifisInt(seed)thencallrandom,,seed/*use repeatability seed for RANDOM BIF*/saysep'Playing a 'N*N" game with a difficulty level of: "hard#=0dor=1forN/* [◄]  build a solution for testing.  */doc=1forN;#=#+1;@.r.c=#/*bump number (count), define a cell.  */end/*c*/end/*r*//* [↓]  HARD  is the puzzle difficulty.*/dohard;row=random(1)/*scramble the grid  HARD   # of times.*/ifrowthencallmoverandom(1,N)substr('LR',random(1,2),1)/* ◄── move row. */elsecallmovesubstr('abcdefghi',random(1,N),1)substr("+-",random(1,2),1)end/*hard*//* [↓]  move col.*//*play 16─game until  solved  or  quit.*/dountildone()/*perform moves until puzzle is solved.*/callmove/*get user's move(s)  and  validate it.*/iferrMsg\==''thendo;saysepererrMsg".";iterate;end/*possible error msg?*/end/*until*/callshow;saysep'Congratulations!   The'N**2"─puzzle is solved."exit/*stick a fork in it,  we're all done. *//*──────────────────────────────────────────────────────────────────────────────────────*/done:#=0;dor=1toN;doc=1toN;#=#+1;if@.r.c\==#thenreturn0;end;end;return1isInt:returndatatype(arg(1),'W')/*return 1 if arg is a whole number.   */ghost:dor=1forn;doc=1forn;!.r.c=@.r.c;end/*r*/;end/*c*/;return/*──────────────────────────────────────────────────────────────────────────────────────*/move:argx/*obtain optional move from ARG or ask.*/ask1=sep'Please enter a     row  number    followed by a   L   or   R,       or'ask2=sep'       enter a   column letter    followed by a   +   or   -'@quit@quit='      (or Quit):'ifx==''thendoifqueued()==0thendo;say;callshow;sayask1;sayask2endpullx;x=space(x,0)/*obtain a response;  elide whitespace.*/endy=left(x,1);d=right(x,1)/*get a number or letter, and also a ± */num=isInt(d);let=datatype(y,'U')/*get direction to shift, based on type*/ifabbrev('QUIT',x,1)thendo;say;say;saysep"quitting.";exit;endselectwhenx==''thenerrMsg="nothing entered"whenlength(x)>2thenerrMsg="improper response:  "xwhennum&(y<1|y>N)thenerrMsg="row isn't in range: "ywhennum&(d\="L"&d\='R')thenerrMsg="row shift isn't L or R: "dwhenlet&(y<"A"|y>HI)thenerrMsg="col isn't in range: "ywhenlet&(d\="+"&d\='-')thenerrMsg="col shift isn't + or -: "dotherwiseerrMsg=end/*select*//* [↑]  verify the human entered data. */callghost;yn=pos(y,'ABCDEFGHI')/*create a ghost grid for easy moving. */ifisInt(y)thenifd=='R'thendoc=1forN;cm=c-1;ifc==1thencm=c+N-1@.y.c=!.y.cmendelsedoc=1forN;cp=c+1;ifc==Nthencp=1@.y.c=!.y.cpendelseifd=='-'thendor=1forN;rm=r-1;ifr==1thenrm=r+N-1@.r.yn=!.rm.ynendelsedor=1forN;rp=r+1;ifr==Nthenrp=1@.r.yn=!.rp.ynendreturn/*──────────────────────────────────────────────────────────────────────────────────────*/show:top='╔'copies(copies("═",2)'╦',N);top=left(top,length(top)-1)"╗"bar='╠'copies(copies("═",2)'╬',N);bar=left(bar,length(bar)-1)"╣"bot='╚'copies(copies("═",2)'╩',N);bot=left(bot,length(bot)-1)"╝"ind=left('',3+length(N))/*compute indentation.*/col=indindind' 'subword("a- b- c- d- e- f- g- h- i-",1,n)HI=substr('abcdefghi',N,1);upperHIsaycolindindind'-  means shift a column down';saypadindtopdor=1forN;z=r'R'"  ║"/*build NxN game grid*/doc=1forN;z=z||right(@.r.c,2)'║'/*build  row by row. */end/*c*/z=z' 'r"L"/*add right-side info*/ifr==1thenz=zpad'L  means shift a row left'/* "   1st help info.*/ifr==2thenz=zpad'R  means shift a row right'/* "   2nd   "    "  */saypadz;ifr\==Nthensaypadindbarend/*r*/saypadindbot;say;saytranslate(col,'+',"-")indindind"+  means shift a column up";sayreturn
output  when using the default inputs:
──────── Playing a  16  game with a difficulty level of:  2                a- b- c- d-                -  means shift a column down               ╔══╦══╦══╦══╗          1R   ║ 1║ 2║15║ 4║   1L          L  means shift a row left               ╠══╬══╬══╬══╣          2R   ║ 5║ 6║ 3║ 8║   2L          R  means shift a row right               ╠══╬══╬══╬══╣          3R   ║12║ 9║ 7║11║   3L               ╠══╬══╬══╬══╣          4R   ║13║14║10║16║   4L               ╚══╩══╩══╩══╝                a+ b+ c+ d+                +  means shift a column up──────── Please enter a     row  number    followed by a   L   or   R,       or────────        enter a   column letter    followed by a   +   or   -       (or Quit):c +                             ◄■■■■■■■■ user input                                                                                                a- b- c- d-                -  means shift a column down               ╔══╦══╦══╦══╗          1R   ║ 1║ 2║ 3║ 4║   1L          L  means shift a row left               ╠══╬══╬══╬══╣          2R   ║ 5║ 6║ 7║ 8║   2L          R  means shift a row right               ╠══╬══╬══╬══╣          3R   ║12║ 9║10║11║   3L               ╠══╬══╬══╬══╣          4R   ║13║14║15║16║   4L               ╚══╩══╩══╩══╝                a+ b+ c+ d+                +  means shift a column up──────── Please enter a     row  number    followed by a   L   or   R,       or────────        enter a   column letter    followed by a   +   or   -       (or Quit):3L                              ◄■■■■■■■■ user input                a- b- c- d-                -  means shift a column down               ╔══╦══╦══╦══╗          1R   ║ 1║ 2║ 3║ 4║   1L          L  means shift a row left               ╠══╬══╬══╬══╣          2R   ║ 5║ 6║ 7║ 8║   2L          R  means shift a row right               ╠══╬══╬══╬══╣          3R   ║ 9║10║11║12║   3L               ╠══╬══╬══╬══╣          4R   ║13║14║15║16║   4L               ╚══╩══╩══╩══╝                a+ b+ c+ d+                +  means shift a column up──────── Congratulations!   The 16─puzzle is solved.

Ring

# Project : Sixteen Puzzle Gameload "guilib.ring"load "stdlib.ring"app1 = new qapp {        t1 = 0        temp = ""        table = [][]        movesnr = 0        button = list(16)         begintiles = list(16)        pReturn = list(4)        CounterMan = 0        saveflag = 0        stylefusionblack()           win1 = new qwidget() {                   move(0,0)                   resize(360, 600)                   setwindowtitle("Calmosoft Sixteen Puzzle Game")                   for n = 1 to 16                         col = n%4                         if col = 0 col = 4 ok                         row = ceil(n/4)                         button[n] = new qpushbutton(win1)                         {                                            setgeometry(60+col*40,60+row*40,40,40)                                                                                        setstylesheet("color:white")                                                setstylesheet("background-color:blue")                                                                                    settext(string(n))                                                                                                                  }                    next                  buttonup1 = new qpushbutton(win1)                  {                                      setgeometry(100, 60, 40, 40)                                      settext("up")                                      setclickevent("up1()")                     }                  buttonup2 = new qpushbutton(win1)                  {                                      setgeometry(140, 60, 40, 40)                                      settext("up")                                      setclickevent("up2()")                     }                 buttonup3 = new qpushbutton(win1)                  {                                      setgeometry(180, 60, 40, 40)                                      settext("up")                                      setclickevent("up3()")                     }                 buttonup4 = new qpushbutton(win1)                  {                                      setgeometry(220, 60, 40, 40)                                      settext("up")                                      setclickevent("up4()")                     }                  buttondown1 = new qpushbutton(win1)                  {                                          setgeometry(100, 260, 40, 40)                                          settext("down")                                          setclickevent("down1()")                     }                  buttondown2 = new qpushbutton(win1)                  {                                          setgeometry(140, 260, 40, 40)                                          settext("down")                                          setclickevent("down2()")                     }                  buttondown3 = new qpushbutton(win1)                  {                                          setgeometry(180, 260, 40, 40)                                          settext("down")                                          setclickevent("down3()")                     }                 buttondown4 = new qpushbutton(win1)                  {                                          setgeometry(220, 260, 40, 40)                                          settext("down")                                          setclickevent("down4()")                     }                  buttonleft1 = new qpushbutton(win1)                  {                                          setgeometry(60, 100, 40, 40)                                          settext("<<<")                                          setclickevent("left1()")                     }                  buttonleft2 = new qpushbutton(win1)                  {                                          setgeometry(60, 140, 40, 40)                                          settext("<<<")                                          setclickevent("left2()")                     }                  buttonleft3 = new qpushbutton(win1)                  {                                          setgeometry(60, 180, 40, 40)                                          settext("<<<")                                          setclickevent("left3()")                     }                  buttonleft4 = new qpushbutton(win1)                  {                                          setgeometry(60, 220, 40, 40)                                          settext("<<<")                                          setclickevent("left4()")                     }                  buttonright1 = new qpushbutton(win1)                  {                                          setgeometry(260, 100, 40, 40)                                          settext(">>>")                                          setclickevent("right1()")                     }                  buttonright2 = new qpushbutton(win1)                  {                                          setgeometry(260, 140, 40, 40)                                          settext(">>>")                                          setclickevent("right2()")                     }                  buttonright3 = new qpushbutton(win1)                  {                                          setgeometry(260, 180, 40, 40)                                          settext(">>>")                                          setclickevent("right3()")                     }                  buttonright4 = new qpushbutton(win1)                  {                                          setgeometry(260, 220, 40, 40)                                          settext(">>>")                                          setclickevent("right4()")                     }                  buttonscramble = new qpushbutton(win1)                  {                                             setgeometry(100, 300, 160, 40)                                             settext("Scarmble")                                             setclickevent("scramble()")                     }                  buttonreset = new qpushbutton(win1)                  {                                        setgeometry(100, 340, 160, 40)                                        settext("Reset")                                        setclickevent("reset()")                     }                  buttonsave = new qpushbutton(win1)                  {                                   setgeometry(100, 380, 160, 40)                                   settext("Save Game")                                   setclickevent("psaveEmpty()")                  }                  buttonplay = new qpushbutton(win1)                     {                                 setgeometry(100,420,160,40)                                   settext("Replay Game")                                   setclickevent("pPlay()")                  }                  buttonnr = new qpushbutton(win1)                  {                                   setgeometry(100, 460, 160, 40)                                   settext("Moves : ")                  }                  timebtn = new qpushbutton(win1)                     {                                 setgeometry(100,500,160,40)                                   settext("Elapsed Time : ")                    }                  t1 = clock()                  for i = 1 to 16                       begintiles[i] = string(i)                  next                  TimerMan = new qtimer(win1)                  {                                    setinterval(0.5)                                    settimeoutevent("pTime()")                                    stop()                  }                  show()        }        exec()}func scramble       reset()       empty = 16       movesnr = 0       buttonnr.settext("Moves : " + movesnr)       for n= 1 to 1000              nr=random(15)+1            up = (empty = (nr - 4))            down = (empty = (nr + 4))            left = ((empty = (nr - 1)) and ((nr % 4) != 1))            right = ((empty = (nr + 1)) and ((nr % 4) != 0))            move = up or down or left  or right            if move = 1                temp1 = button[nr].text()               temp2 = button[empty].text()               button[empty].settext(temp1)               button[nr].settext(temp2)               empty = nr            ok       next       timebtn.settext("Elapsed Time : ")       t1 = clock()       table = []       saveflag = 0       for n= 1 to 16             if isstring(button[n].text())                begintiles[n] = button[n].text()             else                begintiles[n] = string(button[n].text())             ok        nextfunc reset        movesnr = 0        buttonnr.settext("Moves : " + movesnr)        for i = 1 to 16             button[i] {settext(string(i))}             button[i].setstylesheet("background-color:blue")             begintiles[i] = string(i)        next        timebtn.settext("Elapsed Time : ")        t1 = clock()        table = []        saveflag = 0        returnfunc pClock        t2 = (clock() - t1)/1000        timebtn.settext("Elapsed Time : " + t2 + " s")func psaveEmpty        timebtn.settext("Elapsed Time : ")        t1 = clock()        returnfunc psave        if saveflag = 1           for n = 1 to 4                add(table, [pReturn[n], button[pReturn[n]].text()])           next        okfunc pPlay        if saveflag = 1           for n=1 to 16                 button[n]{settext(begintiles[n])}                 button[n].setstylesheet("background-color:blue")           next           timebtn.settext("Elapsed Time : ")           movesnr = 0           buttonnr.settext("Moves : " + movesnr)           t1 = clock()           CounterMan = 0           TimerMan.start()        okfunc pTime()        if saveflag = 1           CounterMan = CounterMan + 1           if CounterMan > 1              temp.setstylesheet("background-color:blue")           ok           pPlaySleep()           sleep(1)            if CounterMan = len(table)              TimerMan.stop()           ok        okfunc pPlaySleep        pClock()        button[table[CounterMan][1]].setstylesheet("background-color:orange")         temp =  button[table[CounterMan][1]]        button[table[CounterMan][1]].settext(table[CounterMan][2])        movesnr = movesnr + 1        buttonnr.settext("Moves : " + movesnr)        returnfunc up1        temp = button[1].text()        button[1].settext(button[5].text())        button[5].settext(button[9].text())        button[9].settext(button[13].text())        button[13].settext(temp)        movesnr =movesnr + 1        buttonnr.settext("Moves : " + string(movesnr))        pClock()        pReturn = [1,5,9,13]        saveflag = 1        psave()        returnfunc up2        temp = button[2].text()        button[2].settext(button[6].text())        button[6].settext(button[10].text())        button[10].settext(button[14].text())        button[14].settext(temp)        movesnr =movesnr + 1        buttonnr.settext("Moves : " + string(movesnr))        pClock()        pReturn = [2,6,10,14]        saveflag = 1        psave()        returnfunc up3        temp = button[3].text()        button[3].settext(button[7].text())        button[7].settext(button[11].text())        button[11].settext(button[15].text())        button[15].settext(temp)        movesnr =movesnr + 1        buttonnr.settext("Moves : " + string(movesnr))        pClock()        pReturn = [3,7,11,15]        saveflag = 1        psave()        returnfunc up4        temp = button[4].text()        button[4].settext(button[8].text())        button[8].settext(button[12].text())        button[12].settext(button[16].text())        button[16].settext(temp)        movesnr =movesnr + 1        buttonnr.settext("Moves : " + string(movesnr))        pClock()        pReturn = [4,8,12,16]        saveflag = 1        psave()        returnfunc down1        temp = button[13].text()        button[13].settext(button[9].text())        button[9].settext(button[5].text())        button[5].settext(button[1].text())        button[1].settext(temp)        movesnr =movesnr + 1        buttonnr.settext("Moves : " + string(movesnr))        pClock()        pReturn = [13,9,5,1]        saveflag = 1        psave()        returnfunc down2        temp = button[14].text()        button[14].settext(button[10].text())        button[10].settext(button[6].text())        button[6].settext(button[2].text())        button[2].settext(temp)        movesnr =movesnr + 1        buttonnr.settext("Moves : " + string(movesnr))        pClock()        pReturn = [14,10,6,2]        saveflag = 1        psave()        returnfunc down3        temp = button[15].text()        button[15].settext(button[11].text())        button[11].settext(button[7].text())        button[7].settext(button[3].text())        button[3].settext(temp)        movesnr =movesnr + 1        buttonnr.settext("Moves : " + string(movesnr))        pClock()        pReturn = [15,11,7,3]        saveflag = 1        psave()        returnfunc down4        temp = button[16].text()        button[16].settext(button[12].text())        button[12].settext(button[8].text())        button[8].settext(button[4].text())        button[4].settext(temp)        movesnr =movesnr + 1        buttonnr.settext("Moves : " + string(movesnr))        pClock()        pReturn = [16,12,8,4]        saveflag = 1        psave()        returnfunc left1        temp = button[1].text()        button[1].settext(button[2].text())        button[2].settext(button[3].text())        button[3].settext(button[4].text())        button[4].settext(temp)        movesnr =movesnr + 1        buttonnr.settext("Moves : " + string(movesnr))        pClock()        pReturn = [1,2,3,4]        saveflag = 1        psave()        returnfunc left2        temp = button[5].text()        button[5].settext(button[6].text())        button[6].settext(button[7].text())        button[7].settext(button[8].text())        button[8].settext(temp)        movesnr =movesnr + 1        buttonnr.settext("Moves : " + string(movesnr))        pClock()        pReturn = [5,6,7,8]        saveflag = 1        psave()        returnfunc left3        temp = button[9].text()        button[9].settext(button[10].text())        button[10].settext(button[11].text())        button[11].settext(button[12].text())        button[12].settext(temp)        movesnr =movesnr + 1        buttonnr.settext("Moves : " + string(movesnr))        pClock()        pReturn = [9,10,11,12]        saveflag = 1        psave()        returnfunc left4        temp = button[13].text()        button[13].settext(button[14].text())        button[14].settext(button[15].text())        button[15].settext(button[16].text())        button[16].settext(temp)        movesnr =movesnr + 1        buttonnr.settext("Moves : " + string(movesnr))        pClock()        pReturn = [13,14,15,16]        saveflag = 1        psave()        returnfunc right1        temp = button[4].text()        button[4].settext(button[3].text())        button[3].settext(button[2].text())        button[2].settext(button[1].text())        button[1].settext(temp)        movesnr =movesnr + 1        buttonnr.settext("Moves : " + string(movesnr))        pClock()        pReturn = [4,3,2,1]        saveflag = 1        psave()        returnfunc right2        temp = button[8].text()        button[8].settext(button[7].text())        button[7].settext(button[6].text())        button[6].settext(button[5].text())        button[5].settext(temp)        movesnr =movesnr + 1        buttonnr.settext("Moves : " + string(movesnr))        pClock()        pReturn = [8,7,6,5]        saveflag = 1        psave()        returnfunc right3        temp = button[12].text()        button[12].settext(button[11].text())        button[11].settext(button[10].text())        button[10].settext(button[9].text())        button[9].settext(temp)        movesnr =movesnr + 1        buttonnr.settext("Moves : " + string(movesnr))        pClock()        pReturn = [12,11,10,9]        saveflag = 1        psave()        returnfunc right4        temp = button[16].text()        button[16].settext(button[15].text())        button[15].settext(button[14].text())        button[14].settext(button[13].text())        button[13].settext(temp)        movesnr =movesnr + 1        buttonnr.settext("Moves : " + string(movesnr))        pClock()        pReturn = [16,15,14,13]        saveflag = 1        psave()        return

Output image:

16 Puzzle Game

Wren

Translation of:Go
Library:Wren-iterate
Library:Wren-fmt
Library:Wren-ioutil
Library:Wren-str
import"random"forRandomimport"./iterate"forSteppedimport"./fmt"forFmtimport"./ioutil"forInputimport"./str"forStrvarrand=Random.new()vareasy=1varhard=4varn=List.filled(16,0)varinitGrid=Fn.new{for(iin0..15)n[i]=i+1}varrotate=Fn.new{|ix|varlast=n[ix[3]]for(iin3..1)n[ix[i]]=n[ix[i-1]]n[ix[0]]=last}varhasWon=Fn.new{for(iin0...15){if(n[i]!=i+1)returnfalse}returntrue}varsetDiff=Fn.new{|level|varmoves=(level==easy)?3:12varrc=[]vari=0while(i<moves){rc.clear()varr=rand.int(2)vars=rand.int(4)if(r==0){// rotate random rowfor(jins*4...(s+1)*4)rc.add(j)}else{// rotate random columnfor(jinStepped.new(s...s+16,4))rc.add(j)}varrca=rc.toListrotate.call(rca)if(hasWon.call()){// do it againi=-1}i=i+1}System.print("Target is%(moves) moves.")}vardrawGrid=Fn.new{System.print()System.print("     D1   D2   D3   D4")System.print("   ╔════╦════╦════╦════╗")Fmt.print("R1 ║ $2d ║ $2d ║ $2d ║ $2d ║ L1",n[0],n[1],n[2],n[3])System.print("   ╠════╬════╬════╬════╣")Fmt.print("R2 ║ $2d ║ $2d ║ $2d ║ $2d ║ L2",n[4],n[5],n[6],n[7])System.print("   ╠════╬════╬════╬════╣")Fmt.print("R3 ║ $2d ║ $2d ║ $2d ║ $2d ║ L3",n[8],n[9],n[10],n[11])System.print("   ╠════╬════╬════╬════╣")Fmt.print("R4 ║ $2d ║ $2d ║ $2d ║ $2d ║ L4",n[12],n[13],n[14],n[15])System.print("   ╚════╩════╩════╩════╝")System.print("     U1   U2   U3   U4\n")}initGrid.call()varlevel=easyvardiff=Input.option("Enter difficulty level easy or hard E/H : ","eEhH")if(diff=="h"||diff=="H")level=hardsetDiff.call(level)varix=List.filled(4,0)System.print("When entering moves, you can also enter Q to quit or S to start again.")varmoves=0while(true){drawGrid.call()if(hasWon.call()){System.print("Congratulations, you have won the game in%(moves) moves!!")return}while(true){System.print("Moves so far =%(moves)\n")varmove=Str.upper(Input.text("Enter move : ",1).trim())if(move=="D1"||move=="D2"||move=="D3"||move=="D4"){varc=move[1].bytes[0]-49ix[0]=0+cix[1]=4+cix[2]=8+cix[3]=12+crotate.call(ix)moves=moves+1break}elseif(move=="L1"||move=="L2"||move=="L3"||move=="L4"){varc=move[1].bytes[0]-49ix[0]=3+4*cix[1]=2+4*cix[2]=1+4*cix[3]=0+4*crotate.call(ix)moves=moves+1break}elseif(move=="U1"||move=="U2"||move=="U3"||move=="U4"){varc=move[1].bytes[0]-49ix[0]=12+cix[1]=8+cix[2]=4+cix[3]=0+crotate.call(ix)moves=moves+1break}elseif(move=="R1"||move=="R2"||move=="R3"||move=="R4"){varc=move[1].bytes[0]-49ix[0]=0+4*cix[1]=1+4*cix[2]=2+4*cix[3]=3+4*crotate.call(ix)moves=moves+1break}elseif(move=="Q"){return}elseif(move=="S"){initGrid.call()setDiff.call(level)moves=0break}else{System.print("Invalid move, try again.")}}}
Output:

Sample (very easy!) game:

Enter difficulty level easy or hard E/H : eTarget is 3 moves.When entering moves, you can also enter Q to quit or S to start again.     D1   D2   D3   D4   ╔════╦════╦════╦════╗R1 ║  3 ║  4 ║  1 ║  2 ║ L1   ╠════╬════╬════╬════╣R2 ║  5 ║  6 ║  7 ║  8 ║ L2   ╠════╬════╬════╬════╣R3 ║  9 ║ 10 ║ 11 ║ 12 ║ L3   ╠════╬════╬════╬════╣R4 ║ 16 ║ 13 ║ 14 ║ 15 ║ L4   ╚════╩════╩════╩════╝     U1   U2   U3   U4Moves so far = 0Enter move : l1     D1   D2   D3   D4   ╔════╦════╦════╦════╗R1 ║  4 ║  1 ║  2 ║  3 ║ L1   ╠════╬════╬════╬════╣R2 ║  5 ║  6 ║  7 ║  8 ║ L2   ╠════╬════╬════╬════╣R3 ║  9 ║ 10 ║ 11 ║ 12 ║ L3   ╠════╬════╬════╬════╣R4 ║ 16 ║ 13 ║ 14 ║ 15 ║ L4   ╚════╩════╩════╩════╝     U1   U2   U3   U4Moves so far = 1Enter move : l1     D1   D2   D3   D4   ╔════╦════╦════╦════╗R1 ║  1 ║  2 ║  3 ║  4 ║ L1   ╠════╬════╬════╬════╣R2 ║  5 ║  6 ║  7 ║  8 ║ L2   ╠════╬════╬════╬════╣R3 ║  9 ║ 10 ║ 11 ║ 12 ║ L3   ╠════╬════╬════╬════╣R4 ║ 16 ║ 13 ║ 14 ║ 15 ║ L4   ╚════╩════╩════╩════╝     U1   U2   U3   U4Moves so far = 2Enter move : l4     D1   D2   D3   D4   ╔════╦════╦════╦════╗R1 ║  1 ║  2 ║  3 ║  4 ║ L1   ╠════╬════╬════╬════╣R2 ║  5 ║  6 ║  7 ║  8 ║ L2   ╠════╬════╬════╬════╣R3 ║  9 ║ 10 ║ 11 ║ 12 ║ L3   ╠════╬════╬════╬════╣R4 ║ 13 ║ 14 ║ 15 ║ 16 ║ L4   ╚════╩════╩════╩════╝     U1   U2   U3   U4Congratulations, you have won the game in 3 moves!!

XPL0

Runs on DOSBox, MS-DOS, and Raspberry Pi. The quoted garbage are IBM's original box characters.

string 0;                       \0 termination for extended (IBM) char stringschar Puzzle(16), Moves;def  X0=(40-11)/2,  Y0=(25-11)/2 - 2; \centers puzzle on screenfunc HaveWon;                   \Return 'true' if winning arrangementint  I;[for I:= 0 to $F do    if Puzzle(I) # I then return false;return true;];proc Rotate(Button);            \Rotate row or column specified by arrow Buttonint  Button;int  Start, Step, Temp, I, J, N;[Start:= [0, 4, 8,12, 3, 7,11,15, 0, 1, 2, 3,12,13,14,15];Step:=   [1, 1, 1, 1,-1,-1,-1,-1, 4, 4, 4, 4,-4,-4,-4,-4];I:= Start(Button);J:= Step(Button);Temp:= Puzzle(I);for N:= 1 to 3 do    [Puzzle(I):= Puzzle(I+J);    I:= I+J;    ];Puzzle(I):= Temp;];func GetButton;                 \Return soft button number at mouse pointerint  Mouse, X, Y, LocX, LocY, I;[Mouse:= GetMouse;X:= Mouse(0)/8 - X0;            \convert pixels to char cellsY:= Mouse(1)/8 - Y0;\ X0,Y0 + 8 9 A B               soft (arrow) button locations\       0         4\       1         5\       2         6\       3         7\         C D E F\       0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  FLocX:= [0, 0, 0, 0,10,10,10,10, 2, 4, 6, 8, 2, 4, 6, 8];LocY:= [2, 4, 6, 8, 2, 4, 6, 8, 0, 0, 0, 0,10,10,10,10];for I:= 0 to $F do    if LocX(I) = X and LocY(I) = Y then return I;return -1;                      \mouse not on any soft button];proc ShowPuzzle;                \Display current state of Puzzleint  I;[Attrib($010F);                 \bright white on blueCursor(X0+1, Y0+1);  Text(6, "ÚÄÂÄÂÄÂÄṡ");Cursor(X0+1, Y0+2);  Text(6, "ġ ġ ġ ġ ġ");Cursor(X0+1, Y0+3);  Text(6, "ÃÄÅÄÅÄÅÄṀ");Cursor(X0+1, Y0+4);  Text(6, "ġ ġ ġ ġ ġ");Cursor(X0+1, Y0+5);  Text(6, "ÃÄÅÄÅÄÅÄṀ");Cursor(X0+1, Y0+6);  Text(6, "ġ ġ ġ ġ ġ");Cursor(X0+1, Y0+7);  Text(6, "ÃÄÅÄÅÄÅÄṀ");Cursor(X0+1, Y0+8);  Text(6, "ġ ġ ġ ġ ġ");Cursor(X0+1, Y0+9);  Text(6, "ÀÄÁÄÁÄÁÄÙ");SetHexDigits(1);for I:= 0 to $F do    [Cursor((I&3)*2+2+X0, I>>2*2+2+Y0);    HexOut(6, Puzzle(I));    ];Attrib($000E);                  \yellow on blackI:= 2;  while I <= 8 do    [Cursor(X0+I,  Y0);     ChOut(6, $1E);      \ ^     Cursor(X0,    Y0+I);   ChOut(6, $11);      \ <     Cursor(X0+10, Y0+I);   ChOut(6, $10);      \ >     Cursor(X0+I,  Y0+10);  ChOut(6, $1F);      \ v    I:= I+2;    ];Cursor(15, 20);  Text(6, "Moves: ");  IntOut(6, Moves);];int  I, Mouse, Button;[SetVid($13);                           \set 320x200x8 graphicsfor I:= 0 to $F do Puzzle(I):= I;for I:= 1 to 12 do Rotate(Ran($10));    \random (hard) arrangementMoves:= 0;                              \initialize move counterShowPuzzle;ShowMouse(true);                        \turn on mouse pointerloop    [if KeyHit then quit;           \keystroke quits loop and program        MoveMouse;                      \make pointer track mouse movements        Mouse:= GetMouse;        if Mouse(2) then                \a left or right mouse button is down            [Button:= GetButton;        \get soft button at mouse pointer            while Mouse(2) do           \wait for mouse button release                [MoveMouse;                Mouse:= GetMouse;                ];            if Button = GetButton and Button # -1 then                [Rotate(Button);        \Button = soft button at release                Moves:= Moves+1;                ShowMouse(false);       \don't draw over mouse pointer                ShowPuzzle;                if HaveWon then                    [Cursor(15, 22);  Text(6, "You Won!");                    quit;                    ];                ShowMouse(true);                ];            ];        ];]
Retrieved from "https://rosettacode.org/wiki/16_puzzle_game?oldid=377495"
Categories:
Hidden category:
Cookies help us deliver our services. By using our services, you agree to our use of cookies.

[8]ページ先頭

©2009-2025 Movatter.jp