Tạo một Tamagotchi / Giga Pet đơn giản hóa!


9

Tamagotchi và Giga Thú cưng là những thiết bị điện tử nhỏ mô phỏng một thú cưng ảo nhỏ. Thú cưng này có một số chỉ số, như sức khỏe, đói, v.v.
Gần đây tôi đã viết ví dụ này:

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

Đây là một thú cưng ảo xương trần trong 467 byte! Sau đó tôi tự hỏi làm thế nào các chuyên gia golf mã có thể làm tốt, vì vậy bây giờ, thách thức.

Các thách thức

Tạo một chương trình theo dõi 6 số liệu thống kê của thú cưng ảo và cập nhật chúng theo thời gian và đáp ứng với đầu vào của người dùng. Các số liệu thống kê là: sức khỏe và tiền bạc (bắt đầu từ 100), thực phẩm (bắt đầu từ 10), và đói, ngủ và thuốc (bắt đầu từ 0).

Chương trình sẽ cập nhật các giá trị để đáp ứng với các sự kiện sau:

  • Mặc dù chương trình không nhận được đầu vào, nhưng nó sẽ thực hiện cập nhật theo các khoảng thời gian đều đặn (khoảng thời gian giữa các lần cập nhật không được ngắn hơn nửa giây cũng không dài hơn một giây). Mỗi bản cập nhật thực hiện như sau:

    • Đói và ngủ mỗi lần tăng thêm 1.
    • Nếu Hunger từ 80 trở lên, Sức khỏe giảm 1.
    • Nếu Ngủ từ 80 trở lên, nó được đặt lại về 0 và Hunger tăng thêm 9.
    • Nếu Sức khỏe từ 80 trở lên, Tiền tăng 1.
    • Nếu Sức khỏe là 0, chương trình sẽ thoát.
  • Chương trình cũng phải phản hồi ngay lập tức khi người dùng nhấn phím sau (điều này có nghĩa là bạn sẽ cần sử dụng một tính năng ngôn ngữ hoặc thư viện có thể phát hiện một phím được nhấn và trả lời ngay lập tức, thay vì chỉ đọc từ đầu vào tiêu chuẩn), thực hiện các hành động sau:

    • f: Nếu Hunger lớn hơn 8 và Thực phẩm là khác không, thì Thực phẩm giảm 1 và Hunger giảm 9.
    • s: Ngủ được đặt lại về 0.
    • p: Nếu Độc dược lớn hơn 0, Độc dược giảm 1 và Sức khỏe tăng 9.
    • b: Nếu Tiền lớn hơn 8, thì Tiền giảm 9 và Độc dược tăng thêm 1.
    • t: Nếu Tiền lớn hơn 8, thì Tiền giảm 9 và Thực phẩm tăng thêm 1.

Bất cứ khi nào giá trị của các số liệu thống kê thay đổi, chúng phải được hiển thị trên màn hình trong biểu mẫu . Tất cả sáu số liệu thống kê phải được hiển thị bất cứ khi nào chúng thay đổi; và các số liệu thống kê trong màn hình phải được phân tách bằng dấu phẩy hoặc dòng mới.Stat: value

Thử thách này tuân theo các quy tắc thông thường : chương trình ngắn nhất tuân thủ các đặc điểm kỹ thuật ở trên sẽ thắng. (Lưu ý rằng như thường lệ, nếu ngôn ngữ mới hơn so với đối thủ, bài nộp phải được đánh dấu là không cạnh tranh.)


Bạn không nói số liệu thống kê bắt đầu là gì
Blue

1
Các đầu ra phải theo "cách dễ đọc" là mơ hồ, và do đó, "một lần mỗi giây là". Bạn nên gửi thử thách đến hộp cát để nhận phản hồi và cải thiện chúng trước khi đăng lên chính ...
FlipTack

1
Làm thế nào là không rõ ràng này? Tôi muốn không rõ ràng có nhiều chi tiết hơn, bởi vì bản thân nó không rõ ràng.
ender_scythe

2
Sandbox không giúp đỡ nữa, vì đã có câu trả lời. Những người đã đánh dấu điều này là không rõ ràng nên nói lý do tại sao nó không rõ ràng, thay vì không rõ ràng.
ender_scythe

1
@BlueEyedBeast (và những cử tri thân thiết khác) Tôi cũng tò mò về những gì không rõ ràng. Phiên bản gốc có một số vấn đề quan trọng, nhưng có vẻ như các chỉnh sửa đã khắc phục điều đó. Ít nhất, nó đã đủ rõ ràng để Carcigenicate và tôi cung cấp bài nộp. Chia sẻ một số chi tiết về những gì bạn thấy không rõ ràng để ender_scythe có thể cải thiện nó.
Ray

Câu trả lời:


6

C, 424 406 386 357 byte

#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)}}

