Bóng nảy 8 bit xung quanh một khung vẽ


20

Lấy cảm hứng từ danh sách này từ Hướng dẫn sử dụng hàng hóa 64:

10 PRINT "{CLR/HOME}"
20 POKE 53280,7 : POKE 53281,13
30 X = 1 : Y = 1
40 DX = 1 : DY = 1
50 POKE 1024 + X + 40 * Y, 81
60 FOR T = 1 TO 10 : NEXT
70 POKE 1024 + X + 40 * Y, 32
80 X = X + DX
90 IF X <= 0 OR X >= 39 THEN DX = -DX
100 Y = Y + DY
110 IF Y <= 0 OR Y >= 24 THEN DY = -DY
120 GOTO 50

Tạo một chương trình tương tự trong ngôn ngữ / nền tảng đã chọn của bạn để trả lại một vật thể giống như quả bóng xung quanh thiết bị đầu cuối, màn hình, khung vẽ hoặc khu vực hiển thị hình ảnh khác của bạn.

Bạn không cần phải bắt chước chính xác đồ họa PETSCII của C64, đơn giản Ohoặc osẽ làm, bạn cũng không phải sử dụng GOTOlệnh nếu nó vẫn tồn tại trong ngôn ngữ của bạn. Miễn là quả bóng của bạn bắt đầu ở trên cùng của khung vẽ của bạn và di chuyển theo đường chéo cho đến khi nó chạm đến giới hạn của khung vẽ, và sau đó nảy lên tương ứng, như sau:

  • Đi xuống dưới và phải và chạm vào đáy của khu vực màn hình, bật lên và tiếp tục sang phải;
  • Đi lên và sang phải và chạm vào ranh giới ngoài cùng bên phải, và nảy sang trái và lên;
  • Đi sang trái và lên và chạm đỉnh, nảy trái và xuống;
  • Đi sang trái và xuống và đến ranh giới ngoài cùng bên trái, nảy sang phải và xuống;
  • Lượt bất kỳ góc và đảo ngược hướng;

Vậy thì tất cả chúng ta đều tốt.

Bạn cũng không phải di chuyển quả bóng 8 pixel một lần, giống như đang xảy ra trong danh sách BASIC trên C64; bạn có thể di chuyển một khối ký tự hoặc một pixel mỗi lần, tùy theo bạn nghĩ là phù hợp nhất.

Để xem danh sách BASIC này hoạt động, bạn có thể nhập nó bằng trình giả lập Commodore 64 trực tuyến này cung cấp trình duyệt của bạn hỗ trợ Flash.


2
Canvas canvas. Cô ạ.
Matthew Roh

Tôi không chắc chắn những gì bạn gọi là một màn hình ngày nay. Bạn đã từng chỉ có màn hình và khu vực viền được xem qua TV hoặc VDU ... và bây giờ bạn đã có thiết bị đầu cuối, cửa sổ, khung vẽ, thiết bị xuất chuẩn, v.v ... tất cả đều rất khó hiểu với tôi.
Shaun Bebbers 17/2/2017

Sẽ tốt hơn nếu chúng ta có giá trị kích thước pixel không đổi.
Matthew Roh

4
Chúng ta có thể giả sử kích thước màn hình của 1x1 và in o mãi mãi không?
Matthew Roh

1
bản sao có thể có của ASCII Ball in Box Animation
Titus

Câu trả lời:


3

Mã máy 6502 (C64), 90 89 91 byte

+2 byte vì nó cần một địa chỉ tải (không phải PIC vì tự sửa đổi)

00 C0 20 44 E5 CA D0 FD C6 FC D0 F9 A2 20 86 FC A9 D8 85 9E A9 03 85 9F A4 CA
18 A5 9E 69 28 85 9E 90 02 E6 9F 88 10 F2 A4 C9 8A 91 9E C9 20 D0 08 E6 C9 E6
CA A2 51 10 D7 A5 C9 F0 04 C9 27 D0 08 AD 2F C0 49 20 8D 2F C0 A5 CA F0 04 C9
18 D0 B4 AD 31 C0 49 20 8D 31 C0 D0 AA

Bản demo trực tuyến

Sử dụng: sys49152

Tôi đã cố gắng hết sức để giảm kích thước (ví dụ KHÔNG sử dụng IRQ cho thời gian nhưng thay vào đó là các vòng trống ngu ngốc), vẫn không thể đạt đến cấp độ C64 BASIC của Titus : o oh, tốt. Nhưng nó có vẻ ít nhấp nháy hơn;)

Giải thích: (phó tháo gỡ)

00 C0       .WORD $C000         ; load address
20 44 E5    JSR $E544           ; clear screen
CA          DEX
D0 FD       BNE $C003           ; inner wait (256 decrements)
C6 FC       DEC $FC
D0 F9       BNE $C003           ; outer wait (32 decrements in zeropage)
A2 20       LDX #$20            ; wait counter and screen code for "space"
86 FC       STX $FC             ; store wait counter
A9 D8       LDA #$D8            ; load screen base address ...
85 9E       STA $9E             ; ... -40 (quasi row "-1") ...
A9 03       LDA #$03            ; ... into vector at $9e/$9f
85 9F       STA $9F
A4 CA       LDY $CA             ; load current row in Y
18          CLC                 ; clear carry flag
A5 9E       LDA $9E             ; add ...
69 28       ADC #$28            ; ... $28 (40 cols) to ...
85 9E       STA $9E             ; ... vector
90 02       BCC $C023
E6 9F       INC $9F             ; handle carry
88          DEY                 ; count rows down
10 F2       BPL $C018
A4 C9       LDY $C9             ; load current col in Y
8A          TXA                 ; copy screen code from X to A
91 9E       STA ($9E),Y         ; store at position of screen
C9 20       CMP #$20            ; screen code was "space"
D0 08       BNE $C037           ; if not, ball was drawn
E6 C9       INC $C9             ; next column   | opcodes are modified
E6 CA       INC $CA             ; next row      | here for directions
A2 51       LDX #$51            ; screen code for "ball"
10 D7       BPL $C00E           ; and back to drawing code
A5 C9       LDA $C9             ; load current column
F0 04       BEQ $C03F           ; if zero, change X direction
C9 27       CMP #$27            ; compare with last column (39)
D0 08       BNE $C047           ; if not equal, don't change X direction
AD 2F C0    LDA $C02F           ; load opcode for X direction
49 20       EOR #$20            ; toggle between ZP INC and DEC
8D 2F C0    STA $C02F           ; store back
A5 CA       LDA $CA             ; load current row
F0 04       BEQ $C04F           ; if zero, change Y direction
C9 18       CMP #$18            ; compare with last row (24)
D0 B4       BNE $C003           ; if not equal, don't change Y direction
AD 31 C0    LDA $C031           ; load opcode for Y direction
49 20       EOR #$20            ; toggle between ZP INC and DEC
8D 31 C0    STA $C031           ; store back
D0 AA       BNE $C003           ; -> main loop

