シンプルなたまごっち/ギガペットを作ろう!


9

たまごっちとギガペットは、小さな仮想ペットを模した小型電子機器でした。このペットには、健康、空腹などのいくつかの統計がありました。
私は最近この例を書きました:

import msvcrt,os,sys;d=m=100;h=s=t=p=0;f=10
while 1:
 os.system('cls'if os.name=='nt'else'clear');print("health:",d,"\nhunger:",h,"\nsleep:",s,"\nfood:",f,"\npotions:",p,"\nmoney:",m);t+=1
 if msvcrt.kbhit():
  k=ord(msvcrt.getch())
  if k==102 and h>8 and f:f-=1;h-=9
  if k==115:s=0
  if k==112 and p:p-=1;d+=9
  if k==98 and m>8:m-=9;p+=1
  if k==116 and m>8:m-=9;f+=1
 if t>99:
  t=0;h+=1;s+=1
  if s>80:s=0;h+=9
  if h>80:d-=1
  if d<1:sys.exit(0)
  if d>79:m+=1

これは467バイトの骨のない仮想ペットです!それから私は、ゴルフのプロがどれほどうまくやれるか疑問に思ったので、今、挑戦しました。

チャレンジ

仮想ペットの6つの統計を追跡するプログラムを作成し、それらを時間の経過とともにユーザー入力に応じて更新します。統計は、健康とお金(100から始まる)、食べ物(10から始まる)、空腹、睡眠、およびポーション(0から始まる)です。

プログラムは、次のイベントに応答して値を更新する必要があります。

  • プログラムが入力を受け取っていない間、プログラムは定期的に更新を実行する必要があります(更新の間隔は0.5秒以上1秒以下にする必要があります)。各更新は次のことを行います。

    • 空腹と睡眠はそれぞれ1増加します。
    • 空腹度が80以上の場合、ヘルスは1減少します。
    • 睡眠が80以上の場合は0にリセットされ、空腹はさらに9増加します。
    • 体力が80以上の場合、お金は1増加します。
    • Healthが0の場合、プログラムは終了します。
  • プログラムは、ユーザーが次のキーを押したときにも即座に応答する必要があります(つまり、標準入力から読み取るだけでなく、押されているキーを検出してすぐに応答できる言語機能またはライブラリを使用する必要があります)。次のアクション:

    • f:飢餓が8より大きく、食料がゼロ以外の場合、食料は1減少し、飢餓は9減少します。
    • s:スリープは0にリセットされます。
    • p:ポーションがゼロより大きい場合、ポーションは1減少し、ヘルスは9増加します。
    • b:Moneyが8より大きい場合、Moneyは9減少し、ポーションは1増加します。
    • t:Moneyが8より大きい場合、Moneyは9減少し、Foodは1増加します。

統計の値が変わるときはいつでも、フォームに画面に表示する必要があります。6つすべての統計は、それらのいずれかが変更されるたびに表示する必要があります。また、表示内の統計は、コンマまたは改行で区切る必要があります。Stat: value

この課題は、通常の規則に従います。上記の仕様に準拠する最短のプログラムが優先されます。(いつものように、言語がコンテストより新しい場合、提出物は非競合としてマークする必要があります。)


あなたは、開始統計が何であるかを言わない
— Blue

1
出力は「読みやすい方法」でなければならず、あいまいであるため、「1秒に1回」です。チャレンジをサンドボックスに送信して、メインに投稿する前にフィードバックを得て改善する必要があります...
— FlipTack

1
これはどのように不明確ですか?それ自体が不明確なため、詳細が不明確だったといいのですが。
— ender_scythe

2
サンドボックスはすでに答えがあるので、もう役に立ちません。これを不明確とマークした人は、なぜ自分が不明瞭であるのかではなく、なぜ不明瞭であるかを言うべきです。
— ender_scythe 2016年

1
@BlueEyedBeast(および他の近い有権者)私は不明確な点についても知りたいです。元のバージョンにはいくつかの重大な問題がありましたが、編集によって修正されたようです。少なくとも、Carcigenicateと私は提出物を提供するのに十分明確でした。不明な点について詳細を共有して、ender_scytheが改善できるようにします。
— レイ

回答:


6

C、424 406 386 357バイト

