傍的ASCII游戏


10

乒乓球

挑战在于以尽可能短的代码重新创建ASCII字符的经典游戏“ pong”。

要求/规格

  • “屏幕”应为45x25字符。
  • 空格实际上应该是空格。
  • 球拍应为9个等号:=========并且应位于最上面和最下面的行中(我知道原著是左右并排演奏,而不是上下演奏,但我认为这对ascii pong更好)。
  • 球可以是小写或大写o或零。
  • 任何类型的两个输入按钮(如果用户按下使输入中显示字母的键也很好,也可以),以一次左右移动播放器的一个或两个字符。
  • 球在击中桨或壁时需要以适当的角度跳动(提示:取反x或y差值)。
  • 分数应显示在输出中的某处。得分是玩家成功击球的次数。
  • 如果球未击中球员的球拍,请终止程序。
  • 应该某种AI(即使AI的球拍刚好与球的x值匹配)。
  • 球不能垂直或水平直线移动。

开始屏幕/第一帧应如下所示:

                  =========                  











                      o                      











                  =========                  
score: 0

计分 这是,因此最短的代码获胜...但是,有一些好处可以减少字符数:

  • -30个字符:根据球在球拍上的击打位置来改变球的轨迹
  • -10个字符:使游戏随着时间的推移而加速
  • -20个字符:使AI出色
  • -20个字符:避免出现任何情况,即玩家保持静止并且游戏永远进行而不会输赢(由某些轨迹和AI模式引起)
  • -20个字符:使球开始以(半)随机轨迹运动
  • -25个字符:添加重置选项

这是一个在JavaScript中没有奖金的简单例子:

//init
var x = 22,
    y = 12,
    xd = Math.random() < 0.5 ? -1 : 1,
    yd = 1,
    player = opponent = 18,
    score = 0,

//interval that runs 10x per second (minus the runtimeof one cycle)
interval = setInterval(function() {
  //move ball
  x += xd;
  y += yd;

  //move opponent
  opponent = x - 4;

  //collision with walls
  if(x <= 0 || x >= 44) xd = -xd;

  //collision with paddles
  if(y == 1) {
    if(x >= opponent && x < opponent + 9) yd = -yd;
    else {
      //you win
      clearInterval(interval);
      document.body.innerHTML = "You win!<br>Your score was: " + score;
      return;
    }
  }
  else if(y == 23) {
    if(x >= player && x < player + 9) {
      yd = -yd;
      score++;
    }
    else {
      //you lose
      clearInterval(interval);
      document.body.innerHTML = "You lose!<br>Your score was: " + score;
      return;
    }
  }

  draw();
}, 100);

function draw() {
  var body = document.body;
  body.innerHTML = "";
  for(var i = 0; i < 25; i++) {
    for(var j = 0; j < 45; j++) {
      //white space is default
      var char = " ";
      
      //ball
      if(j == x && i == y) char = "o";
      
      //paddles
      if(i === 0) {
        if(j >= opponent && j < opponent + 9) char = "=";
      }
      else if(i == 24) {
        if(j >= player && j < player + 9) char = "=";
      }
      
      body.innerHTML += char;
    }
    body.innerHTML += "<br>";
  }
  body.innerHTML += "score: " + score;
}

//key press listener for left and right movement
window.onkeydown = function() {
  if (window.event.keyCode == 37) player -= 2;
  else if(window.event.keyCode == 39) player += 2;
};
<body style="font-family: monospace; white-space: pre">
  
</body>

让游戏开始!


3
好吧,至少有人可以解释为什么他们对此表示反对吗?我真的很好奇,因为我认为这会很有趣,但是我没有太多经验。
Eric Vincent

3
可以打印出ASCII内容,但是通过键盘交互,我们必须构建一个完整的应用程序。由于许多语言不支持I / O,因此这类挑战不那么受欢迎。实现人工智能,物理。几乎像一个完整的应用程序。如果您看一下其他挑战,那么他们的一项任务就是接受(或不接受)输入并产生相关的输出。添加AI,物理和键盘互动只是挑战的
绝大部分

1
@vihan乒乓球的AI非常简单,它只需要遵循球的x值即可。即使使其可打也并不难,只需限制桨的速度即可。这个概念唯一真正的问题是键盘交互,可以用多种语言进行管理。然而,这份简报是相当模糊和开放的(考虑到我们对这里的明确性和公平性持坚决态度),而大量的奖金并没有帮助。
级圣河


2
键盘交互也必须在(重新)实现俄罗斯方块中解决,但这并没有减少任务的普及程度。(是的,我知道,那实际上是流行竞赛,不是。)我个人唯一感到不安的是奖金数额。但是当然不必取决于我的口味。
manatwork

Answers:


4

Perl,760 611 592 535 515(640-30-10-20-20-20-25)

