A guy named Phil asked me to post my code, so here it is. It’s in Mathematica, so I imagine that most people will have trouble reading it. I will probably rewrite the code in a more common, faster language later.
(* Mathematica code for simulating 2048 - by Hein Hundal (Public Domain) Visit http://gabrielecirulli.github.io/2048/ for more detials. *) (* collapse[v] takes a list of values and returns a collapsed list of values where two consecutive equal values are summed into one value. *) collapse[v_List] := PadRight[ collapseAux[Cases[v, _Integer]] , 4, "."]; collapseAux[{}] = {}; collapseAux[{x_}] = {x}; collapseAux[v_List] := If[ v[[1]] == v[[2]], Prepend[ collapseAux[Drop[v, 2]], v[[1]]*2], Prepend[ collapseAux[Drop[v, 1]], v[[1]]]]; vGlobalMoves = Characters["lrud"]; mGlobalEmptyBoard = Table[".", {4}, {4}]; move[mBoard_, sMove_String] := Switch[sMove, "l", collapse /@ mBoard, "r", Reverse /@ collapse /@ Reverse /@ mBoard, "u", Transpose[ collapse /@ Transpose[ mBoard ]], "d", Reverse[ Transpose[ collapse /@ Transpose[ Reverse[ mBoard]]]], _, Throw[{"move::illeagal move", sMove}]]; (* game1Turn[ mStart_List, randFunc_, moveStrat_] Performs one turn of the game. - mStart is a 4 x4 game matrix where every elemet is either a number 2, 4, 8, ... or the string ".". - randFunc is any function that take a positive integer n as input and outputs a positive integer between 1 and n. - moveStrat is any function that takes a game board as an input and gives as an output one of the four characters u, d, l, r. - The output of game1Turn is a new board state. *) game1Turn[ mStart_List, randFunc_, moveStrat_] := Module[{sMove, mBoard, mEmpty, iSpot, iVal}, sMove = moveStrat[mStart]; mBoard = move[mStart, sMove]; (* only add a new piece if the board changed *) If[ mBoard =!= mStart, mEmpty = Position[mBoard, "."]; iSpot = randFunc[Length[mEmpty]]; (* the new board tile will either be a 4 or a 2 *) iVal = If[ randFunc[10] == 1, 4, 2]; mBoard = ReplacePart[mBoard, mEmpty[[iSpot]] -> iVal] ]; mBoard];
(* gameManyTurns - executes iDo turns of the game *) gameManyTurns[mStart_List, randFunc_, moveStrat_, iDo_Integer] := NestList[game1Turn[#, randFunc, moveStrat] &, mStart, iDo]; (******************* Display Results of Multiple Runs **********) periodTo0[m_List] := m /. "." -> 0; maxTile[m_List] := Max[Flatten[periodTo0[m]]] totalTiles[m_List] := Total[Flatten[periodTo0[ m ]]]; rand1[i_Integer] := 1 + RandomInteger[i - 1]; (* rand2[m] replaces a random entry on the board m with a 2 *) rand2[m_List] := ReplacePart[ m, (RandomInteger[3, {2}] + 1) -> 2]; runSeveralGames[ randFunc_, moveStrat_, iDo_Integer] := Module[{}, Table[ (* run a single game for 100 turns *) ten1 = gameManyTurns[rand2[mGlobalEmptyBoard], randFunc, moveStrat, 100]; (* keep going until there is not change for 50 moves *) While[ ten1[[-50]] =!= ten1[[-1]] && Length[ten1] < 10000, ten1 = Join[ten1, gameManyTurns[ten1[[-1]], randFunc, moveStrat, 100]] ]; ten2 = TakeWhile[ ten1, # =!= ten1[[-1]] &]; (* output a list {# turns of the game, tile Total, maximum tile} for each game *) {Length[ten2], totalTiles[Last[ten1]], maxTile[ten1[[-1]]]}, {iDo}]]; stats[mRes_List] := Module[{mRN = N@mRes}, {Mean[mRN], StandardDeviation[mRN], Max[mRes[[All, 3]]], Tally[mRes[[All, 3]]] // Sort}]; (******** Blind Cyclic Strategy ****************************) (* createCyclicStrategy - creates a cyclic strategy function from the string s. If s = "uddl", then the strategy function will repeat the sequence move up, move down, move down, and move left indefinitely. *) createCyclicStrategy[sMoves_String] := Module[ {exHeld, iCount = 1}, exHeld = Hold[ Function[ m, chars[[ Mod[iCount++, iStringLength] + 1]]]]; ReleaseHold[ exHeld /. {chars -> Characters[sMoves] , iStringLength -> StringLength[sMoves]}]]; testOneStrategy[] := Module[{}, stratDRDL = createCyclicStrategy["drdl"]; mRes = runSeveralGames[rand1, stratDRDL, 100]; stats[mRes]];