做一个简化的他妈哥池/吉加宠物!


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开始)。

程序应响应以下事件来更新值:

  • 当程序不接收任何输入时,它应以固定的间隔执行更新(两次更新之间的间隔不应短于半秒,也不应长于一秒)。每个更新执行以下操作:

    • 饥饿和睡眠分别增加1。
    • 如果饥饿大于或等于80,则生命值降低1。
    • 如果“睡眠”为80或更高,它将重置为0,并且饥饿感会额外增加9。
    • 如果健康值为80或更高,则金钱增加1。
    • 如果“健康”为0,则程序退出。
  • 该程序还必须在用户按下以下键时立即做出响应(这意味着您将需要使用一种语言功能或库,该功能或库可以检测到被按下的键并立即做出响应,而不仅仅是从标准输入中读取内容),以下动作:

    • f:如果饥饿大于8并且食物不为零,则食物减少1,饥饿减少9。
    • s:睡眠重设为0。
    • p:如果药水大于零,则药水减少1,生命值提高9。
    • b:如果金钱大于8,则金钱减少9,魔药增加1。
    • t:如果金钱大于8,则金钱减少9,食物增加1。

每当统计值改变时,它们都必须以表格形式显示在屏幕上。无论何时更改,必须显示所有六个统计信息。并且显示器中的统计信息必须用逗号或换行符分隔。Stat: value

这个挑战遵循正常 规则:符合上述规格的最短程序将获胜。(请注意,与往常一样,如果语言比竞赛语言新,则提交的内容必须标记为非竞争内容。)


您无需说说开始的数据是多少
蓝色

1
输出必须以“易于阅读的方式”模棱两可,因此“每秒一次”。您应该向沙盒提交挑战,以获取反馈并加以改进,然后再发布到主要...
FlipTack

1
这怎么不清楚?我希望不清楚有更多细节,因为本身不清楚。
ender_scythe

2
沙盒已无济于事,因为已经有答案了。将此标记为不清楚的人应该说为什么不清楚,而不是自己不清楚。
ender_scythe

1
@BlueEyedBeast(和其他亲密的选民)我也很奇怪什么还不清楚。原始版本存在一些重大问题,但似乎修复了该问题。至少,很明显,我和致癌原提交了意见书。分享一些您不清楚的细节,以便ender_scythe可以改善它。

Answers:


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设置和信号处理程序的一些开销,但偶尔遇到挑战(希望)不会被一种专用的高尔夫语言自动赢得是很好的。

您没有指定确切的游戏结束指示方式,因此这一行为会因传统的Tamagotchi死亡叫喊而消失,即“浮点异常(抛弃内核)”。

不打高尔夫球

/* 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-ish操作系统。奇怪的是,使用switch / case而不是cascade级联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)返回,然后再处理输入。尽管它会在执行下一个更新之前处理所有排队的命令,所以可能还不错。

是的,请注意。那里的措词含糊不清,所以我对解释有所保留,因为这种方式更短。:)如果我今天有时间,我将使用定时循环编写替代解决方案的代码,并同时提出以供考虑。
Alex Howansky '16

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笔记本中对此进行评估,您应该会看到以下内容:

他妈哥池模拟

您必须单击输入字段,然后在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

Ohdeargod。这里绝对有改进的空间。这种问题最容易与副作用有关,而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雅。我试图在某些地方坚持半体面的编码实践,例如制作applying-ruleshandle-keypress纯粹。我正在写一个“螺丝”版本。
Carcigenicate's
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.