Klasik yılan oyununu yeniden yarat


11

Zorluk, mümkün olduğunca az bayt kullanarak klasik Yılan oyunu oluşturmaktır.

İşte gereksinimler:

  • Oyun tipik 2 boyutlu bir düzende uygulanmalıdır. Yılan, haritanın sınırları içinde önemli ölçüde büyüyebilmelidir (bu gerçekten, haritanızı çok küçük yapmayın, takdirinizi burada kullanın).
  • Bir kullanıcı seçtiğiniz tuşları kullanarak yılanı hareket ettirebilir, ancak yılan kendi üzerine iki katına çıkamaz (örneğin Batı'ya gidiyorsa, önce Kuzey veya Güney'e gitmeden Doğu'ya gidemez). Bir yılan tüm 4 yönde seyahat edebilmelidir: yukarı, aşağı, sol, sağ (Kuzey, Güney, Batı, Doğu).
  • Yılan uzunluk 1 olarak başlar, her "yemek" nesnesini yediğinde +1 uzunluğunda büyür
  • Yiyecek nesneleri yılan tarafından işgal edilen yerler dışındaki yerlere rastgele yerleştirilir
  • Yılan kendisine veya bir duvara çarparsa oyun sona erer
  • Oyun sona erdiğinde, "skor: [skor]" görüntülenir; burada [skor] oyun sırasında yenen yiyecek öğelerinin sayısıdır. Yani, örneğin, oyun sona erdiğinde yılan 4 "yiyecek" yemişse (ve bu nedenle uzunluğu 5 ise), "Skor: 4" yazdırılır.
  • Kodunuzda açıkça tanımlanmadığı sürece sıkıştırma algoritması yoktur.

İşte benim çözümüm, 908 Bayt, 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
@ kopyalayın bazı insanlar terminallerle sınırlı olmayı sevmez.
Griffin

yılanın uzunluğu = 1 ise 'yılan çift olamaz' kuralı uygulanır mı?
Paul Prestidge

@chron, evet öyle. Her zaman, yılanlar sadece (gerçekten) iki şekilde sola ve sağa dönebilirler.
mjgpy3

Yanıtlar:


2

Ruby 1.9 + SDL (341 324 316)

SDL kitaplığını kullanarak Ruby sürümüne yönelik ilk denemeyi burada bulabilirsiniz. SDL kütüphanesini -rsdlkomut satırı üzerinde gerektiren deyim yerine yüklememe izin verilirse 6 karakter kaydedebilirim .

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}

Yılan parçaları ve yiyecek parçaları siyah pikseller kullanılarak temsil edilir, ızgara boyutu şu anda 32 * 32'dir. Ok tuşları ile kontrol edebilirsiniz (veya herhangi bir tuş gerçekten, mod 4 kod kodu yön dizisini [SOL, YUKARI, AŞAĞI, SAĞ] indeksler). Bence burada, özellikle de ölüm kontrol eden IF ifadesinde kesinlikle iyileştirme için yer var.

Bunu önceki versiyonda büyük ölçüde geliştirdim, umarım şimdi sorunun ruhuyla daha yakından eşleşir. Spesifikasyona uymak için düzeltmem gereken bir şey var, yiyecek şu anda kuyruk içinde ortaya çıkabilir. Sabit!

Oyun tamamlandıktan sonra skoru stdout'a yazdırır.


2

Java, 2343 2239

Tam olarak özlü değil, ama tüm gereksinimleri karşıladığına inanıyorum.

Yılan sınıfı

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();}}

Yönetim Kurulu sınıfı

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;}}}}

Ekran görüntüsü

java yılan oyunu


yorum

Bir süre önce Java'da klasik 2D oyunlar oluşturmak için bazı öğreticiler sağlayan zetcode adlı bir web sitesini ziyaret ettim . Sağlanan kod Yılan oyunu için sağlanan öğreticiden büyük ölçüde etkileniyor ... Sanırım şu anda klasik oyunları kodlamaya başladım ve bir 'T' öğreticisini takip ettim.

Daha sonra bir düzenleme yapacağım ve insanların oyunu oynayabilmesi için bir çalıştırılabilir dosyaya bağlantı ekleyeceğim.


DÜZENLEMELER

  • 9/9/12: Kaynak klasördeki görüntüleri düzgün şekilde yükleyemiyorum. Kodumun çalıştığını ve sorunun tüm ölçütlerini karşıladığını kanıtlamak için bu sorunu çözmeye devam edeceğim.
  • 9/11/12: Kaynak dosyadan yüklenecek resimleri almak için çalışmaya devam edeceğim. ZetCode öğreticisinden sağlanan bir resim ekledim.

Harika, denemeyi dört gözle bekliyorum!
mjgpy3

Yürütülebilir en-route bağlantı var mı :)
Drenai

@BrianBishop Üzgünüm ahbap, kaynak dosyasındaki görüntü dosyalarımla ne yaptığımı asla çözemedim. Her şey derlenir, ancak görüntüler asla açılır.
Rob

2

Bash: 537 533 507 karakter

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

$COLUMNSVe $LINESshell değişkenlerini kullandığı için , source: çalıştırılmalıdır . snake.sh. Yılan w/ a/ s/ dtuşları ile kontrol edilebilir .

Biliyorum, clearekranı temizlemek için kolayca 493 karaktere düşürülebilir , ancak bashherhangi bir harici araç kullanmadan onu saf tutmayı tercih ederim .


Çok güzel bir çözüm!
mjgpy3

1

Python 2.7: 869 816 818 817 816 Karakterler

Bunu son birkaç saatte birlikte hackledim. Gereksinimleri karşılamalı ve mjgpy3'ün çözümünden birkaç karakter daha kısa (Çok denedim, ama çok daha kısa olamazdı. Şimdi yorgunum). Şaşırtıcı bir şekilde, pygame gibi bir oyun geliştirme kütüphanesi kullanmak piton yılanını çok daha kısaltmadı. Kısaltmanın nasıl yapılacağı ile ilgili öneri ve ipuçları çok takdir edilmektedir. Umarım çok şifreli değildir.

Sonuç budur:

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: Ben 816 Byte azaltabilir, yay! :) Puan düzeltildi

EDIT2: Yanlış sürümü yanlışlıkla yapıştırdı

İşte yorumlanmış bir sürüm:

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)

"Segmentasyon hatası (çekirdek dökümü)" hata mesajını almaya devam ettim. Ve puan 1 tarafından kapalı gibi görünüyor (gerçekten büyük bir anlaşma değil. Çok güzel bir cevap olsa da.
mjgpy3

2
Teşekkürler :) Ben de Segmentation fauklt mesajı alıyorum. Henüz çözemedim. Skoru düzeltildi ve boyutu azaltıldı :) bu eğlenceli.
stefreak

1
yeşil yerine daha koyu hale getirebilirsiniz, 255 yerine 99 kullanın, o zaman bu alınan bir bayt olacaktır
KrystosTheOverlord

@KrystosTheOverlord hahah evet iyi bir nokta: D
stefreak
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.