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)

enter image description here

Tags:

Code Golf

Game