Tôi đánh giá cao sự cần thiết của đầu vào thô và cập nhật không đồng bộ trong thông số kỹ thuật. Mặc dù điều đó đòi hỏi một số chi phí từ thiết lập bộ xử lý tín hiệu và bộ xử lý tín hiệu, nhưng thật tuyệt khi có một thách thức không thường xuyên là (hy vọng) sẽ không tự động chiến thắng bởi một trong những ngôn ngữ chơi gôn chuyên dụng.

Bạn đã không xác định chính xác cách trò chơi kết thúc được chỉ định, do đó, trò chơi này sẽ chết với tiếng kêu chết chóc truyền thống của Tamagotchi về "Ngoại lệ điểm nổi (lõi bị đổ)".

Ung dung

/* 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 byte

(Dang, mục nhập mã golf đầu tiên của tôi mà tôi phải chỉnh sửa theo số byte. Đã chỉnh sửa để xóa cuộc gọi ngủ (), vì nó không thực sự tuân thủ các quy tắc như dự định.)

Yêu cầu HĐH unix-ish cho STDIN không chặn. Điều kỳ lạ là, sử dụng chuyển đổi / trường hợp so với xếp tầng nếu / khác tạo ra mã nguồn ngắn hơn, nhưng phiên bản nén tiếp theo dài hơn.

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

Ung dung:

<?
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";
}

Điều này không "phản hồi ngay lập tức khi nhấn phím sau bởi người dùng". Nó đợi cho đến khi cuộc gọi sleep(1)trở lại trước khi xử lý đầu vào. Mặc dù nó xử lý bất kỳ lệnh xếp hàng nào trước khi thực hiện cập nhật tiếp theo, vì vậy nó có thể ổn.
Ray

Vâng, lưu ý. Các từ ngữ có một sự mơ hồ lớn vì vậy tôi đã có một số tự do về việc giải thích bởi vì cách này ngắn hơn. :) Nếu tôi có thời gian hôm nay, tôi sẽ mã hóa giải pháp thay thế bằng một vòng lặp được định thời gian và trình bày cả hai để xem xét.
Alex Howansky

2

Toán học, 374 byte

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}]

Việc ngắt dòng rất quan trọng vì chúng là các ký tự dòng mới trong chuỗi để tôi có thể sử dụng Rowthay vì Column. Nếu bạn đánh giá điều này trong một cuốn sổ tay Mathicala, bạn sẽ thấy một cái gì đó như thế này:

Mô phỏng Tamagotchi

Bạn phải bấm vào trường đầu vào và nhanh chóng (chưa đến một giây) nhập ký tự của bạn trước khi Dynamickhiến trường đầu vào cập nhật. Cơn đau đầu này có thể tránh được hoàn toàn nếu EventHandlertrong ô của chính nó chứ không phải là một phần tử của Row, nhưng điều đó sẽ yêu cầu lưu chương trình dưới dạng tệp .nb, điều này sẽ làm tăng đáng kể số lượng byte.


Công việc tốt đẹp! Tôi sẽ sử dụng một cấu trúc như 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++]]};... điều này sẽ cho phép bạn tránh sự cần thiết phải nhấp vào trường nhập. Thêm tùy chọn , PassEventsDown -> Truevào cuối mã đó sẽ cho phép bạn tiếp tục chỉnh sửa sổ ghi chép, nhưng có thể được gỡ bỏ ở cuối để tiết kiệm byte :)
Greg Martin

Cảm ơn, đó chính xác là chức năng mà tôi đang tìm kiếm ban đầu! Thật không may, nó dường như dài hơn những gì tôi hiện có.
ngenisis

2

C # 6, 567 563 byte

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");}}

Ung dung:

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 byte

V2

Làm cho tất cả các nguyên tử biến lỏng thay vì ở trong một đối tượng trạng thái. Điều đó một mình đã thoát khỏi rất nhiều mã. Tôi cũng đã tạo các hàm phím tắt a!s!để cộng và trừ từ atomsdễ dàng hơn (về cơ bản hoạt động như +=-=, vì Clojure không có các toán tử đó).

Tôi nhận ra rằng tôi có thể loại bỏ atoms nếu tôi quản lý để tích hợp khóa đầu vào vào loop. Tôi sẽ phải xem.

(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"))

Ung dung:

(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. Chắc chắn phòng để cải thiện ở đây. Loại vấn đề này dễ thực hiện nhất với các tác dụng phụ và Clojure có chức năng, vì vậy tôi đang cố gắng lạm dụng atomđể giảm bớt số lượng mã cần thiết. Thật không may, tôi đã không tham gia vào một kế hoạch, vì vậy đó là loại ngớ ngẩn ngay bây giờ. Tôi đã có một vài ý tưởng để thu nhỏ tôi mặc dù.

Đây là một chương trình đầy đủ. Nó có thể được chạy bằng cách chạy -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))))))

Ung dung:

(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))))))

Đó là một số lượng lớn mã ở đó.
ender_scythe

@ender_scythe Ya. Tôi đã cố gắng tuân thủ các thực hành mã hóa nửa vời ở một số nơi, như làm applying-ruleshandle-keypressthuần túy. Tôi đang viết một phiên bản "vít-it" ngay bây giờ.
Carcigenicate
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.