Erstellen Sie das klassische Schlangenspiel neu


11

Die Herausforderung besteht darin, das klassische Snake-Spiel mit möglichst wenigen Bytes zu erstellen.

Hier sind die Anforderungen:

  • Das Spiel muss in einem typischen zweidimensionalen Layout implementiert werden. Die Schlange sollte in der Lage sein, innerhalb der Grenzen der Karte erheblich zu wachsen (dies bedeutet wirklich, dass Sie Ihre Karte nicht zu klein machen, verwenden Sie hier Ihre Diskretion).
  • Ein Benutzer kann die Schlange mit Schlüsseln Ihrer Wahl bewegen, die Schlange kann sich jedoch nicht selbst verdoppeln (z. B. wenn sie nach Westen geht, kann sie nicht nach Osten gehen, ohne zuerst nach Norden oder Süden zu gehen). Eine Schlange sollte in alle 4 Richtungen reisen können: oben, unten, links, rechts (Nord, Süd, West, Ost).
  • Die Schlange beginnt mit der Länge 1 und wächst jedes Mal, wenn sie ein "Nahrungs" -Objekt frisst, um +1 an Länge
  • Nahrungsgegenstände werden zufällig an anderen Orten als den von der Schlange besetzten platziert
  • Wenn die Schlange sich selbst oder eine Wand trifft, ist das Spiel beendet
  • Wenn das Spiel beendet wurde, wird das wörtliche "Ergebnis: [Ergebnis]" angezeigt, wobei [Ergebnis] die Anzahl der während des Spiels verzehrten Lebensmittel ist. Wenn die Schlange beispielsweise am Ende des Spiels 4 "Lebensmittel" gegessen hat (und daher eine Länge von 5 hat), wird "Punktzahl: 4" gedruckt.
  • Keine Komprimierungsalgorithmen, es sei denn, sie sind explizit in Ihrem Code definiert.

Hier ist meine Lösung, 908 Bytes, Python 2.7

import random as r
import curses as c
def g(s,w,l):
 while 1:
  p=[r.randrange(0,w),r.randrange(0,l)]
  for l in s:
   if l==p:continue
  return p
s=[]
d=[0,1]
p=k=n=0
e=100
v={65:[-1,0],66:[1,0],68:[0,-1],67:[0,1]}
z=c.initscr()
w,l=z.getmaxyx()[0],z.getmaxyx()[1]
c.noecho()
z.clear()
x=g(s,w,l)
s.append([w/2,l/2])
z.nodelay(1)
q=lambda h,i:range(h,len(i))
while k!=101:
 k=z.getch()
 if k in v and not (d[0]==(v[k][0]*-1) and d[1]==(v[k][1]*-1)):d=v[k]
 f=[0,0]
 for i in q(0,s):
  if i == 0:
   f=[s[i][0],s[i][1]]
   s[i][0]+=d[0]
   s[i][1]+=d[1]
  else:s[i],f=f,s[i]
 if s[0]==x:
  n+=1
  s.append(f)
  x=g(s,w,l)
 z.clear()
 if s[0][0]>=w or s[0][1]>=l or s[0][0]<0 or s[0][1]<0:break
 for i in q(1,s):
  if s[0] == s[i]: k = 101
 for i in q(0,s):z.addch(s[i][0],s[i][1],"X")
 z.addch(x[0],x[1],"O")
 z.move(0,0)
 z.refresh()
 if d[1]!=0:c.napms(e/2)
 else:c.napms(e)
c.endwin()
print 'Score: %s'%n


1
@copy Manche Leute möchten nicht auf Terminals beschränkt sein.
Griffin

Gilt die Regel "Schlange kann nicht zurück verdoppeln", wenn die Schlange Länge = 1 ist?
Paul Prestidge

@chron, ja das tut es. Schlangen dürfen sich zu jeder Zeit nur (wirklich) in zwei Richtungen drehen, nach links und rechts.
mjgpy3

