# Graphical User Interface (GUI) with R: A Sliding Tile Game

By Allan Roberts

Here’s a version of the classic sliding tile game, programmed in R. I’ve designed a rudimentary graphical user interface (GUI) using the ‘locator’ function. To play the game, cut and paste the R script provided below onto the command line of your R console.To move a tile into the empty space, click on the tile you want to move.The goal, of course, is to return the tiles to the original position, as in the picture above.

The game will end when you close the graphics window, or if you try to make an illegal move (so be careful!).

If you want to re-start a game from a given position, use the command “TileGame(M,k=0)” where M is a 5-by-5 matrix representing the starting position, and k=0 is a parameter indicating that the tiles will not be scrambled before play. You can adjust the difficulty of the starting position with the parameter k; e.g. “TileGame(k=5)” would scramble the tiles with up to five random moves prior to play.

R Studio Instructions

#If the script below does not work in R Studio, try entering these commands before #running the script:

graphics.off( );
quartz(height = 8, width = 8);

R Script

#Sliding Tile Game
#R script written by Allan Roberts, Feb. 2013.

TileGame <- function(M=matrix(0:24,5,5,byrow=TRUE), k=200){
GetZero <- function(M){
x <- ((which(M==0)-1)%%5)+1;
y <- ((which(M==0)-1)%/%5)+1;
return(c(x,y));
}

PlotZero <- function(M){
Z <- GetZero(M);
rect(Z[2]-0.5,6-(Z[1])-0.5,Z[2]+0.5,6-(Z[1])+0.5, col=rgb(0,0,0) );
}

PlotSquare <- function(M,a,b){
rect(b-0.5,6-(a)-0.5,b+0.5,6-a+0.5, col=rgb(1,0.8,0.4),border=rgb(0,0,0) );
text(b, 6-a, M[a,b],col=rgb(0,0,0));
}

PlotGame<-function(M){
plot.new();
par(usr=c(0,6,0,6),bg=rgb(1,1,1));
rect(0.5,0.5,5.5,5.5,col=rgb(1,0.8,0.4));
for (a in 1:5) for (b in 1:5) if (M[b,a]!=0) text(a, 6-b, M[b,a]);
for (i in 0:5) lines(c(i+0.5,i+0.5),c(0.5,5.5));
for (i in 0:5) lines(c(0.5,5.5), c(i+0.5,i+0.5));
Z <- GetZero(M);
PlotZero(M);
}

GetMove <- function(){
X <- locator(1);
x <- round(X\$x);
y <- round(X\$y);
y <- 6-y;
move <- c(y,x);
}

SwitchZero <- function(M,L,Plot=TRUE){
Z <- GetZero(M);
x <- L[1];
y <- L[2];
if (x<1) return(M);
if (x>5) return(M);
if (y<1) return(M);
if (y>5) return(M);
if (sum(abs(Z-L))==1){M[Z[1],Z[2]] <-M[x,y]; M[x,y] <-0};
if (Plot==TRUE) PlotSquare(M,Z[1],Z[2]);
if (Plot==TRUE) PlotZero(M);
return(M);
}

RandomMove <- function(M, Plot=FALSE){
Z <- GetZero(M);
d <- sample(c(1,2,3,4),1);
if (d==1) move <- Z+c(1,0);
if (d==2) move <- Z+c(-1,0);
if (d==3) move <- Z+c(0,1);
if (d==4) move <- Z+c(0,-1);
M <- SwitchZero(M,move,Plot);
return(M);
}

plot.new();
par(usr=c(0,6,0,6));
if (k>0) for (i in 1:k) M <- RandomMove(M, Plot=FALSE);
previousM <- matrix(0,5,5);
PlotGame(M);
while (sum(previousM != M)>0) {previousM <- M; M <- SwitchZero(M,GetMove());}
return(M);
}

TileGame();