具有所有奖励功能的控制台解决方案。
它应该可以在理解ANSI转义码(\ e [...)的任何终端上工作。在cygwin上测试。

键盘控制:
左:4
右:6
复位:8

use Term::ReadKey;ReadMode 4;END{ReadMode 0}$|++;$a=$d=45;$b=25;$h=1;$j=$l=17;$p='='x9;sub P{print"\e[@_"}sub L{$%=$l+pop;if($%>0&$%+7<$a){P"25H\e[K\e[25;$%H$p ";$l=$%}}sub U{$%=$j+pop;if($%>0&$%+7<$a){P"1H\e[K\e[1;$%H$p ";$j=$%}}sub I{$}=int rand 42;$g=8;$i=1;P"2J\ec";L}I;while(1){if($c>0){$c--}else{$c=98;$d-=$d>6}if($c%9==0){U -1if$}<$j+4;U 1if$}>$j+6};if($c%$d==0){$m=$}+$h;$n=$g+$i;$h*=-1if$m<1||$m>$a;if($n>24&$}>=$l&$}<$l+9){$i*=-1;$h=-1if$m<$l+5;$h=1if$m>$l+5;$s++}if($n<2&$}>=$j&$}<$j+9){$i*=-1}P"$g;1H\e[K";$}+=$h;$g+=$i;P"$g;$}HO"}if($k=ReadKey -1){I,if$k>6;L$k<=>5}P"26;0Hscore:$s";exit,if$g>=$b;select($\,$\,$\,0.01);I,if$g<2}

1
嘿,卢克,很喜欢这个!以为我会分享一些方法,您也许可以节省更多字符...由于您使用print了4次以上,因此设置一个新的sub并调用它应该更便宜sub p{print@_}。如果您不介意使用其他键以及您指定的键,则可以替换if(defined($k=ReadKey(-1))){L(-1)if's'eq$k;L(1)if'd'eq$k;I,if'r'eq$k}L 114<=>ord$k if$k=ReadKey -1;。这只会转换<r:-1,r:0,> r:1,这可能不是您想要的。如果你很高兴这一点,你可以用[4] [5] [6]的钥匙:L$k<=>5 if$k=ReadKey -1;
唐·黑斯廷斯

1
看起来您也可以用后缀if检查替换一些if块,或者用三元替换以节省更多,但是嵌套可能会很棘手...您可以将另一个块$d--if$d>6更改$d-=$d>6为2字节的保存,可能也可以在更多的地方工作,;$p=H.'='x9 .$"而不是节省一点钱$p="H========= "。希望其中一些有用!
Dom Hastings 2015年

1
谢谢,很高兴您喜欢它。您的技巧有助于进一步降低50个字节的空间!与奥德的d俩是邪恶的。$ d-= $ d> 6技巧看起来很奇怪。我还发现打印“ $ aH”之类的问题时,“ $ {a} H”的工作方式与bash相同。:)
LukStorms 2015年

1
是啊!使用非字母变量名称($}或其他名称)或使用裸字($a.H)可以通过几种方法解决,不确定在这种情况下是否对您有帮助。我确实注意到的一点是,sub P 如果您仅对此有一个论点,则可以这样做print"\e[@_".pop因为不必担心字段分隔符。另外,如果你正在使用数字键盘而非字母,你不需要使用ord,因为$k46因此你可以做5<=>$k替代。
唐·黑斯廷斯

1
再次感谢。没想到perl会接受像O_o这样的变量。但是它确实可以正常工作,因此重新占用了一些字节。但是不要尝试使用$!变量。然后发生奇怪的事情。
LukStorms 2015年

1

JavaScript,618字节+ HTML,99字节

好吧,这是我打过的JavaScript答案,即使在其他语言中也不可行:

var x,y,xd,yd,p,o,s,n,i,j,c,k;function a(){x=22;y=12;xd=Math.random()<.5?-1:1;yd=1;p=o=18;s=0;n=setInterval(function(){x+=xd;y+=yd;o=x-4;if(x<=0||x>=44)xd=-xd;if(y==1){if(x>=o&&x<o+9)yd=-yd;else{clearInterval(n);b.innerHTML="You Win!<br>Score: "+s;return}}else if(y==23){if(x>=p&&x<p+9){yd=-yd;s++;}else{clearInterval(n);b.innerHTML="You Lose!<br>Score: "+s;return}}d();},100);}function d(){b.innerHTML="";for(i=0;i<25;i++){for(j=0;j<45;j++){c=" ";if(j==x&&i==y)c="o"; if(i==0&&j>=o&&j<o+9)c="=";if(i==24&&j>=p&&j<p+9)c="=";b.innerHTML+=c;} b.innerHTML+="<br>";}b.innerHTML+="score: "+s;}onkeydown=function(){ k=window.event.keyCode;if(k==37)p-=2;if(k==39)p+=2;};
<button onclick="a()">start</button><div id="b"style="font-family:monospace;white-space:pre"></div>

-20和-25以获得奖金


嗯,这对我来说不太好。您仍然可以删除两个字母的变量名,用几个&&标记代替&,消除大量的;标记,之后删除不必要的空格{,甚至删除HTML中的某些引号字符。甚至更多。这只是一个猜测,但是您可能想要避免使用UglifyJS并手动缩小。:)
Chiru 2015年

6
这种方式颇为神秘。读者必须搜索663个字符的代码以进行键处理,然后可能需要STFW来找出哪些键具有代码37和39。(无论如何,在我使用的最新Firefox中,左右箭头键没有任何反应。)无法测试它,我将永远找不到您获得-20的3个可用奖金中的哪个。
manatwork 2015年
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.