重新创建经典的蛇游戏


11

挑战是使用尽可能少的字节来创建经典的Snake游戏。

要求如下:

  • 游戏必须以典型的二维布局实现。蛇应该能够在地图范围内显着生长(这确实意味着,不要将地图缩小得太小,请在此处谨慎使用)。
  • 用户可以使用您选择的键来移动蛇,但是,蛇无法重返自身(例如,如果向西移动,则不先向北或向南移动就不能向东移动)。一条蛇应该能够在所有四个方向上移动:上,下,左,右(北,南,西,东)。
  • 蛇以长度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 2012年

Answers:


2

Ruby 1.9 + SDL(341 324 316)

这是使用SDL库的Ruby版本的首次尝试。如果允许我-rsdl在命令行而不是require语句上加载SDL库,则可以节省6个字符。

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。您可以使用箭头键(或任何键,实际上,键码mod 4索引方向数组[LEFT,UP,DOWN,RIGHT])进行控制。我认为这里绝对有改进的空间,尤其是在检查死亡的IF语句中。

与以前的版本相比,我已进行了很大的改进,希望它与现在的问题精神更加契合。 我需要修正以符合规格的一件事,即食物当前可以在尾巴内产卵。 固定!

游戏结束后将分数打印到标准输出。


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

屏幕截图

Java中的蛇游戏


评论

不久前,我访问了一个名为zetcode的网站,该网站提供了一些使用Java创建经典2D游戏的教程。所提供的代码在很大程度上受到为Snake游戏提供的教程的影响...我想这时候我才刚刚开始对经典游戏进行编码,并将该教程跟随为“ T”。

稍后我将进行编辑,并添加指向可执行文件的链接,以便人们可以玩游戏。


编辑

  • 12/9/9:我无法从资源文件夹正确加载图像。我将继续解决此问题,以证明我的代码有效并且满足问题的所有条件。
  • 12/9/11:我将继续努力从资源文件中加载图片。我添加了ZetCode教程提供的图片。

太好了,我期待尝试!
mjgpy3 2012年

是否有指向可执行途中的链接:)
Drenai 2012年

@BrianBishop对不起,老兄,我从来没有弄清楚我对资源文件中的图像文件所做的错误。一切都可以编译,但是图像永远不会弹出。
罗布

2

重击:537533507 字符

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$LINESshell变量,它必须运行来源:. snake.sh。可以使用w/ a/ s/ d键控制蛇。

我知道,通过clear清除屏幕可以轻松地将其减少到493个字符,但是我更喜欢保持纯净bash,而无需使用任何外部工具。


很酷的解决方案!
mjgpy3 2012年

1

Python 2.7:869 816 818 817 816个字符

在过去的几个小时里,我一起破解了这个。它应该满足要求,并且比mjgpy3的解决方案短几个字符(尝试过,但无法缩短很多。现在我很累)。令人惊讶的是,使用像pygame这样的游戏开发库并没有使python-snake变得更短。高度赞赏如何缩短时间的建议和技巧。我希望它不太神秘。

结果如下:

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)

编辑:我可以将其减少到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
谢谢:)我也收到了细分fauklt消息。还没弄清楚。固定了分数并减小了大小:)这很有趣。
stefreak 2012年

1
您可以使绿色变深,而不是255,而是使用99,然后将其
删除

@KrystosTheOverlord哈哈,是个好点:D
stefreak
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.