#define x(a,b,c)if(*#a==C){if(b>8){c-=9;}Z=0;}
L,M=100,H,S=-1,F=10,P,Z,C;t(){H++;S++;L-=H>79;if(S>79)S=0,H+=9;Z=1/L/2;alarm(1);}main(){nodelay(initscr(),L=M);signal(14,t);for(t(H=S);C=getch();Z=Z||printf("\rhealth: %d,hunger: %d,sleep: %d,food: %d,potions: %d,money: %d\n",L,H,S,F,P,M)){x(s,9,S=9;S)x(p,P+8,P--;L+=18;L)x(f,H,F--;H)x(b,M,P++;M)x(t,M,F++;M)}}

問題仕様の生の入力と非同期更新の必要性に感謝します。これにはncursesのセットアップとシグナルハンドラーからのオーバーヘッドが必要ですが、専用のゴルフ言語のいずれかで(うまくいけば)自動的に勝てないという難題が時々発生するのは素晴らしいことです。

ゲームオーバーがどのように表示されるかを正確に指定しなかったため、これは「浮動小数点例外(コアダンプ)」という伝統的なたまごっちの死の叫びで消えてしまいます。

未ゴルフ

/* Playing a bit fast and loose with the prototyping rules by omitting these;
 * none of the functions I'm using from them *exactly* match the default
 * prototype of `int f();`
 */
//#include <curses.h>
//#include <stdio.h>
//#include <signal.h>
//#include <unistd.h>

#define x(a,b,c)if(*#a==C){if(b>8){c-=9;}Z=0;}
L,M=100,H,S=-1,F=10,P,Z,C;

t() {
    H++;
    S++;
    L-=H>79;
    if(S>79)S=0,H+=9;
    Z=1/L/2;//0 if L>0. otherwise the pet dies of a floating point error
    alarm(1);
}

main(){
    nodelay(initscr(),L=M);
    signal(14,t);
    for(t(H=S); C=getch(); Z=Z||printf("\rhealth: %d,hunger: %d,sleep: %d,food: %d,potions: %d,money: %d\n",L,H,S,F,P,M)){
        x(s,9,S=9;S)
        x(p,P+8,P--;L+=18;L)
        x(f,H,F--;H)
        x(b,M,P++;M)
        x(t,M,F++;M)
    }
}

2

PHP、396413バイト

(Dang、最初のコードゴルフエントリをバイトカウントで編集する必要がありました。意図したとおりの規則に実際には準拠していなかったため、sleep()呼び出しを削除するように編集しました。)

非ブロッキングSTDINにはUNIX系のOSが必要です。奇妙なことに、switch / caseを使用した場合と、カスケードif / elseを使用した場合のソースコードは短くなりましたが、その後の圧縮バージョンは長くなりました。

<?eval(gzinflate(base64_decode('bY5BT8MwDIXv/Ao0WWujtVJ7YmtITwiNAwhp3KutOE20pImWVGxa999J1IEAcbH87O892wlUqsEjtmnivD/d5rLd9qZPCHX+gFvdOPTNTpl2L/su3bw9PL1kBaEwMHAMLCsocFaGKhjo0BT0Q0iFaUnO4JmXGlPyPZI8TWHPeIe+nbIIGccJqsGTXbi4p4EKEEt4Qs6xH+rlfA6c5DnwEYacregFlcMvziUk/FLQnzN79drosiOIxV/X7kroeklAh9BxsQD7m/H/MXxi4iKoob5bxRuCTtpFHd8Jn8ab0S7iLOz0pO5LgkfpQ0wrzGyNW+VFBSJ7Nj2eKtDZozHvFfBsPfQdHioYso1CtBW47NV4aXpXgb2Z0csn')));

非ゴルフ:

<?
shell_exec('stty -icanon');
stream_set_blocking(STDIN, 0);
$u = $s = $p =0;
$f = 10;
$h = $m = 100;
while(1) {
    $t=time();
    while(1)
        if (($k = fgetc(STDIN)) || time() > $t)
            break;
    if ($k == 'f'){
        if ($u > 8 && $f) --$f | $u -= 9;
    } elseif ($k == 's')
        $s = 0;
    elseif ($k == 'p') {
        if ($p) --$p | $h += 9;
    } elseif ($k == 'b') {
        if ($m > 8) $m -= 9 | ++$p;
    } elseif ($k == 't') {
        if ($m > 8) $m -= 9 | ++$f;
    } else {
        if (++$u > 79) --$h;
        if (++$s > 79) $s = 0 | $u += 9;
        if ($h > 79) ++$m;
        if ($h < 1) exit;
    }
    echo"Health:$h,Money:$m,Food:$f,Hunger:$u,Sleep:$s,Potions:$p\n";
}

