16 puzzle game
- Task
Create 16 Puzzle Game.
See details: 16 Puzzle Game
Video: 16 Puzzle Game
REXX
<lang rexx>/*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.*/ parse arg N hard seed . /*obtain optional arguments from the CL*/ er= '***error***' /*literal used to indicate an error msg*/ if N== | N=="," then N= 4 /*Not specified? Then use the default.*/ if hard== | hard=="," then hard= 2 /* " " " " " " */ if \isInt(N) then do; say sep er "grid size isn't an integer: " N; exit 1; end if N<2 | N>9 then do; say sep er "grid size is out of range: " N; exit 1; end if isInt(seed) then call random , , seed /*use repeatability seed for RANDOM BIF*/ say sep 'Playing a ' N*N " game with a difficulity level of: " hard
- =0
do r=1 for N /* [◄] build a solution for testing. */ do c=1 for N; #= #+1; @.r.c= # /*bump number (count), define a cell. */ end /*c*/ end /*r*/ /* [↓] HARD is the puzzle difficulity*/ do hard; row= random(1) /*scramble the grid HARD # of times.*/ if row then call move random(1,N)substr('LR', random(1, 2), 1) /* ◄── move row. */ else call move substr('abcdefghi',random(1,N), 1)substr('+-',random(1,2),1) end /*hard*/ /* [↓] move col.*/ /*play 16─game until solved or quit.*/ do until done() /*perform moves until puzzle is solved.*/ call move /*get user's move(s) and validate it.*/ if errMsg\== then do; say sep er errMsg"."; iterate; end /*possible error msg?*/ end /*until*/
call show; say sep 'Congratulations! The' N**2"─puzzle is solved." exit /*stick a fork in it, we're all done. */ /*──────────────────────────────────────────────────────────────────────────────────────*/ done: #=0; do r=1 to N; do c=1 to N; #=#+1; if @.r.c\==# then return 0; end; end; return 1 isInt: return datatype( arg(1), 'W') /*return 1 if arg is a whole number. */ ghost: do r=1 for n; do c=1 for n; !.r.c= @.r.c; end /*r*/; end /*c*/; return /*──────────────────────────────────────────────────────────────────────────────────────*/ move: arg x /*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):' if x== then do if queued()==0 then do; say; call show; say ask1; say ask2 end pull x; x= space(x, 0) /*obtain a response; elide whitespace.*/ end y= 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*/ if abbrev('QUIT', x, 1) then do; say; say; say sep "quitting."; exit; end select when x == then errMsg= "nothing entered" when length(x)>2 then errMsg= "improper response: " x when num & (y <1 | y >N ) then errMsg= "row isn't in range: " y when num & (d\="L" & d\='R') then errMsg= "row shift isn't L or R: " d when let & (y <"A" | y >HI ) then errMsg= "col isn't in range: " y when let & (d\="+" & d\='-') then errMsg= "col shift isn't + or -: " d otherwise errMsg= end /*select*/ /* [↑] verify the human entered data. */ call ghost; yn= pos(y, 'ABCDEFGHI') /*create a ghost grid for easy moving. */ if isInt(y) then if d=='R' then do c=1 for N; cm= c-1; if c==1 then cm= c+N-1 @.y.c= !.y.cm end else do c=1 for N; cp= c+1; if c==N then cp= 1 @.y.c= !.y.cp end else if d=='-' then do r=1 for N; rm= r-1; if r==1 then rm= r+N-1 @.r.yn= !.rm.yn end else do r=1 for N; rp= r+1; if r==N then rp= 1 @.r.yn= !.rp.yn end return
/*──────────────────────────────────────────────────────────────────────────────────────*/ 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= ind ind ind' ' subword('a- b- c- d- e- f- g- h- i-', 1, n) HI= substr('abcdefghi', N, 1); upper HI say col ind ind ind '- means shift a column down'; say pad ind top do r=1 for N; z= r'R' " ║" /*build NxN game grid*/ do c=1 for N; z= z || right(@.r.c, 2)'║' /*build row by row. */ end /*c*/ z= z ' ' r"L" /*add rightside info.*/ if r==1 then z= z pad'L means shift a row left' /* " 1st help info.*/ if r==2 then z= z pad'R means shift a row right' /* " 2nd " " */ say pad z; if r\==N then say pad ind bar end /*r*/ say pad ind bot; say; say translate(col, '+', "-") ind ind ind '+ means shift a column up'; say return</lang>
- output when using the default inputs:
──────── Playing a 16 game with a difficulity 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
<lang ring>
- Project : Sixteen Puzzle Game
- Date : 2018/04/21
- Author : Gal Zsolt (~ CalmoSoft ~)
- Email : <calmosoft@gmail.com>
load "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 next
func 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 return
func pClock
t2 = (clock() - t1)/1000 timebtn.settext("Elapsed Time : " + t2 + " s")
func psaveEmpty
timebtn.settext("Elapsed Time : ") t1 = clock() return
func psave
if saveflag = 1 for n = 1 to 4 add(table, [pReturn[n], button[pReturn[n]].text()]) next ok
func 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() ok
func 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 ok
func 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) return
func 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() return
func 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() return
func 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() return
func 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() return
func 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() return
func 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() return
func 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() return
func 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() return
func 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() return
func 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() return
func 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() return
func 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() return
func 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() return
func 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() return
func 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() return
func 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
</lang> Output image: