ポンのアスキーゲーム


10

アスキーポン

課題は、古典的なゲーム「ピンポン」を可能な限り短いコードでASCII文字で再現することです。

要件/仕様

  • 「画面」は45x25文字にする必要があります。
  • 空白は実際には空白でなければなりません。
  • パドルは9つの等号=========である必要があります。また、一番上と一番下の行にある必要があります(オリジナルは上から下ではなく左右に再生されることはわかっていますが、これはアスキーポンに適しています。 )。
  • ボールは、小文字、大文字、oまたはゼロにすることができます。
  • 任意の種類の2つの入力ボタン(ユーザーが入力に文字を表示するキーを押しても問題ありません)は、プレーヤーのパドルを1つまたは2つのキャラクターを左右に一度に移動します。
  • ボールは、パドルや壁に当たったときに適切な角度で跳ね返る必要があります(ヒント: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つのタスクがあり、関連する出力を生成します。AI、物理学、キーボードknteractionを追加することは、課題の大部分を
占めるに過ぎません

1
@vihanピンポンのAIは非常にシンプルで、ボールのx値を追跡するだけです。それを打ち負かすことはそれほど難しいことではなく、パドルの速度を制限するだけです。この概念の唯一の本当の問題はキーボード操作であり、これは合理的なさまざまな言語で管理できます。しかし、このブリーフはどちらかと言えばあいまいでオープンであり(ここでは、あいまいさや公平さを求める人がいるのであれば)、さまざまなボーナスがそれを助けてくれません。
Level River St


2
テトリスの(再)実装でもキーボード操作を解決する必要がありましたが、それでもタスクの人気が低下することはありませんでした。(はい、私は知っています、それは実際に人気コンテストでした、これはそうではありません。)私が個人的に気になる唯一のことは、ボーナスの額です。しかし、確かに私の好みに合わせる必要はありません。
manatwork 2015

回答:


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
こんにちはLukさん、これを愛しています!私はあなたがいくつかのより多くの文字を節約できるかもしれないいくつかの方法を共有すると思います... print4回以上使用しているので、新しいサブをセットアップしてそれを呼び出す方が安くなるはずです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ブロックを後置ifチェックで置き換えるか、3進数で置き換えるとさらに節約$d--if$d>6できますが、ネストするとトリッキーになる可能性があります... $d-=$d>62バイトの節約に変更できる別のブロックがあります。いくつかの場所でも動作する可能性があり、の;$p=H.'='x9 .$"代わりに別の小さな節約があり$p="H========= "ます。これらのいくつかが役立つことを願っています!
Dom Hastings、

1
よろしくお願いします。あなたのヒントは、50バイトでさらにゴルフを進めるのに役立ちました!オードとのそのトリックは邪悪です。$ d-= $ d> 6のトリックは奇妙に見えました。「$ aH」のようなものを印刷することが問題である場合、「$ {a} H」はbashの場合と同様に機能することも発見しました。:)
LukStorms 2015

1
ああそうだ!アルファベット以外の変数名($}または何か)を使用する$a.H、またはベアワード()を使用するその周りのいくつかの方法、それがこの場合に役立つかどうかはわかりません。私は予告をした何かが、であるsub P ならば、あなただけ今までそれに引数を一つ持っている、あなたが持っている可能性print"\e[@_"の代わりに、.pop心配するフィールド区切りがないからです。あなたは文字の代わりにテンキーを使用している場合にも、あなたが使用する必要はありませんordように、$kだろう4か、6あなたができるので、5<=>$k代わりに。
Dom Hastings

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


うーん、これは私にはあまりゴルフに見えません。それでも、2文字の変数名を削除し、いくつかの&&トークンをに置き換え、&大量の;トークンを削除し、不要なスペースを削除{し、HTML内の一部の引用文字を削除することもできます。そして、おそらくもっともっと。これは単なる推測ですが、UglifyJSを回避して手動で縮小することをお勧めします。:)
Chiru

6
かなり暗号がこの方法で投稿されました。リーダーはキーの処理のために663文字のコードを検索し、次にSTFWでコード37と39を持つキーを見つける必要があります。テストできないので、利用可能な3つのボーナスのどれが-20を獲得したかはわかりません。
manatwork 2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.