これは、「ユーザーが次のキーを押したときにすぐに応答する」わけではありません。sleep(1)入力を処理する前に、への呼び出しが戻るまで待機します。次の更新を行う前に、キューに入れられたコマンドを処理するため、問題ない可能性があります。
— Ray

ええ、指摘しました。そこの言葉遣いは漠然としていたので、この方法はより短かったので、私は解釈にある程度の自由をとりました。:)今日時間があれば、別のソリューションをタイミングループでコーディングし、両方を検討のために提示します。
— Alex Howansky

2

Mathematica、374バイト

h=m=100;f=10;g=s=p=0;RunScheduledTask[g++;s++;If[g>79,h--];If[s>79,s=0;g+=9];If[h>79,m++];If[h<1,Quit[]]];Dynamic@Row[{EventHandler[InputField[],"KeyDown":>Switch[CurrentValue@"EventKey","f",If[g>8&&f>0,f--;g-=9],"s",s=0,"p",If[p>0,p--;h+=9],"b",If[m>8,m-=9;p++],"t",If[m>8,m-=9;f++]]],"
Health: ",h,"
Money: ",m,"
Food: ",f,"
Hunger: ",g,"
Sleep: ",s,"
Potions: ",p}]

改行は文字列の改行文字であるため重要RowですColumn。そのため、の代わりに使用できます。Mathematicaノートブックでこれを評価すると、次のように見えるはずです:

たまごっちシミュレーション

入力フィールドをクリックして、すばやく(1秒未満で)文字をDynamic入力してから、入力フィールドを更新する必要があります。EventHandlerがの要素ではなく独自のセルにある場合、この頭痛は完全に回避できますRowが、バイト数を大幅に増やす.nbファイルとしてプログラムを保存する必要があります。


よくやった!私はCurrentValue[EvaluationNotebook[], NotebookEventActions] = {"KeyDown" :> Switch[CurrentValue@"EventKey", "f", If[g > 8 && f > 0, f--; g -= 9], "s", s = 0, "p", If[p > 0, p--; h += 9], "b", If[m > 8, m -= 9; p++], "t", If[m > 8, m -= 9; f++]]};...のような構造を使用するつもりでした。これにより、入力フィールドをクリックする必要がなくなります。, PassEventsDown -> Trueそのコードの最後にオプションを追加すると、ノートブックの編集を続行できますが、バイトを節約するために最後に削除できます:)
— Greg Martin

ありがとう、それはまさに私が最初に探していた機能です!残念ながら、私が現在持っているものよりも長いようです。
— ngenisis

2

C#6、567 563バイト

using System;using System.Threading;class T{int L,M,F=10,H,S,P;static void Main(){T t=new T();}T(){M=L=100;var W=new Thread(new ThreadStart(Q));W.Start();while(1>0){var r=Console.Read();bool B=0>1,K=1>0;if(r=='f'&H>8&F>0){F--;H-=9;B=K;}if(r=='s'){S=0;B=K;}if(r=='p'&P>0){P--;L+=9;B=K;}if(r=='b'&M>8){M-=9;P++;B=K;}if(r=='t'&M>8){M-=9;F++;B=K;}if(B)p();}}void Q(){while(1>0){H++;S++;if(H>79)L--;if(S>79){S=0;H+=9;}if(L>79)M++;L*=L/L;p();Thread.Sleep(500);}}void p(){Console.Write($"\nhealth: {L}\nhunger: {H}\nsleep: {S}\nfood: {F}\nmoney: {M}\npotions: {P}\n");}}

非ゴルフ:

using System;
using System.Threading;
class T
{
    int L,M,F=10,H,S,P;
    static void Main()
    {
        T t=new T();
    }
    T()
    {
        M=L=100;
        var W=new Thread(new ThreadStart(Q));
        W.Start();
        while(1>0)
        {
            var r=Console.Read();
            var B=0>1;
            if(r=='f'&H>8&F>0){F--;H-=9;B=1>0;}
            if(r=='s'){S=0;B=1>0;}
            if(r=='p'&P>0){P--;L+=9;B=1>0;}
            if(r=='b'&M>8){M-=9;P++;B=1>0;}
            if(r=='t'&M>8){M-=9;F++;B=1>0;}
            if(B)p();
        }
    }
    void Q()
    {
        while(1>0)
        {
            H++;S++;
            if(H>79)L--;
            if(S>79){S=0;H+=9;}
            if(L>79)M++;
            L*=L/L;
            p();
            Thread.Sleep(500);
        }
    }
    void p()
    {
        Console.Write($"\nhealth: {L}\nhunger: {H}\nsleep: {S}\nfood: {F}\nmoney: {M}\npotions: {P}\n");
    }
}

1

Clojure、1224 702バイト

V2

すべてのアトムが状態オブジェクト内にあるのではなく変数を失うようにしました。それだけで多くのコードが不要になりました。また、ショートカット関数a!を作成s!し、atoms簡単な関数を追加および削除しました(Clojureにはこれらの演算子がないため、基本的に+=およびとして機能し-=ます)。

atomキー入力をに統合できれば、おそらくs を省くことができることに気づきましたloop。私は見なければならないでしょう。

(ns bits.golf.pet.v2.petms)(def h(atom 100))(def j(atom 0))(def s(atom 0))(def f(atom 10))(def p(atom 0))(def m(atom 100))(defn a[sa n](swap! sa #(+ % n)))(defn v[sa n](swap! sa #(- % n)))(defn c[](a j 1)(a s 1)(if(>=@j 80)(v h 1))(if (>=@s 80)(do(reset! s 0)(a j 9)))(if(>= @h 80)(a m 1)))(defn l[k](case k\f(if(> @j 8)(do(v f 1)(v j 9)))\s(reset! s 0) \p(if(>@p 0)(do(v p 1)(a h 9)))\b(if(> @m 8)(do(v m 9)(a p 1)))\t(if(>@m 8)(do(v m 9)(a f 1)))nil))(defn b[](.start(Thread.^Runnable(fn[](while(>@h 0)(l(first (read-line))))))))(defn -main[](b)(while(>@h 0)(Thread/sleep 500)(c)(println(str"Health: "@h"\nHunger: " @j"\nSleep: "@s"\nFood: "@f"\nPotions: "@p"\nMoney:"@m"\n")))(println"You died!\n"))

非ゴルフ:

(ns bits.golf.pet.v2.pet)

; 100 0 0 10 0 100
(def he (atom 100))
(def hu (atom 0))
(def sl (atom 0))
(def fo (atom 10))
(def po (atom 0))
(def mo (atom 100))

(defn a! [sa n]
  (swap! sa #(+ % n)))

(defn s! [sa n]
  (swap! sa #(- % n)))

(defn apply-rules []
    (a! hu 1)
    (a! sl 1)
    (if (>= @hu 80)
      (s! he 1))
    (if (>= @sl 80)
      (do
        (reset! sl 0)
        (a! hu 9)))
    (if (>= @he 80)
      (a! mo 1)))

(defn handle-keypress [k]
    (case k
      \f (if (> @hu 8)
           (do
             (s! fo 1)
             (s! hu 9)))
      \s (reset! sl 0)
      \p (if (> @po 0)
           (do
             (s! po 1)
             (a! he 9)))
      \b (if (> @mo 8)
           (do
             (s! mo 9)
             (a! po 1)))
      \t (if (> @mo 8)
           (do
             (s! mo  9)
             (a! fo 1)))
      nil))


(defn start-listener []
  (.start
    (Thread. ^Runnable
      (fn []
        (while (> @he 0)
            (handle-keypress (first (read-line))))))))

(defn -main []
  (start-listener)
  (while (> @he 0)
    (Thread/sleep 500)

    (apply-rules)

    (println (str
               "Health: " @he "\n"
               "Hunger: " @hu "\n"
               "Sleep: " @sl "\n"
               "Food: " @fo "\n"
               "Potions: " @po "\n"
               "Money:" @mo "\n")))

  (println "You died!\n"))

V1

ああ親愛なる神。ここには間違いなく改善の余地があります。この種の問題は副作用で最も簡単に実行でき、Clojureは機能atomしているため、sを乱用して必要なコードの量を減らしています。残念ながら、私は計画を立てていなかったので、それは今のところ偶然のようなものです。私はすでにいくつかのアイデアを縮小しました。

それは完全なプログラムです。を実行すると実行できます-main。

(ns bits.golf.pet)(defrecord S[he hu sl fo po mo])(def new-state(->S 100 0 0 10 0 100))(def state(atom new-state))(defn update![sa k f](swap! sa #(update % k f)))(defn apply-rules[s](let [s' (atom s)u! #(update! s' %1 %2)g #(get @s' %)](u! :hu inc)(u! :sl inc)(if(>=(g :hu)80)(u! :he dec))(if(>= (g :sl)80)(do(u! :sl (fn[_]0))(u! :hu #(+ % 9))))(if(>=(g :he)80)(u! :mo inc))@s'))(defn get-input [](let [raw (read-line)](first raw)))(defn handle-keypress[s k](let [s'(atom s)u! #(update! s' %1 %2)g #(get @s' %)](case k\f(if (> (g :hu)8)(do(u! :fo dec)(u! :hu #(- % 9))))\s(u! :sl (fn [_] 0))\p(if(> (g :po)0)(do(u! :po dec)(u! :he #(+ % 9))))\b(if(>(g :mo))(do(u! :mo #(- % 9))(u! :po inc)))\t(if(>(g :mo)8)(do(u! :mo #(- % 9))(u! :fo inc)))nil@s')))(defn start-listener[](.start(Thread.^Runnable(fn[](while true(let[k(get-input)](swap! state #(handle-keypress % k))))))))(defn -main[](start-listener)(let[g #(get @%1 %2)](while true(Thread/sleep 500)(swap! state #(apply-rules %))(println(str"Health: "(g state :he)"\nHunger: "(g state :hu)"\n""Sleep: " (g state :sl)"\nFood: "(g state :fo)"\nPotions: "(g state :po)"\n""Money:"(g state :mo)"\n"))(if(<=(g state :he)0)(do(println"You died!\n")(reset! state new-state))))))

非ゴルフ:

(ns bits.golf.pet)

(defrecord State [he hu sl fo po mo])

(def new-state (->State 100 0 0 10 0 100))

(def state (atom new-state))

(defn update! [sa k f]
  (swap! sa #(update % k f)))

(defn apply-rules [s]
  (let [s' (atom s)
        u! #(update! s' %1 %2)
        g #(get @s' %)]
    (u! :hu inc)
    (u! :sl inc)
    (if (>= (g :hu) 80)
      (u! :he dec))
    (if (>= (g :sl) 80)
      (do
        (u! :sl (fn [_] 0))
        (u! :hu #(+ % 9))))
    (if (>= (g :he) 80)
      (u! :mo inc))
    @s'))

(defn get-input []
  (let [raw (read-line)]
    (first raw)))

(defn handle-keypress [s k]
  (let [s' (atom s)
        u! #(update! s' %1 %2)
        g #(get @s' %)]
    (case k
      \f (if (> (g :hu) 8)
           (do
             (u! :fo dec)
             (u! :hu #(- % 9))))
      \s (u! :sl (fn [_] 0))
      \p (if (> (g :po) 0)
           (do
             (u! :po dec)
             (u! :he #(+ % 9))))
      \b (if (> (g :mo))
           (do
             (u! :mo #(- % 9))
             (u! :po inc)))
      \t (if (> (g :mo) 8)
           (do
             (u! :mo #(- % 9))
             (u! :fo inc)))
      nil
      @s')))

(defn start-listener []
  (.start
    (Thread. ^Runnable
      (fn []
        (while true
          (let [k (get-input)]
            (swap! state #(handle-keypress % k))))))))

(defn -main []
  (start-listener)
  (let [g #(get @%1 %2)]
    (while true
      (Thread/sleep 500)

      (swap! state #(apply-rules %))

      (println (str
                 "Health: " (g state :he) "\n"
                 "Hunger: " (g state :hu) "\n"
                 "Sleep: " (g state :sl) "\n"
                 "Food: " (g state :fo) "\n"
                 "Potions: " (g state :po) "\n"
                 "Money:" (g state :mo) "\n"))

      (if (<= (g state :he) 0)
        (do
          (println "You died!\n\n\n\n\n")
          (reset! state new-state))))))

それはそこにかなりの量のコードです。
— ender_scythe

@ender_scythe Ya。私が作るような、いくつかの場所で半まともなコーディング慣行を遵守しようとしていたapplying-rulesとhandle-keypress純粋。私は今「ねじ込み」バージョンを書いています。
— カルシジェネート
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.