Để giải trí, đây là một biến thể chuyên nghiệp hơn bằng cách sử dụng sprite cho bóng và nhấp nháy đường viền khi đánh vào 385 byte (chứa dữ liệu sprite được sử dụng tại chỗ ):

00 C0 AD 15 D0 F0 30 A9 CC 85 FC A9 04 20 A2 C0 A9 97 8D 00 DD A9 15 8D 18 D0 
A9 00 8D 15 D0 8D 1A D0 A2 81 8E 0D DC A2 31 8E 14 03 A2 EA 8E 15 03 58 A6 D6 
4C F0 E9 A9 04 85 FC A9 CC 20 A2 C0 A2 31 86 01 A2 10 A9 D0 85 FC B1 FB C6 01 
91 FB E6 01 C8 D0 F5 E6 FC CA D0 F0 A9 37 85 01 A9 94 8D 00 DD A9 35 8D 18 D0 
8D 27 D0 A2 05 8E F8 CF A2 01 8E 15 D0 8E 1A D0 8E 12 D0 86 FD 86 FE A2 18 8E 
00 D0 A2 1B 8E 11 D0 A2 32 8E 01 D0 A2 7F 8E 0D DC AE 0D DC AE 20 D0 86 FB A2 
C1 8E 14 03 A2 C0 D0 8A 85 FE 8D 88 02 A9 00 85 FB 85 FD A2 04 A0 00 78 B1 FB 
91 FD C8 D0 F9 E6 FC E6 FE CA D0 F2 60 A6 FB 8E 20 D0 CE 19 D0 A5 FD F0 20 AD 
00 D0 18 69 04 8D 00 D0 90 03 EE 10 D0 C9 40 D0 2C AD 10 D0 29 01 F0 25 20 38 
C1 C6 FD F0 1E AD 00 D0 38 E9 04 8D 00 D0 B0 03 CE 10 D0 C9 18 D0 0C AD 10 D0 
29 01 D0 05 20 38 C1 E6 FD A5 FE F0 14 AD 01 D0 18 69 04 8D 01 D0 C9 E6 D0 19 
20 38 C1 C6 FE F0 12 AD 01 D0 38 E9 04 8D 01 D0 C9 32 D0 05 20 38 C1 E6 FE 4C 
31 EA A9 01 8D 20 D0 60 00 00 00 7E 00 03 FF C0 07 FF E0 1F FF F8 1F FF F8 3F 
FF FC 7F FF FE 7F FF FE FF FF FF FF FF FF FF FF FF FF FF FF 7F FF FE 7F FF FE 
3F FF FC 1F FF F8 1F FF F8 07 FF E0 03 FF C0 00 7E 00 00 00 00 

Bản demo trực tuyến - | - duyệt nguồn trình biên dịch ca65

Bắt đầu và dừng bóng nảy với sys49152.

  • Điều này khiến C64 BASIC chạy, điều đó được thực hiện bằng cách di chuyển không gian địa chỉ VIC-II lên $C000, yêu cầu sao chép nội dung màn hình và bộ ký tự (phông chữ).
  • Nó móc vào IRQ hệ thống và để tránh nhấp nháy, thay đổi nguồn IRQ này sang chip đồ họa VIC-II, vì vậy các cập nhật luôn được thực hiện giữa các khung.
  • Trục trặc:
    1. RUN/STOP + RESTORE bị hỏng, đừng thử.
    2. Với nguồn VIC-II là nguồn IRQ, con trỏ nhấp nháy chậm hơn một chút và TI$cũng sẽ bị tụt lại phía sau.
    3. khi dừng trong khi đường viền được nhấp nháy (rất khó xảy ra nhưng có thể), nó vẫn giữ màu trắng - bạn phải khôi phục lại bằng tay.

1
Nó không hoàn toàn độc lập, phải không? Tôi thấy hai LDA tuyệt đối và hai STA. Công việc tuyệt vời dù sao!
Tít

Chết tiệt, bạn đã đúng: o Tôi quên việc tự sửa đổi! Tôi sẽ cập nhật ngay khi tôi ở trên PC.
Felix Palmen

1
@Titus đã sửa ... và chỉ để giải trí, đã thêm một biến thể "tốt hơn" :)
Felix Palmen

Bạn đã xem xét việc đóng gói sprite? (Hmm ... sử dụng ROM bộ ký tự?) Và tôi thích inc $d020hơn jsr flash;) hithimelfwithalargetrout Nó thật tuyệt vời!
Tít

1
@Titus sẽ tiết kiệm 2 byte, vâng. Đối với địa chỉ tải, nó là một phần của .prgtệp hợp lệ và từ câu hỏi meta của tôi ở đây tôi phải đưa nó vào ... có lẽ có thể loại bỏ nó nếu mã độc lập với vị trí.
Felix Palmen

14

Tiện ích Bash + Unix, 125 117 byte

for((x=y=u=v=1;;x+=u,y+=v,u=(x<1||x>=`tput cols`-1)?-u:u,v=(y<1||y>=`tput lines`-1)?-v:v)){
tput cup $y $x
sleep .1
}

Hoạt hình chạy mẫu:

Hoạt hình chạy mẫu


6
Nó đánh vào góc chính xác! : O
mbomb007

11

CP-1610 lắp ráp, 67 ... 64 62 DECLEs = 78 byte

Mã này được dự định để chạy trên Intellivision . Nó đang sử dụng một trong những họa tiết phần cứng của nó, được gọi là MOB (cho Mobile Object).

Mã op CP-1610 được mã hóa với giá trị 10 bit, được gọi là 'DECLE'. Chương trình này dài 62 DECLE, bắt đầu từ $ 4800 và kết thúc ở mức $ 483D.