Antworten:


2

Ruby 1.9 + SDL (341 324 316)

Hier ist ein erster Versuch einer Ruby-Version unter Verwendung der SDL-Bibliothek. Ich kann 6 Zeichen speichern, wenn ich die SDL-Bibliothek -rsdlüber die Befehlszeile anstelle der require-Anweisung laden darf .

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}

Die Schlangensegmente und Lebensmittelstücke werden mit schwarzen Pixeln dargestellt, die Rastergröße beträgt derzeit 32 * 32. Sie können mit den Pfeiltasten steuern (oder mit beliebigen Tasten, der Keycode Mod 4 indiziert das Richtungsarray [LINKS, OBEN, UNTEN, RECHTS]). Ich denke, hier gibt es definitiv Raum für Verbesserungen, insbesondere in der IF-Erklärung zur Todeskontrolle.

Ich habe dies gegenüber der vorherigen Version erheblich verbessert, hoffentlich passt es jetzt besser zum Geist der Frage. Es gibt eine Sache, die ich korrigieren muss, um der Spezifikation zu entsprechen, nämlich dass Lebensmittel derzeit im Schwanz erscheinen können. Fest!

Druckt die Partitur nach Beendigung des Spiels auf stdout.


2

Java, 2343 2239

Nicht gerade prägnant, aber ich glaube, es folgt allen Anforderungen.

Schlangenklasse

import javax.swing.*;
public class S extends JFrame{
S(){add(new B());setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setSize(320,340);setVisible(true);}
public static void main(String[]a){new S();}}

Board Klasse

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class B extends JPanel implements ActionListener{
int W=300;int H=300;int DS=10;int AD=900;int RP=29;int D=140;int x[]=new int[AD];int y[]=new int[AD];int d;int ax;int ay;boolean l=false;boolean r=true;boolean u=false;boolean dn=false;boolean ig=true;Timer t;Image b;Image a;Image h;
B(){addKeyListener(new T());setBackground(Color.black);ImageIcon id=new ImageIcon(this.getClass().getResource("d.png"));b=id.getImage();ImageIcon ia=new ImageIcon(this.getClass().getResource("a.png"));a=ia.getImage();ImageIcon ih=new ImageIcon(this.getClass().getResource("h.png"));h=ih.getImage();setFocusable(true);i();}
void i(){d=3;for(int z=0;z<d;z++){x[z]=50-z*10;y[z]=50;}l();t=new Timer(D,this);t.start();}
public void p(Graphics g){super.paint(g);if(i){g.drawImage(a,ax,ay,this);for(int z=0;z<d;z++){if(z==0)g.drawImage(h,x[z],y[z],this);else g.drawImage(b,x[z],y[z],this);}Toolkit.getDefaultToolkit().sync();g.dispose();}else{g(g);}}
void g(Graphics g){String ms="Score:";Font sm=new Font("Courier",Font.PLAIN,12);FontMetrics me=this.getFontMetrics(sm);g.setColor(Color.white);g.setFont(sm);g.drawString(ms+d,(W-me.stringWidth(ms)),H);}
void c(){if((x[0]==ax)&&(y[0]==ay)){d++;l();}}
void m(){for(int z=d;z>0;z--){x[z]=x[(z-1)]; y[z]=y[(z-1)];}if(l){x[0]-=DS;}if (r){x[0]+=DS;}if(u){y[0]-=DS;}if(dn){y[0]+=DS;}}
void cc(){for(int z=d;z>0;z--){if((z>4)&&(x[0]==x[z])&&(y[0]==y[z])){ig=false;}}if(y[0]>H){ig=false;}if(y[0]<0){ig=false;}if(x[0]> W){ig=false;}if(x[0]<0){ig=false;}}
void l(){int r=(int)(Math.random()*RP);ax=((r*DS));r=(int)(Math.random()*RP);ay=((r*DS));}
public void actionPerformed(ActionEvent e){if(ig){c();cc();m();}repaint();}
class T extends KeyAdapter{public void keyPressed(KeyEvent e){int k=e.getKeyCode();if((k==KeyEvent.VK_LEFT)&&(!r)){l=true;u=false;dn=false;}if((k==KeyEvent.VK_RIGHT)&&(!l)){r=true;u=false;dn=false;}if((k==KeyEvent.VK_UP)&&(!dn)){u=true;r=false;l=false;}if((k==KeyEvent.VK_DOWN)&&(!u)){dn=true;r=false;l=false;}}}}

