간단한 다마고치 / 기가 애완 동물 만들기!


9

Tamagotchi와 Giga Pets는 작은 가상 애완 동물을 시뮬레이션 한 소형 전자 장치였습니다. 이 애완 동물에는 건강, 굶주림 등과 같은 몇 가지 통계가있었습니다.
최근에이 예제를 썼습니다.

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보다 크고 Food가 0이 아닌 경우 Food는 1 씩 감소하고 Hunger는 9만큼 감소합니다.
    • s: 슬립이 0으로 재설정됩니다.
    • p: 물약이 0보다 크면 물약이 1만큼 감소하고 체력이 9만큼 증가합니다.
    • b돈이 8보다 크면 돈이 9만큼 감소하고 물약이 1 씩 증가합니다.
    • t: 돈이 8보다 크면 돈은 9만큼 감소하고 음식은 1 씩 증가합니다.

통계 값이 변경 될 때마다 통계 형식으로 화면에 표시되어야합니다 . 6 개의 통계는 모두 변경 될 때마다 표시되어야합니다. 디스플레이 내 통계는 쉼표 또는 줄 바꿈으로 구분해야합니다.Stat: value

이 도전은 정상을 따릅니다 규칙 : 위의 사양을 준수하는 가장 짧은 프로그램이 우선합니다. (언제와 같이 언어가 경쟁 언어보다 최신 인 경우 제출물을 경쟁이 아닌 것으로 표시해야합니다.)


시작 통계가 무엇인지 말하지 마십시오
Blue

1
출력은 "읽기 쉬운 방식"이어야하고 모호하므로 "초당 한 번 ish"입니다. 메인에 게시하기 전에 피드백을 받고 개선하기 위해 샌드 박스에 챌린지를 제출해야합니다.
FlipTack

1
이것이 어떻게 불분명합니까? 명확하지 않기 때문에 불분명 한 자세한 내용을 원합니다.
ender_scythe

2
샌드 박스는 이미 답변이 있으므로 더 이상 도움이되지 않습니다. 이것을 불분명 한 것으로 표시 한 사람들은 자신이 불분명하지 않고 왜 불분명한지 말해야합니다.
ender_scythe

1
@BlueEyedBeast (및 다른 가까운 유권자) 나는 또한 무엇이 불분명한지 궁금합니다. 원래 버전에는 몇 가지 중요한 문제가 있었지만 수정 사항이 수정 된 것처럼 보입니다. 적어도 Carcigenicate와 나는 제출물을 제공 할 수있을 정도로 분명했다. ender_scythe가 개선 할 수 있도록 명확하지 않은 부분에 대한 세부 정보를 공유하십시오.
Ray

답변:


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, 396 413 바이트

(Dang, 바이트 수로 편집 해야하는 첫 번째 코드 골프 항목입니다. 의도 된 규칙을 실제로 준수하지 않았기 때문에 sleep () 호출을 제거하도록 편집되었습니다.)

비 차단 STDIN에는 유닉스 OS가 필요합니다. 이상하게도 스위치 / 케이스와 캐스케이드를 사용하면 소스 코드가 더 짧아 지지만 후속 압축 버전은 더 길어집니다.

<?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

수학, 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 노트북에서 이것을 평가하면 다음과 같이 보일 것입니다 :

다마고치 시뮬레이션

입력 필드를 클릭 Dynamic하고 입력 필드가 업데이트 되기 전에 문자를 빠르게 (1 초 미만) 입력해야합니다 . 이 두통은 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

클로저, 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-ruleshandle-keypress순수 와 같은 일부 장소에서 반 정도의 코딩 관행을 고수하려고했습니다 . 지금 "screw-it"버전을 작성하고 있습니다.
Carcigenicate
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.