Kết xuất thập lục phân + nguồn

                            ROMW  10            ; use 10-bit ROM
                            ORG   $4800         ; start program at address $4800

                    FRAME   EQU   $17E          ; frame #

                            ;; ------------------------------------------------ ;;
                            ;;  main entry point                                ;;
                            ;; ------------------------------------------------ ;;
                    main    PROC

4800 0001                   SDBD                ; load Interrupt Service Routine
4801 02B8 002B 0048         MVII  #isr,   R0    ; into R0

4804 0240 0100              MVO   R0,     $100  ; update ISR
4806 0040                   SWAP  R0
4807 0240 0101              MVO   R0,     $101

4809 02B9 0208              MVII  #$0208, R1    ; initialize R1 = X
480B 02BA 0108              MVII  #$0108, R2    ; initialize R2 = Y
480D 02BB 0001              MVII  #1,     R3    ; initialize R3 = DX
480F 009C                   MOVR  R3,     R4    ; initialize R4 = DY

4810 0002                   EIS                 ; enable interrupts

                            ;; ------------------------------------------------ ;;
                            ;;  main loop                                       ;;
                            ;; ------------------------------------------------ ;;
4811 0280 017E      @@loop  MVI   FRAME,  R0    ; R0 = current frame #

4813 0340 017E      @@spin  CMP   FRAME,  R0    ; wait for next frame
4815 0224 0003              BEQ   @@spin

4817 00D9                   ADDR  R3,     R1    ; X += DX

4818 0379 02A0              CMPI  #$2A0,  R1    ; reached right border?
481A 0204 0003              BEQ   @@updDx

481C 0379 0208              CMPI  #$208,  R1    ; reached left border?
481E 002F                   ADCR  PC

481F 0023           @@updDx NEGR  R3            ; DX = -DX

4820 00E2                   ADDR  R4,     R2    ; Y += DY

4821 037A 0160              CMPI  #$160,  R2    ; reached bottom border?
4823 0204 0003              BEQ   @@updDy

4825 037A 0108              CMPI  #$108,  R2    ; reached top border?
4827 002F                   ADCR  PC

4828 0024           @@updDy NEGR  R4            ; DY = -DY

4829 0220 0019              B     @@loop        ; loop forever

                            ENDP

                            ;; ------------------------------------------------ ;;
                            ;;  ISR                                             ;;
                            ;; ------------------------------------------------ ;;
                    isr     PROC

482B 01DB                   CLRR  R3            ; clear a bunch of STIC registers
482C 02BC 0020              MVII  #$20,   R4