Bildschirmfoto

Schlangenspiel in Java


Kommentar

Vor einiger Zeit besuchte ich eine Website namens Zetcode, die einige Tutorials zum Erstellen klassischer 2D-Spiele in Java enthielt . Der bereitgestellte Code ist stark von dem Tutorial beeinflusst , das für das Snake-Spiel bereitgestellt wurde ... Ich glaube, zu diesem Zeitpunkt habe ich gerade angefangen, klassische Spiele zu codieren, und bin dem Tutorial zu einem 'T' gefolgt.

Ich werde später eine Bearbeitung vornehmen und einen Link zu einer ausführbaren Datei hinzufügen, damit die Leute das Spiel spielen können.


EDITS

  • 09.09.12: Ich kann die Bilder nicht ordnungsgemäß aus dem Ressourcenordner laden. Ich werde dieses Problem weiter bearbeiten, um zu beweisen, dass mein Code funktioniert und alle Kriterien der Frage erfüllt.
  • 9/11/12: Ich werde weiter daran arbeiten, dass die Bilder aus der Ressourcendatei geladen werden. Ich habe ein Bild aus dem ZetCode-Tutorial hinzugefügt.

Großartig, ich freue mich darauf, es zu versuchen!
mjgpy3

Gibt es einen Link zur ausführbaren Datei unterwegs :)
Drenai

@BrianBishop Entschuldigung, Alter, ich habe nie herausgefunden, was ich mit meinen Bilddateien in der Ressourcendatei falsch gemacht habe. Alles wird kompiliert, aber die Bilder werden nie angezeigt.
Rob

2

Bash: 537 533 507 Zeichen

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

Da es die Variablen $COLUMNSund $LINESshell verwendet, muss es als Quelle ausgeführt werden : . snake.sh. Die Schlange kann mit den Tasten w/ a/ s/ gesteuert werden d.

Ich weiß, dass es durch clearLöschen des Bildschirms leicht auf 493 Zeichen reduziert werden kann , aber ich bevorzuge es, es rein zu halten bash, ohne ein externes Werkzeug zu verwenden.


Sehr coole Lösung!
mjgpy3

1

Python 2.7: 869 816 818 817 816 Zeichen

Ich habe das in den letzten Stunden zusammen gehackt. Es sollte die Anforderungen erfüllen und ist ein paar Zeichen kürzer als die Lösung von mjgpy3 (hart ausprobiert, aber nicht viel kürzer. Jetzt bin ich müde). Überraschenderweise hat die Verwendung einer Spieleentwicklungsbibliothek wie Pygame die Python-Schlange nicht viel kürzer gemacht. Vorschläge und Tipps, wie man es kürzer macht, werden sehr geschätzt. Ich hoffe es ist nicht zu kryptisch.

Das ist das Ergebnis:

