Buat kembali Game ular klasik

11

Tantangannya adalah membuat game Snake klasik menggunakan byte sesedikit mungkin.

Berikut persyaratannya:

  • Gim harus diimplementasikan dalam tata letak 2 dimensi yang khas. Ular harus dapat tumbuh secara signifikan dalam batas-batas peta (ini berarti, jangan membuat peta Anda terlalu kecil, gunakan kebijaksanaan Anda di sini).
  • Seorang pengguna dapat memindahkan ular menggunakan kunci pilihan Anda, namun, ular itu tidak dapat menggandakan dirinya sendiri (misalnya jika ia pergi ke Barat, ia tidak dapat pergi ke Timur tanpa terlebih dahulu pergi ke Utara atau Selatan). Seekor ular harus dapat melakukan perjalanan di semua 4 arah: atas, bawah, kiri, kanan (Utara, Selatan, Barat, Timur).
  • Ular dimulai dari panjang 1, setiap kali memakan objek "makanan", panjangnya +1
  • Objek makanan ditempatkan secara acak di lokasi selain yang ditempati oleh ular
  • Jika Snake mengenai dirinya sendiri atau tembok permainan berakhir
  • Ketika permainan telah berakhir, "Skor: [skor]" literal ditampilkan di mana [skor] adalah jumlah makanan yang dimakan selama pertandingan. Jadi, misalnya, jika ular telah makan 4 "makanan" (dan karena itu memiliki panjang 5) ketika permainan berakhir, "Skor: 4" akan dicetak.
  • Tidak ada algoritma kompresi kecuali mereka secara eksplisit didefinisikan dalam kode Anda.

Inilah solusi saya, 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
mjgpy3
sumber
1
kemungkinan duplikat dari game Recreate a 'Snake' di konsol / terminal
salin
1
@ copy beberapa orang tidak suka dibatasi pada terminal.
Griffin
apakah aturan 'ular tidak dapat kembali ganda' berlaku jika ular itu panjangnya = 1?
Paul Prestidge
@ sink, ya itu. Setiap saat, ular hanya dapat (benar-benar) berbelok ke dua arah, kiri dan kanan.
mjgpy3

Jawaban:

2

Ruby 1.9 + SDL (341 324 316)

Berikut adalah upaya pertama pada versi Ruby menggunakan perpustakaan SDL. Saya dapat menyimpan 6 karakter jika saya diizinkan memuat perpustakaan SDL menggunakan -rsdlpada baris perintah alih-alih pernyataan yang diperlukan.

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}

Segmen ular dan potongan makanan diwakili menggunakan piksel hitam, ukuran kotak saat ini 32 * 32. Anda dapat mengontrol dengan tombol panah (atau tombol apa saja, mod kode 4 indeks indeks array arah [KIRI, ATAS, BAWAH, KANAN]). Saya pikir pasti ada ruang untuk perbaikan di sini, terutama dalam pernyataan IF yang memeriksa kematian.

Saya telah jauh memperbaiki ini dibandingkan versi sebelumnya, semoga saja ini lebih cocok dengan semangat pertanyaan sekarang. Ada satu hal yang perlu saya perbaiki untuk memenuhi spesifikasi, yaitu makanan saat ini dapat muncul di dalam ekor. Tetap!

Mencetak skor ke stdout setelah pertandingan selesai.

Paul Prestidge
sumber
2

Jawa, 2343 2239

Tidak persis ringkas, tapi saya percaya itu mengikuti semua persyaratan.

Kelas ular

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

Kelas dewan

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

Tangkapan layar

game ular di java


Komentar

Beberapa waktu yang lalu saya mengunjungi situs web yang disebut zetcode yang menyediakan beberapa tutorial untuk membuat game 2D klasik di Jawa. Kode yang diberikan sangat dipengaruhi oleh tutorial yang disediakan untuk permainan Snake ... Saya pikir saat ini saya baru saja mulai mengkodekan permainan klasik dan mengikuti tutorial ke 'T'.

Saya akan mengedit nanti dan menambahkan tautan ke file yang dapat dieksekusi sehingga orang-orang dapat memainkan game.


EDIT

  • 9/9/12: Saya tidak dapat memuat gambar dengan benar dari folder sumber. Saya akan terus bekerja melalui masalah ini dalam upaya untuk membuktikan bahwa kode saya berfungsi dan memenuhi semua kriteria pertanyaan.
  • 9/11/12: Saya akan terus bekerja untuk mendapatkan gambar untuk dimuat dari file sumber. Saya menambahkan gambar yang disediakan dari tutorial ZetCode.
rampok
sumber
Bagus, saya berharap untuk mencobanya!
mjgpy3
Apakah ada tautan ke rute yang dapat dieksekusi :)
Drenai
@BrianBishop Maaf kawan, saya tidak pernah tahu apa yang saya lakukan salah dengan file gambar saya di file sumber daya. Semuanya dikompilasi, tetapi gambar tidak pernah muncul.
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

Karena menggunakan $COLUMNSdan $LINESvariabel shell, itu harus dijalankan bersumber: . snake.sh. Ular dapat dikontrol dengan tombol w/ a/ s/ d.

Saya tahu, ini dapat dengan mudah dikurangi menjadi 493 karakter dengan menggunakan clearuntuk menghapus layar, tetapi saya lebih memilih untuk tetap murni bash, tanpa menggunakan alat eksternal.

manatwork
sumber
Solusi yang sangat keren!
mjgpy3
1

Python 2.7: 869 816 818 817 816 Karakter

Saya meretas ini bersama dalam beberapa jam terakhir. Itu harus memenuhi persyaratan dan beberapa karakter lebih pendek dari solusi mjgpy3 (Berusaha keras, tetapi tidak bisa membuatnya lebih pendek. Sekarang saya lelah). Anehnya, menggunakan perpustakaan pengembangan game seperti pygame tidak membuat ular piton jauh lebih pendek. Saran dan tips bagaimana membuatnya lebih pendek sangat dihargai. Saya harap itu tidak terlalu samar.

Ini hasilnya:

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: Saya bisa menguranginya menjadi 816 Bytes, yay! :) Memperbaiki skor

EDIT2: Menyisipkan versi yang salah secara tidak sengaja

Ini adalah versi yang dikomentari:

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)
stefreak
sumber
Saya terus menerima pesan kesalahan ini "Segmentasi fault (core dumped)." Dan sepertinya skor dimatikan oleh 1 (bukan masalah besar. Tapi jawaban yang sangat keren.
mjgpy3
2
Terima kasih :) Saya mendapatkan pesan faal Segmentasi juga. Belum mengetahuinya. Memperbaiki skor dan mengurangi ukuran :) ini menyenangkan.
stefreak
1
Anda bisa membuat hijau lebih gelap, alih-alih 255, gunakan 99, maka itu akan menjadi byte yang dilepas
KrystosTheOverlord
@KrystosTheOverlord hahah poin bagus ya: D
stefreak