482E 0263           @@clear MVO@  R3,     R4    ; (including background color,
482F 037C 0032              CMPI  #$32,   R4    ; border color, etc.)
4831 0226 0004              BLE   @@clear

4833 0259                   MVO@  R1,     R3    ; update X register of MOB #0
4834 0242 0008              MVO   R2,     $8    ; update Y register of MOB #0
4836 02BB 017E              MVII  #$017E, R3    ; update A register of MOB #0
4838 0243 0010              MVO   R3,     $10   ; (using a yellow "O")

483A 0298                   MVI@  R3,     R0    ; increment frame #
483B 0008                   INCR  R0
483C 0258                   MVO@  R0,     R3

483D 00AF                   JR    R5            ; return from ISR

                            ENDP

Đầu ra

đầu ra


10

HTML (Microsoft Edge / Internet Explorer), 81 byte

Giả sử năm 1998 với các <marquee>thẻ lồng nhau này :

<marquee behavior=alternate direction=down><marquee behavior=alternate width=99>O

Đã thử nghiệm trong Microsoft Edge, mặc dù từ những gì tôi đã đọc IE cũng vẫn nên hỗ trợ marquees. Quyết định không hoạt động trong Chrome.

Cài đặt direction=upsẽ tiết kiệm 2 byte, nhưng phá vỡ quy tắc rằng bóng phải bắt đầu ở trên cùng của khung vẽ.


Thật không may, đây là một câu trả lời không hợp lệ vì quả bóng không đi theo đường chéo, theo yêu cầu của thử thách.
El'endia Starman

Bạn đã thử nó trong Microsoft Edge chưa? Chrome dường như không hỗ trợ directionthuộc tính.
Jack Brounstein

Huh, lời xin lỗi của tôi - nó hoạt động trong Edge. Tôi có thể xác nhận rằng nó không hoạt động trong Chrome và tôi có thể chứng thực rằng nó không hoạt động trong Firefox và Internet Explorer. Ba phần tư không tệ (và bạn chỉ cần một câu để câu trả lời này có hiệu lực). +1
El'endia Starman

1
+1 cho marquee, đó là khá sáng tạo!
Metoniem

Làm việc trong Chrome cho tôi.
ckjbgames

8

TI-BASIC, 71 70

1->A
1->B
1->C
1->D
While 1
ClrHome
Output(B,A,0
A+C->A
B+D->B
If A<2 or A>15
~C->C
If B<2 or B>7
~D->D
End

Dịch nghĩa đen, tôi sẽ không ngạc nhiên nếu có những thủ thuật để làm cho nó nhỏ hơn.

Màn hình có kích thước 16x8 và 1 chỉ số nên các hằng số khác nhau.

~ là cách SourceCoder để viết ký hiệu phủ định.

gif nảy O

Nó trông mượt mà hơn trên phần cứng.


Bạn có chắc đây là 70 byte? Có vẻ như ít hơn thế.
12Me21

@ 12Me21 bạn đếm được bao nhiêu byte? Tôi nhận được 80 byte nếu tôi lưu cái này trên máy tính và 10 byte cho một chương trình trống đồng ý với số lượng của tôi.
harold

Ồ, tôi đoán tôi đã đếm sai rồi.
12Me21

7

Befunge, 209 byte

>10120130pppp>"l52?[J2["39*,,,,39*,,,,,,v
v+56/+55\%+55:+1g01*83-"6!"7\-"6!?"8-*86<
>00g1+:55+%\55+/"+!6"-48*,68>*#8+#6:#,_v$
v:+g03g01p02+-\g02*2!-*64\*2!:p00:+g02g<$
>10p:!2*\"O"-!2*30g\-+30p"2"::**>:#->#1_^

Điều này giả sử kích thước màn hình là 80x25, nhưng bạn có thể dễ dàng điều chỉnh phạm vi bằng cách thay thế "O"(79) trên dòng cuối cùng và *64(24) trên dòng cuối cùng thứ hai (lưu ý rằng dòng cuối cùng thứ hai được thực hiện từ phải sang trái). Tốc độ cũng có thể được điều chỉnh bằng cách thay thế "2"(50) trên dòng cuối cùng.


7

Java, 184 176 byte

class A{public static void main(String[]a)throws Exception{for(int X=1,Y=1,x=1,y=1;;System.out.print("\033["+X+";"+Y+"H"),Thread.sleep(50),X+=x=X%25<1?-x:x,Y+=y=Y%85<1?-y:y);}}

Điều này sử dụng Chuỗi thoát ANSI để định vị lại con trỏ, là đối tượng nảy xung quanh 85 x 25màn hình đầu cuối. Lưu trong một tập tin có tên A.java.

Ung dung

class Terminal_Bouncing_Ball {
    public static void main(String[] args) throws InterruptedException {
        int X = 0, Y = 0, dx = 1, dy = 1;
        while (true) {
            System.out.print(String.format("\033[%d;%dH",X,Y));
            Thread.sleep(50);
            dx = (X < 1) ? 1 : (X > 71) ? -1 : dx;
            dy = (Y < 1) ? 1 : (Y > 237) ? -1 : dy;
            X += dx;
            Y += dy;
        }
    }
}

Bản giới thiệu

Thí dụ


Đây là mã golf, vì vậy bạn sẽ muốn xóa Thread.sleep(50) . Và các chương trình đánh gôn và vô dụng của bạn không phù hợp.
Jakob

4

Clojure, 398 380 375 byte

(ns g(:require[quil.core :as q]))(def w 1e3)(def h 1e3)(def f 100)(def b(atom{:x f :y f :n 1 :m 1}))(q/defsketch . :size[w h]:setup #(do(q/text-font(q/create-font""f))(q/fill 255 255 255)):draw #(let[s 9{x :x y :y n :n m :m}@b c(+ x(* n s))u(+ y(* m s))](q/background 0 0 0)(reset! b{:x c :y u :n(if(< 0 c(- w f))n(* -1 n)):m(if(<(+ 0 f)u h)m(* -1 m))})(q/text"O"(:x @b)(:y @b))))

-18 byte bằng cách thay đổi tên phông chữ thành một chuỗi trống để mặc định nó, nội tuyến kiểm tra ranh giới và khắc phục vấn đề ranh giới dưới cùng (mà bạn có thể thấy trong GIF). Sửa lỗi mà thực sự lưu byte.

-5 byte bằng cách thay đổi thành cú pháp phá hủy cô đọng hơn và thu nhỏ bóng bằng pixel.

Sử dụng Quil .

Tôi đã cố gắng chuyển sang chế độ chức năng, nhưng nó đòi hỏi rất nhiều mã bổ sung và cuối cùng đắt hơn.

(ns bits.golf.ball-bounce
  (:require [quil.core :as q]))

(def width 1000)
(def height 1000)

(def font-size 100)

; Mutable state holding the properties of the ball. n and m are the directions on the x and y axis.
(def ball (atom {:x 300 :y 600 :n 1 :m 1}))

(q/defsketch b
  :size [width height] ; Window size

  :setup #(do
            (q/text-font (q/create-font "Arial" font-size)) ; Set the font
            (q/fill 255 255 255)) ; And the text color

  :draw
  #(let [speed 9
         ; Deconstruct the state
         {:keys [x y n m]} @ball
         next-x (+ x (* n speed))
         next-y (+ y (* m speed))

         ; I'm adding/subtracting the font-size so it stays in the window properly
         x-inbounds? (< 0 next-x (- width font-size))
         y-inbounds? (< (+ 0 font-size) next-y height)]

     ; Wipe the screen so the ball doesn't smear
     (q/background 0 0 0)

     ; Reset the state
     (reset! ball
             {:x next-x
              :y next-y
              :n (if x-inbounds? n (* -1 n))
              :m (if y-inbounds? m (* -1 m))})

     ; Draw the ball
     (q/text "O" (:x @ball) (:y @ball))))

Bóng nảy

(Lưu ý, phiên bản mới không bị nảy sớm dọc theo phía dưới màn hình giống như trong GIF.)


Tôi chỉ nhận ra mình có (+ 0 font-size)trong đó. Điều đó thật xấu hổ. Tôi sẽ sửa nó trong phiên bản tiếp theo. Nên tiết kiệm cho tôi như 5 byte.
Carcigenicate

4

Vợt 247 byte

(let*((w 500)(h(* w 0.6))(x 100)(y 0)(d 10)(e d)(G(λ(t)(set! x(+ x d))(when(or(> x w)(< x 0))
(set! d(* d -1)))(set! y(+ y e))(when(or(> y h)(< y 0))(set! e(* e -1)))
(underlay/xy(rectangle w h"solid""white")x y(circle 10"solid""black")))))(animate G))

Ung dung:

(require 2htdp/image
         2htdp/universe) 

(let* ((wd 500)            ; define variables and their initial values
       (ht 300)
       (x 100)
       (y 0)
       (dx 10)
       (dy 10)

       (imgfn              ; define function to draw one frame; called repeatedly by animate fn; 
        (λ (t)             ; t is number of ticks till now- sent by animate fn; ignored here;

                           ; update location (x and y values):
          (set! x (+ x dx))
          (when (or (> x wd) (< x 0))
            (set! dx (* dx -1)))             ; invert direction at edges
          (set! y (+ y dy))
          (when (or (> y ht) (< y 0))
            (set! dy (* dy -1)))             ; invert direction at edges

                           ; draw image: 
          (underlay/xy
           (rectangle wd ht "solid" "white") ; draw background
           x y                               ; go to location (x,y)
           (circle 10 "solid" "black")       ; draw ball
          ))))

  (animate imgfn))         ; animates the images created by imgfn (default rate 28 times/sec)

Đầu ra:

nhập mô tả hình ảnh ở đây


1
Chơi vợt với vợt!
ckjbgames

Nó là cái tốt!
rnso

"Vợt" có nguồn gốc từ ngôn ngữ lập trình "Lược đồ": sau Scheme (một kế hoạch lệch lạc) có Vợt (lừa đảo hoặc lừa đảo)!
rnso

