Skip to content

Commit ad14920

Browse files
committed
Create play2048.r
Play 2048 in ascii in your R console. This is a standalone app
1 parent 1ca5149 commit ad14920

File tree

1 file changed

+127
-0
lines changed

1 file changed

+127
-0
lines changed

play2048.r

+127
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# for truly absurd fun, write 2048 for R
2+
# This will be a cheap, sloppy version at best. Use readline to get the next
3+
# direction of motion and re-draw the grid with the new numbers. Track empty cells
4+
# and fill one randomly on each cycle. Establish a "top-to-bottom" sort of algorithm
5+
# to determine which pair of 3-in-a-row get merged. And so on
6+
# figure out options later, if any
7+
# and how are points awarded? Wiki says value of new tile(s); also says
8+
# new tile might be a 4 as well as a 2. hmmm... that's an input option to do
9+
#Since it's 4x4, keep things simple by tracking cells in a 16-elt vector.
10+
## for first round, just do ascii
11+
#
12+
# TODO
13+
#
14+
#
15+
play2048<-function(brd=structure(list(score=0,brd=matrix(0,4,4)),class='brd2048') ) {
16+
17+
# init
18+
#brd<-matrix(0,4,4)
19+
if (! 'brd2048'%in%class(brd) ) stop('Input must be of class "brd2048".')
20+
score <- brd$score
21+
brd <- brd$brd
22+
# now check for newness
23+
if ( !sum(brd) ) {
24+
newspot <- sample(1:16,2)
25+
brd[newspot] <- sample(c(2,4),2,rep=TRUE,prob=c(.9,.1))
26+
score <- 0
27+
}
28+
print(brd)
29+
#it's OK for board to be full, just not full AND no legal move!
30+
# so add a comparison with "oldbrd" . In fact, a good "tag" can replace the
31+
## identical() test, I think.
32+
# probably need an initial tag value here, as
33+
# tag<-c(FALSE,FALSE,FALSE)
34+
# then the conditional could be !(sum(tag))
35+
youlose<-FALSE
36+
while (length(which(brd==0)) || !youlose ) {
37+
#bustamove
38+
oldbrd <- brd # for later comparison
39+
move<-readline('u,d,l,r,s(ave)? ')
40+
# first flipflop matrix, do move, flopflip back
41+
42+
switch(move,
43+
'u'=brd <- brd[4:1,] , # flip(brd,1),
44+
'l' = brd <- t(brd)[4:1,], #flip(t(brd),1),
45+
'r' = brd <- t(brd)[,4:1] , #flip(t(brd),2),
46+
'd' = "", #do nothing
47+
's' = {savebrd<-structure(list(score=score,brd=brd),class='brd2048'); assign('savebrd',savebrd,env=.GlobalEnv);print("Game saved to 'savebrd'");return(invisible() ) } #just to bail out
48+
)
49+
50+
getsq <- squoosh(brd)
51+
brd<-getsq$brd
52+
score <- score + getsq$score
53+
54+
# re-orient board
55+
switch(move,
56+
'u'=brd<- brd[4:1,] , #flip(brd,1),
57+
'l' = brd <- t(brd)[,4:1], #flip(t(brd),2),
58+
'r' = brd <- t(brd)[4:1,],
59+
'd' = '' ) # flip(t(brd),1) )
60+
## check that it was a legal, i.e. productive, move
61+
## or the board is full and jammed. So when the board is full,
62+
## AND the selected move caused no change, need to "call" all 3 other moves
63+
## to see if any produce a change, and if so, skip to "illegal move try again"
64+
## option.
65+
if ( identical(brd, oldbrd) ) {
66+
if(!length(which(brd==0))) {
67+
# here is where I'll need to cycle thru (u,d,l,r)!%in% move , so to speak
68+
# and if any of them get !identical, then want 'try again'
69+
trymov<- c('u','d','l','r')
70+
trymov<-trymov[! trymov%in% move]
71+
idtag<-vector(length=3)
72+
tmpbrd<-brd
73+
for( jj in 1:3) {
74+
switch(trymov[jj],
75+
'u'=tmpbrd<- tmpbrd[4:1,] , #flip(tmpbrd,1),
76+
'l' = tmpbrd <- t(tmpbrd)[,4:1], #flip(t(tmpbrd),2),
77+
'r' = tmpbrd <- t(tmpbrd)[4:1,],
78+
'd' = '' )
79+
# notice that for comparison purpboses, I don't need to reorient the temp
80+
idtag[jj]<- identical(tmpbrd,squoosh(tmpbrd)$brd)
81+
}
82+
#OK, now if idtag has any FALSEs, the game ain't over.
83+
youlose <- !(FALSE%in%idtag)
84+
if(youlose) {
85+
print("Game Over")
86+
break # get out of while loop
87+
} else print("Illegal move: try again.")
88+
} else print("Illegal move: try again.")
89+
# that finished if (!length(which(brd==0
90+
# the following "else" refers back to if (identical
91+
} else {
92+
print(brd)
93+
# add new tile. AGGGGGGGHHHHH remember what happens if the first argument
94+
# is a single integer? you get the whole damn string! use my 'cheapfix'
95+
newspot <- sample(rep(which(brd==0),2),1)
96+
brd[newspot] <- sample(c(2,4),1,prob=c(.9,.1))
97+
print("updating...")
98+
print(brd)
99+
} #end of ifelse
100+
} #end while
101+
# might be nice to return max tile as well. Notice I don't return a brd2048-class
102+
# element 'cause we only get here when the board is full and busted.
103+
return(invisible( list(score=score, maxtile=max(brd), brd=brd) ) )
104+
}
105+
106+
########### crunching engine
107+
squoosh <- function(brd) {
108+
#internal score only
109+
score<-0
110+
for (j in 1:4) {
111+
#drop column as far as possible
112+
brd[,j]<-brd[order(as.logical(brd[,j])),j]
113+
for(k in 4:2) {
114+
if(brd[k,j]==brd[(k-1),j] & brd[k,j]>0 ) {
115+
brd[(k-1):k,j]<- c(0,2*brd[k,j])
116+
# don't drop or re-squoosh here because that could add an existing '4' to
117+
# a newly minted '2+2-->4' and that's not how it works.
118+
# every collapse adds new tile val to score
119+
score <- score + brd[k,j]
120+
}
121+
}
122+
# repeat drop (but do NOT repeat sqooshing)
123+
brd[,j]<-brd[order(as.logical(brd[,j])),j]
124+
} #end all board moves
125+
126+
return(invisible(list(brd=brd,score=score) ) )
127+
}

0 commit comments

Comments
 (0)