2048: Difference between revisions
Content added Content deleted
m (→{{header|FutureBasic}}: Remove FutureBasic 'Output' label) |
|||
Line 9,325: | Line 9,325: | ||
} |
} |
||
</syntaxhighlight> |
</syntaxhighlight> |
||
=={{header|jq}}== |
|||
'''Works with jq, the C implementation of jq''' |
|||
'''Works with gojq, the Go implementation of jq''' |
|||
Except for trivial changes to one or two lines in the "play" function, the following |
|||
implementation is generic with respect to the number of rows and |
|||
columns. The target value can also be specified when calling `play`. |
|||
As of this writing, neither the C nor Go implementations of jq include |
|||
a built-in PRN generator and so in the following the MRG32k3a module |
|||
available at [[:Category:jq/MRG32k3a.jq|MRG32k3a.jq]] is used. |
|||
<syntaxhighlight lang="jq"> |
|||
include "MRG32k3a" {search: "."}; # see comment above |
|||
### Generic functions |
|||
def lpad($len): tostring | ($len - length) as $l | (" " * $l) + .; |
|||
# Create an m x n matrix with initial values specified by . |
|||
def matrix($m; $n): |
|||
if $m == 0 then [] |
|||
else . as $init |
|||
| if $m == 1 then [range(0;$n) | $init] |
|||
elif $m > 0 then |
|||
matrix(1; $n) as $row |
|||
| [range(0; $m) | $row ] |
|||
else error("matrix\($m);\($n)) invalid") |
|||
end |
|||
end; |
|||
### The 2048 Game |
|||
# Left-squish the input array in accordance with the game requirements for a single row |
|||
def squish: |
|||
def squish($n): |
|||
def s: |
|||
if length == 0 then [range(0;$n)|null] |
|||
elif .[0] == null then .[1:] | s |
|||
elif length == 1 then . + [range(0; $n - 1)|null] |
|||
elif .[0] == .[1] then [.[0] + .[1]] + (.[2:]|squish($n-1)) |
|||
else .[0:1] + (.[1:]|squish($n-1)) |
|||
end; |
|||
s; |
|||
squish(length); |
|||
# Input: a matrix of rows |
|||
def squish_left: |
|||
[.[] | squish]; |
|||
def squish_right: |
|||
[.[] | reverse | squish | reverse]; |
|||
def squish_up: |
|||
transpose |
|||
| [.[] | squish] |
|||
| transpose; |
|||
def squish_down: |
|||
transpose |
|||
| [.[] | reverse | squish | reverse] |
|||
| transpose; |
|||
# Gather the [i,j] co-ordinates of all the null values in the input matrix |
|||
def gather: |
|||
if length == 0 then error end |
|||
| (.[0] | length) as $cols |
|||
| [range(0;length) as $i |
|||
| range(0; $cols) as $j |
|||
| select(.[$i][$j] == null) | [$i,$j]] |
|||
| if length == 0 then error end ; |
|||
# Input: {matrix} |
|||
# Add a random 2 or 4 if possible, else error |
|||
# Output: includes .prng for the PRN generator |
|||
def add_random: |
|||
(.matrix | gather) as $gather |
|||
| ($gather | length) as $n |
|||
| if $n == 0 then error end |
|||
| if .prng == null then .prng = seed(now | tostring | sub("^.*[.]";"") | tonumber) end |
|||
| .prng |= nextFloat |
|||
| $gather[.prng.nextFloat * $n | trunc] as [$i,$j] |
|||
| .prng |= nextFloat |
|||
| (if (.prng.nextFloat) < 0.1 then 4 else 2 end) as $exmachina |
|||
| .matrix[$i][$j] = $exmachina ; |
|||
def prompt: "[ijkl] or [wasd] or q to quit or n to restart:"; |
|||
def direction: |
|||
{"i": "up", "j": "left", "k": "down", "l": "right", |
|||
"w": "up", "a": "left", "s": "down", "d": "right", |
|||
"q": "quit", |
|||
"n": "restart" |
|||
}; |
|||
# Recognize $goal as the goal |
|||
def play($goal): |
|||
# Pretty print |
|||
def pp: |
|||
.matrix[] | map(. // "." | lpad(4)) | join(" "); |
|||
def won: |
|||
any(.matrix[][]; . == $goal); |
|||
def lost: |
|||
.matrix |
|||
| (squish_left == .) and (squish_right == .) and |
|||
(squish_up == .) and (squish_down == .); |
|||
def round: |
|||
pp, |
|||
if lost then "Sorry! Better luck next time.", play($goal) |
|||
else prompt, |
|||
( (try input catch halt) as $in |
|||
| .matrix as $matrix # for checking if a move is legal |
|||
| .emit = null |
|||
| direction[$in | ascii_downcase] as $direction |
|||
| if $direction == "up" then .matrix |= squish_up |
|||
elif $direction == "down" then .matrix |= squish_down |
|||
elif $direction == "left" then .matrix |= squish_left |
|||
elif $direction == "right" then .matrix |= squish_right |
|||
elif $direction == "quit" then .emit = "bye" |
|||
elif $direction == "restart" then .emit = "restart" |
|||
else .emit = "unknown direction \($direction) ... please try again." |
|||
end |
|||
| if .emit == "bye" then .emit, halt |
|||
elif .emit == "restart" then "Restarting...", play($goal) |
|||
elif .emit != null then .emit, round |
|||
elif .matrix == $matrix then "Disallowed direction! Please try again.", round |
|||
elif won then pp, "Congratulations!", play($goal) |
|||
else add_random | round |
|||
end) |
|||
end; |
|||
{ matrix: (null | matrix(4;4))} |
|||
| .matrix[2] = [null,2,2,2] |
|||
| round; |
|||
play(2048) |
|||
</syntaxhighlight> |
|||
Invocation: jq -nRrf 2048.jq |
|||
{{output}} |
|||
<pre> |
|||
. . . . |
|||
. . . . |
|||
. 2 2 2 |
|||
. . . . |
|||
[ijkl] or [wasd] or q to quit or n to restart: |
|||
l |
|||
2 . . . |
|||
. . . . |
|||
. . 2 4 |
|||
. . . . |
|||
[ijkl] or [wasd] or q to quit or n to restart: |
|||
...etc... |
|||
</pre> |
|||
=={{header|Julia}}== |
=={{header|Julia}}== |