@mso Thậm chí còn tốt hơn!
ckjbgames

3

Thạch, 37 byte

“ñc‘Ọ24ḶŒḄṖ⁸ị⁷x⁸µ80ḶŒḄṖ⁸ị⁶x⁸‘œS.1
Ç1¿

Với sự giúp đỡ của câu trả lời này để có được vòng lặp và thoát các ký tự đúng. Hiện tại nó bị trả lại trong một màn hình 80x24, nhưng điều đó có thể dễ dàng sửa đổi trong mã.

Các tọa độ trong mỗi hướng có thể được biểu diễn dưới dạng các phần tử của hai danh sách [0, 1,..., 24, 23,..., 1][0, 1,..., 80, 79,..., 1], hãy gọi chúng YX, được lặp lại vô hạn. Sự lặp lại vô hạn này có thể được mô phỏng bằng cách lập chỉ mục mô-đun - sử dụng trong Jelly. Ví dụ: trong ilần lặp thứ nhất, quả bóng ở vị trí (X[i%|X|], Y[i%|Y|]) = (iịY, iịX). Quả bóng di chuyển chỉ là con trỏ được đặt vào vị trí bằng cách phát ra iịYdòng mới và iịXdấu cách.

Bản giới thiệu

https://i.gyazo.com/b8eac64097cb6d3a18185877c2f4c945.gif

Giải trình

“ñc‘Ọ24ḶŒḄṖ⁸ị⁷x⁸µ80ḶŒḄṖ⁸ị⁶x⁸‘œS.1        Monadic helper link - argument i.
                                         Resets the terminal, prints Y[i] newlines,
                                         X[i] spaces and returns i + 1.
“ñc‘                                     Set the output to [27, 99]
    Ọ                                    Convert to characters and print (\x1bc)
                                          -> Cursor is at position (0,0)
     24Ḷ                                 Lowered range of 24. Yields [0,...,23].
        ŒḄ                               Bounce. Yields [0,...,23,22,...,0].
          Ṗ                              Pop. Yields [0,...,23,22,...,1] = Y.
           ⁸ị                            Modular index i (⁸) into Y. The current
                                         value is the Y coordinate, y.
              x                          Repeat y times
             ⁷                           the newline character ('\n').
               ⁸                         Output that (y times '\n') and continue
                                         with value i.
                                          -> Cursor is at position (0, y)
                µ                        Monadic chain separation.
                 80ḶŒḄṖ                  Same as above, but this time yielding X.
                       ⁸ị                Modular index i into X, yielding the
                                         value for x.
                          x              Repeat x times
                         ⁶               the whitespace character.
                           ⁸             Output that (x times ' ') and continue
                                         with value i.
                                         -> Cursor is at position (x, y), the
                                            final position.
                             œS.1        Wait 0.1 seconds.
                            ‘            Return i + 1.

Ç1¿                                      Main (niladic) link.
 1¿                                      While true.
Ç                                        Call the helper link. The first time
                                         there is no argument and i will be [],
                                         which is cast to 0 when used as integer
                                         (e.g. try ‘¶Ç). After that, the previous
                                         return value (i + 1) is used.

2

SmileBASIC, 85 74 byte

SPSET.,9M=MAINCNT
SPOFS.,ASIN(SIN(M/5))*122+192,112+71*ASIN(SIN(M/3))EXEC.

Vị trí của quả bóng có thể được mô hình hóa bằng 2 sóng tam giác, và cách ngắn nhất tôi có thể tìm thấy để tạo ra chúng trong SmileBASIC là arcsine (sin (x)). (thuật toán sử dụng MOD dài hơn kể từ khi SB sử dụng MODthay vì %)


2

CSS / HTML, 200 + 7 = 207 byte

p{position:relative}a{position:absolute;animation:infinite linear alternate;animation-name:x,y;animation-duration:7.9s,2.3s}@keyframes x{from{left:0}to{left:79ch}}@keyframes y{from{top:0}to{top:24em}}
<p><a>O

Phiên bản này cho bạn thấy kích thước của khung vẽ và cũng mang lại cho hình ảnh động một cảm giác rõ nét hơn:


2

APL Dyalog, 44 byte

{⎕SM∘←0,G←⍺+⍵⋄G∇⍵×1-2×⊃1 G∨.≥G⎕SD⊣⎕DL.1}⍨1 1

Giải trình:

  • {... }⍨1 1: gọi hàm đã cho với = ⍵ = 1 1
    • ⎕SM∘←0,G←⍺+⍵: lưu trữ ⍺+⍵trong G, hiển thị 0tại vị trí đó trong ⎕SMcửa sổ.
    • ⎕DL.1: đợi 1/10 giây
    • ⊃1 G∨.≥G⎕SD: kiểm tra xem Gcó ở ⎕SMranh giới cửa sổ không ( 1≥Ghoặc G≥⎕SD, ⎕SDlà hình ảnh của creen d )
    • 1-2×: ánh xạ [1,0]lên [¯1,1], để lật hướng di chuyển
    • ⍵×: nhân hướng đi hiện tại của nó
    • G∇: đệ quy, hãy Glà vị trí mới ( ) và ⍵....là hướng mới ( ).

Đây có phải là liên tục mở và đóng thiết bị đầu cuối khi nó chạy? Thật khó để ngăn điều này chạy khi nó khởi động, vì thiết bị đầu cuối đóng và mở lại cứ sau một phần mười giây (ít nhất là trên Windows).
ren

1
@wptreanor: cố định
marinus

tuyệt, công việc tuyệt vời!
ren

2

PHP, 112 97 94 103 102 byte

for(;;usleep(1e5),$i%=624)echo($r=str_repeat)(A^K,99),$r(A^a,abs($i%78-39)),O,$r(A^K,abs($i++%48-24));

trả lại một vốn Otrên lưới 40x25, bắt đầu từ góc trên bên phải;
in 99 dòng mới để xóa màn hình.

Chạy với -nr.

A^K= chr(10)= dòng mới
A^a= chr(32)= không gian


