Відтворити класичну гру зі змією


11

Завдання полягає в тому, щоб створити класичну гру Snake, використовуючи якомога менше байтів.

Ось такі вимоги:

  • Гра повинна бути реалізована у типовому двовимірному макеті. Змія повинна мати можливість значно рости в межах карти (це дійсно означає, не робіть свою карту занадто малою, використовуйте тут свій розсуд).
  • Користувач може переміщувати змію за допомогою клавіш на ваш вибір, проте змія не може подвоїтися назад (наприклад, якщо йде Захід, вона не може піти на Схід, не спершу пішовши на Північ або Південь). Змія повинна мати можливість подорожувати у всіх 4 напрямках: вгору, вниз, вліво, вправо (на північ, південь, захід, схід).
  • Змія починається з довжини 1, щоразу, коли вона їсть "харчовий" предмет, вона виростає +1 у довжину
  • Харчові предмети випадково розміщуються в інших місцях, ніж ті, що займаються змією
  • Якщо Змія вдарила себе або об стіну, гра закінчена
  • Після закінчення гри відображається буквальний "Оцінка: [оцінка]", де [оцінка] - кількість харчових продуктів, з'їдених під час гри. Так, наприклад, якщо змія з'їла 4 "страви" (і тому має довжину 5), коли гра закінчиться, "Оцінка: 4" буде надруковано.
  • Ні алгоритмів стиснення, якщо вони чітко не визначені у вашому коді.

Ось моє рішення, 908 байт, 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 деякі люди не люблять обмежуватися терміналами.
Гриффін

чи застосовується правило "змія не може подвоїтися назад", якщо змія довжиною = 1?
Пол Престиждж

@chron, так, це так. У будь-який час змії можуть лише (справді) повертати два шляхи - вліво і вправо.
mjgpy3

Відповіді:


2

Ruby 1.9 + SDL (341 324 316)

Ось перша спроба версії Ruby за допомогою бібліотеки SDL. Я можу зберегти 6 символів, якщо мені дозволено завантажувати бібліотеку SDL за -rsdlдопомогою командного рядка замість оператора вимагати.

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}

Сегменти змії та шматки їжі представлені за допомогою чорних пікселів, розмір сітки наразі становить 32 * 32. Ви можете керувати клавішами зі стрілками (або будь-якими клавішами дійсно, клавішний код 4 індексує масив напрямку [Вліво, Вгору, Вниз, Вправо]). Я думаю, що тут, безумовно, є можливість для покращення, особливо у заяві ІФ про перевірку смерті.

Я значно покращив це в порівнянні з попередньою версією, сподіваюся, що вона більше відповідає дусі питання. Є одне, що мені потрібно виправити, щоб відповідати вимогам, а саме те, що їжа в даний момент може нереститися в хвості. Виправлено!

Роздрукує рахунок до stdout після закінчення гри.


2

Ява, 2343 2239

Не зовсім стисло, але я вважаю, що це відповідає всім вимогам.

Клас змій

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

Клас дошки

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

Знімок екрана

гра змія в Яві


Коментар

Нещодавно я відвідав веб-сайт під назвою zetcode, який представив кілька навчальних посібників для створення класичних 2D ігор на Яві. На наданий код сильно впливає підручник, який був наданий для гри Snake ... Я думаю, що в цей час я тільки почав кодувати класичні ігри та дотримувався підручника до "T".

Пізніше я зроблю редагування і додам посилання на виконуваний файл, щоб люди могли грати в гру.


РЕДАКТИ

  • 9/9/12: Я не можу належним чином завантажити зображення з папки ресурсів. Я продовжую працювати над цим питанням, намагаючись довести, що мій код працює і відповідає всім критеріям питання.
  • 11.11.12: Я продовжую працювати над завантаженням картинок для завантаження з файлу ресурсу. Я додав зображення, надане з підручника ZetCode.

Чудово, з нетерпінням чекаю спробувати!
mjgpy3

Чи є посилання на виконуваний маршрут :)
Drenai

@BrianBishop Вибачте чувак, я ніколи не з'ясовував, що я неправильно роблю зі своїми файлами зображень у файлі ресурсу. Все компілюється, але зображення ніколи не спливають.
Роб

2

Bash: 537 533 507 символів

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

Як він використовує $COLUMNSі $LINESзмінні оболонки, він повинен бути запущений джерелами: . snake.sh. Керувати змією можна за допомогою клавіш w/ a/ s/ d.

Я знаю, його можна легко скоротити до 493 символів за допомогою clearочищення екрана, але я вважаю за краще зберігати його чистою bash, не використовуючи жодного зовнішнього інструменту.


Дуже круте рішення!
mjgpy3

1

Пітон 2.7: 869 816 818 817 816 Персонажі

Я зламав це разом протягом останніх кількох годин. Він повинен відповідати вимогам і на кілька символів коротший, ніж рішення mjgpy3 (Спробував важко, але не міг набагато коротше. Зараз я втомився). Дивно, але використовуючи бібліотеку для розробки ігор на зразок pygame, пітфон-змія не стала набагато коротшою. Пропозиції та поради, як скоротити її, високо оцінюються. Я сподіваюся, що це не надто вибагливо.

Це результат:

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: Я міг би скоротити її до 816 байт, так! :) Виправлено рахунок

EDIT2: випадково вставлено неправильну версію

Ось коментована версія:

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)

Я постійно отримував це повідомлення про помилку "Помилка сегментації (ядро скинуто)". І здається, що оцінка знята на 1 (не дуже вже багато. Хоча дуже класна відповідь.
mjgpy3

2
Дякую :) Я також отримую, що повідомлення про помилки сегментації. Ще не з'ясував. Виправили рахунок і зменшили розмір :) Це весело.
stefreak

1
ви можете зробити темнішим зелений, замість 255, використовувати 99, тоді цей байт буде знятий
KrystosTheOverlord

@KrystosTheOverlord hahah так гарний момент: D
stefreak
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.