import pygame as p
from random import randint as r
p.init();l=20
c=p.time.Clock()
dp=p.display;w=p.display.set_mode((500,)*2)
C=p.Color;b=C(0,0,0);g=C(0,99,0)
D=(0,1);U=(0,-1);L=(-1,0);R=(1,0)
S=[R];d=R;n=[]
O=lambda t:{U:D,R:L,D:U,L:R}[t]
def Q(e):print "Score: %i"%(len(S)-1);p.quit()
def K(e):global d;_={276:L,273:U,274:D,275:R}.get(e.key,(0,0));d=not _==O(d) and _ or d
def N(S):[p.draw.rect(w,g,[x[0]*l,x[1]*l,l,l]) for x in S+n] 
def M():n=(r(0,24),r(0,24));return n not in S and n or M()
A=lambda s,o:tuple(x+y for x,y in zip(s,o))
n=[M()] 
while True:
 w.fill(b);[{12:Q,2:K}.get(e.type,lambda e:e)(e) for e in p.event.get()]
 if not (0<=S[-1][0]<25 and 0<=S[-1][1]<25) or A(S[-1],d) in S: Q(e) 
 if A(S[-1],d) in n: S.append(A(S[-1],d));n=[M()]
 else: S.append(A(S[-1],d));S.pop(0)
 N(S);dp.update();c.tick(6)

EDIT: Ich könnte es auf 816 Bytes reduzieren, yay! :) Die Punktzahl wurde korrigiert

EDIT2: Versehentlich die falsche Version eingefügt

Hier ist eine kommentierte Version:

import pygame as p
from random import randint as r

# initialize pygame
p.init()

# the game consists of 25*25 blocks,with each block 20*20 pixels
l=20

# initialize the main loop clock
c=p.time.Clock()

# open the window
dp=p.display;w=p.display.set_mode((500,)*2)

# define black and green colors
C=p.Color;b=C(0,0,0);g=C(0,99,0)

# Directions of the snake: down, up, left, right
D=(0,1);U=(0,-1);L=(-1,0);R=(1,0)

# S is the snake, d is the current direction and n is the array of foods
S=[R];d=R;n=[]

# get the opposite direction of a direction to forbid double backing
O=lambda t:{U:D,R:L,D:U,L:R}[t]

# print the score and quit
def Q(e):print "Score: %i"%(len(S)-1);p.quit()

# update the direction (this is a key press handler)
def K(e):global d;_={276:L,273:U,274:D,275:R}.get(e.key,(0,0));d=not _==O(d) and _ or d

# draw the snake and food boxes
def N(S):[p.draw.rect(w,g,[x[0]*l,x[1]*l,l,l]) for x in S+n]

# place new food on the map not colliding with the snake
def M():n=(r(0,24),r(0,24));return n not in S and n or M()

# A((1,1), (-2, 1)) -> (-1,2)
A=lambda s,o:tuple(x+y for x,y in zip(s,o))

# initialize food array
n=[M()]

while True:
 # fill the screen black
 w.fill(b)
 # get quit or key press events and execute the event handlers
 [{12:Q,2:K}.get(e.type,lambda e:e)(e) for e in p.event.get()]

 # check if snake hits map boundaries or itself
 if not (0<=S[-1][0]<25 and 0<=S[-1][1]<25) or A(S[-1],d) in S: Q(e)

 # check if snake is eating food at the moment and append one to the snake's length
 if A(S[-1],d) in n: S.append(A(S[-1],d));n=[M()]

 # move the snake in the current direction
 else: S.append(A(S[-1],d));S.pop(0)

 # draw the map and limit the main loop to 6 frames per second
 N(S);dp.update();c.tick(6)

Ich erhielt immer wieder die Fehlermeldung "Segmentierungsfehler (Core Dumped)". Und es scheint, als ob die Punktzahl um 1
abweicht

2
Danke :) Ich bekomme auch diese Segmentierungs-Fauklt-Nachricht. Ich habe es noch nicht herausgefunden. Die Punktzahl wurde korrigiert und die Größe reduziert :) Das macht Spaß.
Stefreak

1
Sie könnten das Grün dunkler machen, anstatt 255, verwenden Sie 99, dann wird das ein Byte entfernt
KrystosTheOverlord

@KrystosTheOverlord hahah ja guter Punkt: D
Stefreak
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.