1
Chào Titus là tôi một lần nữa. for($d=$e=-1;;usleep(1e5))echo($r=str_repeat)(A^K,99),$r(A^a,$x+=$d*=$x%79?1:-1),O,$r(A^K,$y+=$e*=$y%24?1:-1);. Modulo sai ở 0 và N và hoàn nguyên hướng. Đáng buồn thay, chúng ta phải khởi tạo $ d và $ e thành -1 nhưng vẫn nhận được một số tiền tiết kiệm. $x%79<=>.5cũng hoạt động cho các byte tương tự.
Christoph

1
Chào @Christoph chào mừng trở lại. Lạ: khi tôi sao chép Nội dung của bạn, nó có 116 byte thay vì 110. Nhưng nó đã truyền cảm hứng cho tôi đến một thứ gì đó ngắn hơn rất nhiều.
Tít

Chúng tôi chắc chắn là một nhóm tốt;) Điều kỳ lạ về bản sao Tôi không biết tại sao.
Christoph

2

Simons CƠ BẢN (C64), 66 65 byte

Một byte được lưu cảm ơn @ShaunBebbers.

Tôi chỉ cần một dòng ở đây, vì Simons Lúc Basic có chức năng modulo.
AfaIk, điều này đòi hỏi một mô-đun BASIC vật lý C64 và Simons
(hoặc bất kỳ tiện ích mở rộng BASIC nào khác có modchức năng).

0fori=0to623:print"{CLR}":poke1024+40*abs(mod(i,48)-24)+abs(mod(i,78)-39),81:next:goto

Nhập vào 69 ký tự này:

0fOi=0TO623:?"{CLR}":pO1024+40*aB(mod(i,48)-24)+aB(mod(i,78)-39),81:nE:gO

{CLR}PETSCII 147, giúp xóa màn hình. Sử dụng Shift + CLR / HOME để nhập nó vào.

bytecount

Khi lưu vào đĩa, phải mất 65 byte, vì các lệnh được tokenized:
for, to, poke, abs, nextgotolà một trong byte mỗi; modmất hai byte.
Điều đó tạo ra 59 byte mã cộng với 4 byte cho con trỏ và 2 byte cho số dòng.

Để tham khảo, xem Ánh xạ C64 và tìm kiếm $800(Văn bản chương trình BASIC).
(Bạn có thể tìm thấy Vùng bộ nhớ màn hình video tại $400.)

phá vỡ

Các vòng lặp chương trình Itừ 0 đến 623 (= LCM là 48 và 78 trừ 1). Trong vòng

  • màn hình bị xóa
  • I được ánh xạ tới 39..0., 38 tương ứng 24..0..23
  • và blob (PETSCII 81) được đặt ở vị trí tương ứng trong bộ nhớ video
    (giống như chương trình gốc).

Khi vòng lặp hoàn thành, chương trình được khởi động lại bằng cách nhảy đến dòng 0.

C64 BASIC, 77 76 byte

0fori=0to623:print"{CLR}"
1poke1024+40*abs(i-48*int(i/48)-24)+abs(i-78*int(i/78)-39),81:next:goto

Thật không may, tôi cần hai dòng, bởi vì ngay cả với tất cả các chữ viết tắt có thể, nó sẽ mất 83 ký tự - quá nhiều để sử dụng trình chỉnh sửa dòng C64:

0fOi=0to623:?"{CLR}":pO1024+40*aB(i-48*int(i/48)-24)+aB(i-78*int(i/78)-39),81:nE:gO

(Một trình soạn thảo hex có thể được sử dụng để tạo một dòng dài hơn - sẽ tạo ra 73 byte.)


1
:;
Dấu

1
Ngoài ra, nếu bạn bắt đầu ở dòng số 0, bạn chỉ có thể sử dụng gototrong phiên bản hai lớp của mình, vì gotokhông có số giả định nào goto 0trên BASIC 2
Shaun Bebbers

Nếu bạn muốn nhận thêm các lệnh trong danh sách C64 BASIC của mình, hãy nhập nó vào C128 ở chế độ 128, lưu nó vào đĩa và tải lại vào chế độ C64, C128 có giới hạn 160 ký tự theo mặc định để rào cản này có thể bị phá vỡ sử dụng từ viết tắt hàng hóa.
Shaun Bebbers

@ShaunBebbers rất vui được biết. Đã từ rất lâu. Tôi cũng muốn thực hiện điều này trong mã máy ... cố gắng tóm tắt lại các thường trình kernel; không chắc chắn khi tôi phải sao lưu những gì đăng ký; danh sách kernel hoàn chỉnh là trực tuyến ; Tôi chỉ không thể dành thời gian để đào thêm. Bạn có muốn hoàn thành điều này ?
Tít

Tôi sẽ tạo ra một phiên bản MC, mặc dù tôi nghĩ rằng việc đưa nó vào thử thách của riêng tôi sẽ là quá nuông chiều ngay cả đối với tôi. Cách nhanh nhất là ghi byte trực tiếp lên màn hình từ $0400đến $07e7; hoặc sử dụng các họa tiết. Sử dụng Kernal với $ffd2(bộ tích lũy đầu ra) sẽ hoạt động khi bạn có thể đặt vị trí X và Y trên con trỏ đủ dễ dàng (tôi không nhớ cuộc gọi cho điều đó), nhưng bạn có thể phải tránh vị trí ký tự cuối cùng trong trường hợp nó buộc một nguồn cấp dữ liệu.
Shaun Bebbers

1

Python 2, 176 168 byte

Điều này giả định kích thước thiết bị đầu cuối là 80x24. Chắc chắn là không tối ưu nhưng tôi mới chơi golf nên vâng.

import time;x=y=d=e=1
while 1:
 m=[[' 'for i in' '*80]for j in' '*24];x+=d;y+=e;m[y][x]='O';time.sleep(.1)
 if x%79<1:d=-d
 if y%23<1:e=-e 
 for r in m:print''.join(r)

Cảm ơn R. Kap đã đề xuất x% 79 <1 thay vì x <1or x> 79 và ditto cho y.


Bạn có thể lưu một vài byte bằng cách thay thế x<1or x>78bằng x%79<0y<1or y>22bằng y%23<1.
R. Kap

1

Rebol / View, 284 266 byte

