Recreate the classic snake Game
Ruby 1.9 + SDL (341 324 316)
Here's a first attempt at a Ruby version using the SDL library. I can save 6 characters if I'm allowed to load the SDL library using -rsdl
on the command line instead of the require statement.
require'sdl'
f=o=d=3
s=SDL::Screen.open l=32,l,0,0
r=*0..l*l
loop{f==o ?f=(r-$*).sample: $*.shift
/yU/=~"#{e=SDL::Event.poll}"&&(v=e.sym%4)&&d+v!=3&&d=v
$><<"Score #{$*.size}"&&exit if$*.index(n=o+[-1,-l,l,1][d])||n<0||n>=l*l||d%3<1&&n/l!=o/l
$*<<o=n
r.map{|i|s[i%l,i/l]=[[f,*$*].index(i)?0:255]*3}
s.flip
sleep 0.1}
The snake segments and food pieces are represented using black pixels, the grid size is currently 32*32. You can control with the arrow keys (or any keys really, the keycode mod 4 indexes the direction array [LEFT, UP, DOWN, RIGHT]). I think there's definitely room for improvement here, especially in the death-checking IF statement.
I've vastly improved this over the previous version, hopefully it more closely matches the spirit of the question now. There's one thing I need to fix to comply with the spec, which is that food can currently spawn inside the tail. Fixed!
Prints the score to stdout after the game is completed.
Bash: 537 533 507 characters
C=$COLUMNS;L=$LINES;D=-1;c=9;r=9;z=(9\ 9);l=;h=1;v=;s=1;d=1
t(){ echo -en "\e[$2;$1H$3";}
b(){ ((f=RANDOM%C+1));((g=RANDOM%L+1));for i in "${z[@]}";do [[ $f\ $g = $i ]]&&b;done;t $f $g F;}
echo $'\e[2J';b
while :;do
read -sn1 -t.1 k
case $k in
w|s)((h))&&h=&&v=${D:$k};;
a|d)((v))&&v=&&h=${D:$k};;
esac
((c+=h));((r+=v))
((c==f&&r==g&&++l))&&b
((c<1||r<1||c>C||r>L))&&break
for i in "${z[@]}";do [[ $c\ $r = $i ]]&&break 2;done
t ${z[-1]} \ ;t $c $r X
z=($c\ $r "${z[@]::l}")
done
echo $'\e[2J\e[H'Score: $l
As it uses the $COLUMNS
and $LINES
shell variables, it must be run sourced: . snake.sh
. The snake can be controlled with the w/a/s/d keys.
I know, it can be easily reduced to 493 characters by using clear
to clear the screen, but I prefer to keep it pure bash
, without using any external tool.
APL (dzaima/APL), 244 233 bytes
s←2⌿⊂2⌿25
d←?x←2⌿50
o←⍳2
G←P5.G
P5.draw←{G.bg¯1
G.fill←0
s⊢←(1↓s),⊂o+f←⊃⌽s
((⊢≢∪)s)∨~f⊂⍛∊a←⍳x:P5.exit 0⊣⍞←'Score: ',⍕2-⍨≢s
d≡f:s⊢←s,⊂f+2×o⊣d⊢←?x
(t←'center'G.rect,∘2 2)¨2×s
G.fill←'f00'
t+⍨d}
P5.kp←{o≢-n←('sdwa'⍳⍵)⊃1-↓⍬2⍴3⊤2320:o⊢←n}
Golfed from 294 → 244 bytes with the help of dzaima.
Uses WASD
controls.
Uses ⎕IO←0
(0-indexing).
The grid is 50x50
, on the default 100x100
canvas Processing uses.
Displays score to the console.
Explanation done!
Explanation
s←2⌿⊂2⌿25
snake starts at \$(25,25)\$
d←?x←2⌿50
first food position: 2 random ints in (0,50)
x←2⌿50
save (50,50) in x
o←⍳2
initial snake direction: (0,1)
G←P5.G
save namespace as G
P5.draw←{
execute the following each frame:
G.bg¯1
display white background
G.fill←0
set fill to black
s⊢←(1↓s),⊂o+f←⊃⌽s
calculate next snake position:
(1↓s)
remove the last tail segment
,⊂o+f←⊃⌽s
add direction to the front, and append that
f←⊃⌽s
assign head coordinates to f
((⊢≢∪)s)∨~f⊂⍛∊a←⍳x:(...)
check if the player has lost:
((⊢≢∪)s)∨
if snake does not match itself uniquified, or
~f⊂⍛∊a←⍳x:
head is not within 50x50 grid:
⍞←'Score: ',⍕2-⍨≢s
display the score in console, and
P5.exit 0⊣
exit, displaying nothing
d≡f:s⊢←s,⊂f+2×o⊣d⊢←?x
if head matches food, then change food position and increase snake length.
(t←'center'G.rect,∘2 2)¨2×s
draw each position of the snake
t←'center'G.rect,∘2 2
create function t
for drawing the blocks
G.fill←'f00'
set fill to red`
t+⍨d
draw the food
}
close draw loop
P5.kp←{...}
execute the following each time a key is pressed (⍵ is key name):
1-↓⍬2⍴3⊤2320
array of directions │0 1│1 0│0 ¯1│¯1 0│
('sdwa'⍳⍵)⊃
get key number, index into directions
n←
store direction in n
o≢-
if snake direction is not the opposite of n,(prevents moving backward)
o⊢←n
then change snake direction
Gameplay
(recorded at low fps)