탁구의 ASCII 게임


10

아씨 퐁

문제는 가능한 짧은 코드로 ASCII 문자로 된 고전 게임 "퐁"을 재현하는 것입니다.

요구 사항 / 사양

  • "화면"은 45x25 자 여야합니다.
  • 공백은 실제로 공백이어야합니다.
  • 패들은 9 등호 =========여야합니다. 가장 맨 위와 맨 아래 행에 있어야합니다. ).
  • 공은 소문자 또는 대문자 o이거나 0 일 수 있습니다.
  • 플레이어의 패들을 한 번에 한두 문자 씩 좌우로 움직이기 위해 어떤 종류의 두 개의 입력 버튼 (사용자가 입력에 문자를 표시하는 키를 눌러도 괜찮습니다).
  • 패 들이나 벽에 부딪 칠 때 공은 적절한 각도로 튀어 나와야합니다 (힌트 : 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, 물리 구현. 본격적인 응용 프로그램과 거의 같습니다. 다른 도전 과제를 살펴보면 하나의 작업이 입력을 받거나받지 않고 관련 출력을 생성합니다. AI, 물리 및 키보드 knteraction 추가는 도전을위한 많은 방법입니다.
Downgoat

1
@vihan pong의 AI는 매우 간단합니다. 공의 x 값을 따라야합니다. 이길 수 있도록 만드는 것조차 그렇게 어렵지는 않습니다. 패들 속도를 제한하십시오. 이 개념의 유일한 진짜 문제는 키보드 인터랙션인데, 이는 합리적인 다양한 언어로 관리 될 수 있습니다. 그러나 브리핑은 모호하고 개방적이며 (여기서는 우리가 모호하지 않고 공평 함을 유지하는 사람들에게 주어짐), 다양한 보너스가 도움이되지 않습니다.
Level River St


2
(Re) Iteementinging Tetris 에서도 키보드 상호 작용을 해결해야 했지만 작업의 인기를 떨어 뜨리지 않았습니다. (그렇습니다, 그것은 실제로 인기있는 경연 대회였습니다 , 이것은 아닙니다.) 개인적으로 혼란스러워하는 것은 보너스의 양입니다. 그러나 확실히 내 취향에 달하지 않아도됩니다.
manatwork

답변:


4

펄, 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 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;.
Dom Hastings

1
또한 접미사 if검사로 블록을 몇 개 교체하거나 더 절약하기 위해 3 진으로 대체 할 수 있지만 중첩으로 까다로울 수 있습니다 ... 2 바이트 절약 $d--if$d>6$d-=$d>6위해 변경할 수있는 또 다른 블록 이 있습니다. 몇 군데 더 많은 곳에서 작동 할 수 있으며 또 다른 작은 절약이 ;$p=H.'='x9 .$"대신됩니다 $p="H========= ". 이것들 중 일부가 유용하기를 바랍니다!
Dom Hastings

1
고마워, 당신이 그것을 좋아 기쁘다. 당신의 팁은 50 바이트로 더 많이 골프를 치는 데 도움이되었습니다! ord와의 트릭은 사악합니다. $ d-= $ d> 6 트릭은 너무 이상해 보였습니다. 또한 "$ aH"와 같은 것을 인쇄 할 때 "$ {a} H"가 bash에서와 같이 작동한다는 것을 발견했습니다. :)
LukStorms

1
아 그래! 알파벳이 아닌 변수 이름 ( $}또는 다른 것)을 사용하거나 베어 워드 ( $a.H) 를 사용하는 몇 가지 방법 이이 경우 도움이 될지 확실하지 않습니다. 내가 알아 차린 것은sub P 경우 당신은 오직 그것 하나 개의 인자를 가지고, 당신이 수 print"\e[@_"대신 .pop걱정에 필드 분리가 없을 것이기 때문이다. 대신 문자의 숫자 키패드를 사용하는 경우 또한, 당신은 사용할 필요가 없습니다 ord같은 $k4또는 6당신이 할 수 있도록 5<=>$k대신.
Dom Hastings

1
다시 감사합니다. 펄이 O_o와 같은 변수를 받아 들일 것이라고 생각하지 않았습니다. 그러나 작동하지만 몇 바이트가 그에 의해 다시 채워졌습니다. 그러나 $를 사용하지 마십시오! 변하기 쉬운. 그러면 이상한 일이 일어납니다.
LukStorms

1

자바 스크립트, 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

6
상당히 비밀스러운 방식으로 게시했습니다. 독자는 키 처리를 위해 663 자 코드를 검색 한 다음 STFW에서 코드 37과 39를 가진 키를 찾아야합니다. (어쨌든, 내가 사용하는 최신 Firefox에서는 왼쪽 및 오른쪽 화살표 키에 대한 반응이 없습니다.) 그것을 테스트 할 수 없다는 것은 당신이 -20을 획득 한 3 가지 보너스 중 어떤 것을 찾지 못할 것입니다.
manatwork
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.