rebol[]p: 3x9 d:[3 3]view layout[b: box blue 99x99 effect[draw[circle p 2]]rate :0.01 feel[engage: func[f a e][if a = 'time[case/all[p/x < 2[d/1: abs d/1]p/y < 2[d/2: abs d/2]p/x > 98[d/1: negate d/1]p/y > 98[d/2: negate d/2]]p/x: p/x + d/1 p/y: p/y + d/2 show b]]]]

Ung dung:

rebol []

p: 3x9     ;; starting position
d: [3 3]   ;; direction

view layout [
    b: box blue 99x99 effect [
        draw [
            circle p 2
        ]
    ]

    rate :0.01 feel [
        engage: func [f a e] [
            if a = 'time [
                case/all [
                    p/x < 2  [d/1: abs d/1]
                    p/y < 2  [d/2: abs d/2]
                    p/x > 98 [d/1: negate d/1]
                    p/y > 98 [d/2: negate d/2]
                ]
                p/x: p/x + d/1
                p/y: p/y + d/2
                show b
            ]
        ]
    ]
]

1

C 294 byte

#include<graphics.h> f(){int d=0;g,x,y,a=0,b=0;initgraph(&d,&g,NULL);x=30;y=30;while(1){x+=6;y+=7;if(y<60)b=0;if(x<60)a=0;if((y>getmaxy()-40)) b=!b;if((x>getmaxx()-40))a=!a;if(b){y-=18;x+=3;}if(a){x-=15;y+=2;}usleep(10000);setcolor(4);cleardevice();circle(x, y,30);floodfill(x,y,4);delay(45);}}

Phiên bản bị đánh cắp:

#include<graphics.h>
void f()
{
 int d=DETECT,g,x,y,r=30,a=0,b=0;
 initgraph(&d,&g,NULL);
 x=30;
 y=30;

 while(1)
 {
   x+=6;
   y+=7;

   if(y<60)
     b=0;
   if(x<60)
     a=0;     

   if((y>getmaxy()-40))
        b=!b;

   if((x>getmaxx()-40))
        a=!a;

    if(b)
    {       
        y-=18;
        x+=3;
    }

    if(a)
    {       
       x-=15;
       y+=2;               
    } 
    usleep(10000);
    setcolor(RED);
    cleardevice();
    circle(x,y,r);
    floodfill(x,y,RED);
    delay(45);

  }   

}

Giải trình

  • Vì vậy, để bắt đầu với điều này, tôi đã phải graphics.hvào /usr/includethư mục của mình . Do đó, tôi đã tìm kiếm và điều này là những gì tôi tìm thấy. Đây là một triển khai Đồ họa TurboC sử dụng SDL cho Linux. Người ta cũng có thể sử dụng OpenGL. Trong windows, tôi đoán nó đã được cài đặt, không chắc chắn về MacOS.
  • void initgraph(int *graphdriver, int *graphmode, char *pathtodriver);khởi chạy hệ thống và đặt nó ở chế độ đồ họa, trong trường hợp này trình điều khiển đồ họa được tự động phát hiện. Vui lòng tham khảo liên kết này để biết thêm chi tiết.
  • xy là tọa độ xác định vị trí của quả bóng.
  • ablà các cờ, ađược đặt thành 0 khi xgiá trị giảm xuống dưới 60 và bđược đặt thành 0 khiy giảm xuống dưới 60.
  • Các cờ được bật khi xy vượt quá giá trị biên của cửa sổ và tọa độ được điều chỉnh tương ứng.
  • Tôi đặt một usleepcái để CPU của tôi không bị căng thẳng.
  • Thông thường người ta nên sử dụng một closegraph()cuộc gọi, để đóng cửa sổ. Nhưng nó bị thiếu ở đây.

Phải được biên dịch với cờ liên kết -lgraph

Nó chạy mượt hơn trên phần cứng thực. :)

Bouncing Red Ball


Là báo cáo nhập khẩu cần thiết để chạy chương trình này?
Kritixi Lithos

@KritixiLithos Vâng thưa ông; Đã cập nhật! bạn cần bao gồm graphics.h. Câu trả lời này Askubfox.com/questions/525051/ đã hữu ích.
Abel Tom

1

MATL , 42 byte

1thXH_XI`Xx8E70hZ"79HZ}&(DH4M\1>EqI*XIH+XH

Điều này sử dụng màn hình và ký tự 70 × 16 O. Nếu bạn chờ đợi một vài lần nảy, bạn sẽ thấy quả bóng đập vào một góc.

Hãy thử tại MATL Online!

Kích thước màn hình có thể dễ dàng sửa đổi trong mã. Phần có liên quan là 8E70, đẩy 8, nhân đôi và đẩy 70. Ví dụ: đối với màn hình 80 × 25 thay thế bằng cách 5W80đẩy 5, bình phương và đẩy 80(hoặc thay thế bằng 25 80, nhưng điều đó đòi hỏi thêm một byte).

Ngoài ra, thêm tDvào cuối mã cho thấy vị trí hiện tại trong thời gian thực (dọc, sau đó ngang, 1 1là phía trên bên trái). Ví dụ, đối với 80×18màn hình,

1thXH_XI`Xx9E80hZ"79HZ}&(DH4M\1>EqI*XIH+XHtD

Hãy thử nó!

Giải trình

Điều này sử dụng một vòng lặp vô hạn. Vị trí được giữ trong bảng tạm Hdưới dạng vectơ 1 × 2 và hướng được giữ trong bảng tạm Idưới dạng vectơ 1 × 2 với các mục 1hoặc -1.

Mỗi lần lặp sẽ xóa màn hình, xác định ma trận khoảng trắng, viết một Ovị trí có liên quan và hiển thị nó. Sau đó, vị trí và directio cần phải được cập nhật.

Vị trí được 1dựa trên, và do đó các cạnh của màn hình 1và kích thước màn hình tối đa. Vì vậy, nếu kích thước màn hình modulo vị trí cho 0hoặc 1trong các thành phần thứ nhất hoặc thứ hai, có nghĩa là chúng ta đã đạt được cạnh dọc hoặc ngang tương ứng, thành phần đó của vectơ chỉ hướng bị phủ định. Sau đó, hướng mới được thêm vào vị trí hiện tại để có được vị trí mới.


1

Đây là danh sách ZX Spectrum.

  10 FOR n=0 to 7
  20 READ a: POKE USR "a"+n, a
  30 NEXT n
  40 DATA 60,126,243,251,255,255,126,60
  50 LET x=10:LET y=10:LET vx=1: LET vy=1
  60 PRINT AT y,x;"\a"
  70 IF x<1 OR x>30 THEN LET vx=-vx
  80 IF y<1 OR x>20 THEN LET vy=-vy
  90 LET x=x+vx: LET y=y+vy
 100 PRINT AT y-vy,x-vx;" ": GO TO 60

DrlB đầu tiên đẹp - bạn có thể vui lòng bao gồm số byte. Tôi cho rằng điều này sẽ hoạt động trên bất kỳ Speccy bao gồm máy 16K?
Shaun Bebbers

Xin chào, đây là 201 byte, bạn có thể bỏ qua 4 dòng đầu tiên nhưng sau đó bạn chỉ nhận được một ký tự "a" nảy nhưng nó giúp bạn tiết kiệm 64 byte. Tôi sẽ cố gắng tối ưu hóa. Điều này không có gì lạ mắt cả và sẽ hoạt động trên mọi mô hình Spectrum :)
DrIB

Ok tôi đã quản lý để cắt nó xuống còn 185 bằng cách ngưng tụ các dòng một chút mà không làm rơi đồ họa bóng. Mặc dù nó ít đọc hơn một chút nhưng nó nhanh hơn.
DrIB

1

Lời nguyền C +, 190 byte

#include<curses.h>
w;h;x;y;d;main(e){initscr();curs_set(0);getmaxyx(stdscr,h,w);for(d=e;;usleep(20000),mvaddch(y,x,32)){mvaddch(y+=d,x+=e,48);if(!y||y>h-2)d=-d;if(!x||x>w-2)e=-e;refresh();}}

Giải trình:

#include<curses.h>
w;h;x;y;d;
main(e)
{
    initscr();
    curs_set(0);
    getmaxyx(stdscr,h,w);

    // initialize distances to 1 (e is 1 when called without arguments)
    // wait for 1/5 second, then write space character at current pos
    for(d=e;;usleep(20000),mvaddch(y,x,32))
    {
        // advance current pos and write ball character (`0`)
        mvaddch(y+=d,x+=e,48);

        // check and change direction:
        if(!y||y>h-2)d=-d;
        if(!x||x>w-2)e=-e;

        // trigger output to screen:
        refresh();
    }
}

1

Lua ( LÖVE 2D ), 130 byte

x,y,a,b=0,0,1,1
function love.draw()a=(x<0 or x>800)and-a or a
b=(y<0 or y>600)and-b or b
x=x+a
y=y+b
love.graphics.points(x,y)end

Lua không phải là ngôn ngữ tốt nhất khi nói về golf, nhưng ở đây bạn đi! Một vài điểm đáng nói:

  • Kích thước vải mặc định là 800 x 600. Nó có thể được thay đổi trong tệp cấu hình, nhưng tôi không thấy bất kỳ hạn chế kích thước nào, vì vậy tôi đã để nguyên như vậy.

  • love.draw()là chức năng vẽ của LÖVE và nó có một tên được xác định trước. Các hàm LÖVE thay thế có thể được sử dụng sẽ là love.update(dt)love.run()- hàm đầu tiên dài hơn, tính bằng byte và hàm sau ngắn hơn, vâng, nhưng không có vòng lặp vô hạn tích hợp. Vì vậy, draw()dường như là đặt cược tốt nhất của chúng tôi ở đây.

  • Các phiên bản trên sử dụng love.graphics.pointsđể vẽ bóng. Mặc dù ngắn hơn, tôi không chắc nó được cho phép. Đây là một GIF về cách nó chạy:

Animated screenshot - point

Như bạn có thể thấy (hoặc có lẽ không thể), có một pixel di chuyển trên màn hình. Trong khi điều đó tiết kiệm tối đa byte, nó không phải là kết quả hài lòng nhất.

Vì vậy, tôi đã thực hiện một giải pháp thay thế 131 byte :

x,y,a,b=0,0,1,1
function love.draw()a=(x<0 or x>795)and-a or a
b=(y<0 or y>595)and-b or b
x=x+a
y=y+b
love.graphics.print(0,x,y)end

Cái này sử dụng love.graphics.print- in văn bản - và 0như một quả bóng, làm cho nó rõ ràng và hấp dẫn hơn nhiều.

Animated screenshot - zero


1

CHIP-8, 36 34 28 byte

FF29 'LDF I,vF //load digit sprite for the value of vF (should be 0)

4000 'SNE v0,0 //if x is 0...
6201 'LD v2,1 //set x velocity to 1
403C 'SNE v0,3C //if x is 3C...
62FF 'LD v2,FF //set x velocity to -1
4100 'SNE v1,0 //if y is 0...
6301 'LD v3,1 //set y velocity to 1
411B 'SNE v1,1B //if y is 1B...
63FF 'LD v3,FF //set y velocity to -1

D015 'DRW v0,v1,5 //draw sprite
D015 'DRW v0,v1,5 //draw sprite again to clear it.
8024 'ADD v0,v2 //add x velocity to x
8134 'ADD v1,v3 //add y velocity to y

1202 'JMP 202 //jump to second instruction

Không có mánh khóe nào ở đây ...

Yêu cầu một trình thông dịch vẽ các sprite chính xác (chỉ có thể vẽ một sprite trên mỗi khung, làm chậm chương trình đủ để bạn có thể nhìn thấy nó).

Video chất lượng thấp


0

ZX Spectrum BASIC - 179 byte

Ở đây nó chỉ ngưng tụ một chút. Đó là 179 byte với đồ họa bóng đi kèm

  10 LET a=10: LET b=10: LET c=1: LET d=-1: FOR e=0 TO 7: READ f: POKE USR "a"+e, f: NEXT e
  20 DATA 60, 126,243,251,255,255,126,60
  30 PRINT AT b,a;"\a"
  40 IF a<1 OR a>30 THEN LET c=-c
  50 IF b<1 OR b>20 THEN LET d=-d
  60 LET a=a+c: LET b=b+d: PRINT AT b-d, a-c;" ": GO TO 30

Vui lòng xem đánh dấu được sử dụng để trả lời, cũng bằng cách sử dụng ký tự ohoặc Obạn có thể lưu một số byte trong danh sách tượng trưng; bạn cũng có thể chỉnh sửa các câu trả lời trước đó khi bạn có các giải pháp cải tiến, thay vì trả lời lại cùng một câu hỏi
Shaun Bebbers
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.