8-битный стиль прыгающего мяча вокруг холста


20

Вдохновленный этим списком из руководства пользователя Commodore 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

Создайте аналогичную программу на выбранном вами языке / платформе, чтобы отразить похожий на шарик объект вокруг вашего терминала, экрана, холста или другой области визуального отображения.

Вы не должны точно имитировать графику PETSCII C64, просто Oили oподойдет, и вам не нужно использовать GOTOкоманду, если она все еще существует на вашем языке. Пока ваш шар начинается сверху холста и движется по диагонали, пока не достигнет предела холста, а затем соответственно отскакивает, как показано ниже:

  • Двигаясь вниз и вправо и ударяясь о нижнюю часть экрана, подпрыгивает и продолжает движение вправо;
  • Путешествие вверх и вправо, попадание в крайнюю правую границу и отскок влево и вверх;
  • Путешествие влево и вверх и удар по вершине, отскок влево и вниз;
  • Путешествие налево и вниз и достигает самой левой границы, подпрыгивает направо и вниз;
  • Бьет любой угол и меняет направление;

Тогда у нас все хорошо.

Вам также не нужно перемещать шарик на 8 пикселей одновременно, как это происходит в листинге BASIC на C64; вы можете перемещать один блок символов или один пиксель за раз, в зависимости от того, что вы считаете наиболее подходящим.

Чтобы увидеть этот листинг BASIC, вы можете ввести его с помощью этого онлайн-эмулятора Commodore 64, если ваш браузер поддерживает Flash.


2
JavaScript холст. D'эм.
Мэтью Ро

Я не уверен, что вы называете экраном в настоящее время. Раньше вы смотрели только экран и границу через ваш телевизор или VDU ... и теперь у вас есть терминалы, окна, холсты, стандартный вывод и т. Д. ... это меня очень смущает.
Шон Бебберс

Было бы лучше, если бы у нас был постоянный размер пикселя.
Мэтью Ро

4
Можем ли мы принять размер экрана 1x1 и напечатать o навсегда?
Мэтью Ро

1
возможный дубликат ASCII Ball in Box Animation
Тит

Ответы:


3

6502 машинный код (C64), 90 89 91 байт

+2 байта, потому что для этого нужен адрес загрузки (не PIC из-за самостоятельной модификации)

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

Онлайн демо

Использование: sys49152

Я изо всех сил старался уменьшить размер (например, НЕ используя IRQ для измерения времени, а вместо этого глупые пустые петли), все еще невозможно достичь уровня гольфового C64 BASIC от Titus : о, хорошо. Но выглядит менее мерцающим;)

Пояснение: (порок разборки)

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

Просто для удовольствия, вот более профессиональный вариант, использующий спрайт для мяча и мигающий границу при попадании в 385 байт (содержащий данные спрайта, которые используются на месте ):

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 

Демонстрационная версия онлайн - | - источник ассемблера ca65

Запустите и остановите прыгающий мяч с помощью sys49152.

  • Это позволяет C64 BASIC работать, что достигается путем перемещения адресного пространства VIC-II вверх $C000, что требует копирования содержимого экрана и набора символов (шрифта).
  • Он подключается к IRQ системы и, чтобы избежать мерцания, изменяет источник этого IRQ на графический чип VIC-II, поэтому обновления всегда выполняются между кадрами.
  • Глюки:
    1. RUN/STOP + RESTORE сломан, не пытайтесь.
    2. При использовании VIC-II в качестве источника IRQ курсор мигает немного медленнее, а также TI$будет отставать.
    3. при остановке, когда граница мигает (очень маловероятно, но возможно), она остается белой - вы должны восстановить ее вручную.

1
Это не совсем независимо, не так ли? Я вижу два абсолютных LDA и два STA. Отличная работа, тем не менее!
Тит

Чёрт возьми, вы правы: о, я забыл о модификации себя! Я буду обновлять, как только я на ПК.
Феликс Палмен

1
Исправлено @Titus ... и просто для удовольствия, добавил "лучший" вариант :)
Феликс Палмен

Рассматривали ли вы упаковку спрайта? (Хм ... использовать кодировки ROM?) И я бы предпочел inc $d020более jsr flash;) hitshimselfwithalargetrout подмигнул изумительно!
Тит

1
@Titus сэкономит 2 байта, да. Что касается адреса загрузки, он является частью действительного .prgфайла, и из моего мета-вопроса, который я здесь взял, я должен включить его ... возможно, мог бы пропустить его, если бы код был позиционно независимым.
Феликс Пальмен

14

Утилиты Bash + Unix, 125 117 байт

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
}

Анимация пробного запуска:

Анимация пробного запуска


6
Он попал точно в угол! : O
mbomb007

11

CP-1610 в сборе, 6764 62 DECLE = 78 байт

Этот код предназначен для запуска на Intellivision . Он использует один из своих аппаратных спрайтов, известный как MOB (для мобильного объекта).

Код операции CP-1610 кодируется 10-битным значением, известным как «DECLE». Длина этой программы составляет 62 DECLE, начиная с 4800 долларов США и заканчивая 483 долларами США.

Шестнадцатеричный дамп + источник

                            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

Выход

выход


10

HTML (Microsoft Edge / Internet Explorer), 81 байт

Представьте, что это 1998 год с этими вложенными <marquee>тегами:

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

Протестировано в Microsoft Edge, хотя из того, что я читал, IE также должен поддерживать маркеры. Решительно не работает в Chrome.

Установка direction=upсохранит 2 байта, но нарушит правило, согласно которому мяч должен начинаться сверху холста.


К сожалению, это неверный ответ, так как мяч не движется по диагонали, как того требует вызов.
El'endia Starman

Вы пробовали это в Microsoft Edge? Похоже, что Chrome не поддерживает этот directionатрибут.
Джек Броунштайн

Да, мои извинения - это работает в Edge. Я могу подтвердить, что он не работает в Chrome, и могу подтвердить, что он работает в Firefox и Internet Explorer. Три из четырех неплохо (и вам нужен только один, чтобы этот ответ был действительным). +1
El'endia Starman

1
+1 за marquee, это довольно креативно!
Метония

Работал в Chrome для меня.
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

Весьма буквальный перевод, я не удивлюсь, если есть хитрости, чтобы сделать его меньше.

Экран 16x8 и 1-индексированный, поэтому константы разные.

~ это SourceCoder способ написать символ отрицания.

GIF подпрыгивая O

Это выглядит более гладко на оборудовании.


Вы уверены, что это 70 байтов? Похоже, меньше, чем это.
12Me21

@ 12Me21 сколько байтов ты считаешь? Я получаю 80 байт, если сохраню это на калькуляторе, и 10 байт для пустой программы, которая согласуется с моим счетом.
Harold

О, я полагаю, тогда я ошибся.
12Me21

7

Befunge, 209 байтов

>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_^

Предполагается, что размер экрана составляет 80x25, но вы можете легко настроить диапазон, заменив "O"(79) в последней строке и *64(24) во второй последней строке (обратите внимание, что вторая последняя строка выполняется справа налево). Скорость также можно отрегулировать, заменив "2"(50) на последней строке.


7

Ява, 184 176 байт

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

Это использует ANSI Escape-последовательности для перемещения курсора, который является объектом, который прыгает вокруг 85 x 25дисплея терминала. Сохранить в файл с именем A.java.

Ungolfed

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

демонстрация

пример


Это код гольф, поэтому вы хотите удалить Thread.sleep(50). И ваши игры в гольф и без игры не совпадают.
Якоб

4

Clojure, 398 380 375 байт

(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 байт, изменив имя шрифта на пустую строку по умолчанию, вставив проверку границ и исправив проблему с нижней границей (которую вы можете увидеть в GIF). Исправление того, что фактически сохраненные байты.

-5 байт, изменив более лаконичный синтаксис деструктурирования и сократив шарик на пиксель.

Использует Quil .

Я пытался переключиться в функциональный режим, но это потребовало много дополнительного кода и оказалось дороже.

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

Мяч подпрыгивая GIF

(Обратите внимание, что новая версия не отскакивает рано внизу экрана, как в GIF.)


Я только что понял, что у меня (+ 0 font-size)там. Это смущает. Я исправлю это в следующей версии. Должно спасти меня как 5 байтов.
Carcigenicate

4

Ракетка 247 байт

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

Ungolfed:

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

Выход:

введите описание изображения здесь


1
Игра в ракетбол с ракеткой!
ckjbgames

Этот подходит!
17

«Ракетка» происходит от языка программирования «Схема»: после «Схемы» (хитрый план) идет «Ракетка» (мошенничество или мошенничество)!
rnso

@mso Еще лучше!
ckjbgames

3

Желе, 37 байт

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

С некоторой помощью из этого ответа для получения правильного цикла и escape-символов. В настоящее время он отображается на экране размером 80x24, но его можно легко изменить в коде.

Координаты в каждом направлении могут быть представлены как элементы двух списков, [0, 1,..., 24, 23,..., 1]и [0, 1,..., 80, 79,..., 1], давайте назовем их YиX которые бесконечно повторяются. Это бесконечное повторение можно эмулировать с помощью модульной индексации - с помощью Jelly. Пример: в iитерации мяч находится в положении (X[i%|X|], Y[i%|Y|]) = (iịY, iịX). Движущийся шарик - это просто курсор, который помещается в позицию, испуская iịYновые строки и iịXпробелы.

демонстрация

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

объяснение

“ñ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 байта

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

Положение шара можно смоделировать с помощью двух треугольных волн, и самый короткий способ, которым я смог найти их в SmileBASIC, был арксинус (синус (x)). (алгоритм с использованием MOD был длиннее, поскольку SB использует MODвместо %)


2

CSS / HTML, 200 + 7 = 207 байт

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

Эта версия показывает вам размер холста, а также дает анимации более пиксельное ощущение:


2

Dyalog APL, 44 байта

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

Объяснение:

  • {...}⍨1 1 : вызвать данную функцию с ⍺ = ⍵ = 1 1
    • ⎕SM∘←0,G←⍺+⍵: сохранить ⍺+⍵в G, отобразить 0в этом месте в ⎕SMокне.
    • ⎕DL.1: подождите 1/10 секунды
    • ⊃1 G∨.≥G⎕SD: Проверка , если Gнаходится на ⎕SMгранице окна ( 1≥Gили G≥⎕SD, ⎕SDэто с Creen д imensions)
    • 1-2×: Карта [1,0]на [¯1,1], чтобы изменить направление движения
    • ⍵×: умножить текущее направление движения на
    • G∇: рекурсия, пусть Gбудет новое местоположение ( ) и ⍵....будет новое направление ( ).

Это должно постоянно открывать и закрывать терминалы во время работы? Довольно сложно остановить его запуск после его запуска, поскольку терминал закрывается и открывается каждую десятую секунды (по крайней мере, в Windows).
жэнь

1
@wptreanor: исправлено
marinus

классно, отличная работа!
жэнь

2

PHP, 112 97 94 103 102 байта

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

отскакивает заглавную Oв сетке 40х25, начиная с правого верхнего угла;
печатает 99 строк, чтобы очистить экран.

Беги с -nr.

A^K= chr(10)= новая строка
A^a= chr(32)= пробел


1
Привет Титус, это снова я. 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);, Модуль имеет значение false в 0 и N и меняет направление. К сожалению, мы должны инициализировать $ d и $ e в -1, но все же получить некоторую экономию. $x%79<=>.5также работает для тех же байтов.
Кристоф

1
Эй, Кристоф, добро пожаловать обратно. Странно: когда я копировал Твой материал, у него было 116 байтов вместо 110. Но это вдохновило меня на что-то намного короче.
Тит

Мы определенно хорошая команда;) Странная вещь в копировании. Я понятия не имею, почему.
Кристоф

2

Симонс Бейсик (C64), 66 65 байт

Один байт сохранен благодаря @ShaunBebbers.

Мне нужна только одна строка, потому что Simons Basic имеет функцию по модулю.
На самом деле, для этого требуется физический C64 и модуль BASIC Симона
(или любое другое расширение BASIC, имеющее modфункцию).

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

Введите следующие 69 символов:

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

{CLR}это PETSCII 147, который очищает экран. Используйте Shift + CLR / HOME, чтобы ввести его.

ByteCount

При сохранении на диск, он занимает 65 байт, так как команды лексемы:
for, to, poke, abs, nextи gotoодин байт каждый; modзанимает два байта.
Это составляет 59 байтов кода плюс 4 байта для указателей и 2 байта для номера строки.

Для справки см. Сопоставление C64 и поиск $800(основной текст программы).
(Вы можете найти область памяти видеоэкрана на$400 .)

сломать

Программа зацикливается Iот 0 до 623 (= LCM 48 и 78 минус 1). В петле

  • экран очищен
  • I отображается на 39..0..38 соответственно на 24..0..23
  • и BLOB-объект (PETSCII 81) помещается в соответствующую позицию в видеопамяти
    (как это делает оригинальная программа).

Когда цикл завершен, программа перезапускается, переходя к строке 0.

C64 BASIC, 77 76 байт

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

К сожалению, мне нужны две строки, потому что даже при всех возможных сокращениях потребуется 83 символа - слишком много, чтобы использовать редактор строк C64:

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

(Шестнадцатеричный редактор может быть использован для создания более длинной строки, которая будет составлять 73 байта.)


1
Командные разделители команд есть :и нет;
Shaun Bebbers

1
Кроме того, если вы начинаете с нулевой строки, вы можете просто использовать gotoв своей gotogoto 0
двухстрочной

Если вы хотите получить больше команд в своем списке C64 BASIC, введите его в C128 в режиме 128, сохраните его на диск и загрузите обратно в режим C64, по умолчанию C128 имеет ограничение в 160 символов, поэтому этот барьер может быть преодолен используя ключевые слова Commodore.
Шон Бебберс

@ShaunBebbers приятно знать. Это было так давно. Я также хотел реализовать это в машинном коде ... пытаясь повторить подпрограммы ядра; не уверен, когда мне нужно сделать резервную копию, какие регистры; полный список ядра находится в сети ; Я просто не могу найти время, чтобы копать дальше. Хотите завершить это ?
Тит

Я собирался сделать MC-версию, хотя я думаю, что подвергнуть ее собственным испытаниям было бы чрезмерно снисходительно даже для меня. Самый быстрый способ - записать байт непосредственно на экран из $0400в $07e7; или использовать спрайты. Использование Kernal с $ffd2(выходной аккумулятор) будет работать, так как вы можете достаточно легко установить X и Y pos на курсор (я не помню вызов этого), но вам, возможно, придется избегать позиции последнего символа в случае, если он вызывает перевод строки.
Шон Бебберс

1

Python 2, 176 168 байт

Это предполагает размер терминала 80x24. Определенно не оптимально, но я новичок в гольфе, так что да.

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)

Спасибо Р. Капу за предложение x% 79 <1 вместо x <1 или x> 79 и то же самое для y.


Вы можете сэкономить несколько байт, заменяя x<1or x>78с x%79<0и y<1or y>22с y%23<1.
Р. Кап

1

Rebol / View, 284 266 байт

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

Ungolfed:

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 байта

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

Безголовая версия:

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

  }   

}

объяснение

  • Итак, чтобы начать с этого, я должен был попасть graphics.hв мой /usr/includeкаталог. Поэтому я искал и это то, что я нашел. Это графическая реализация TurboC, использующая SDL для Linux. Можно также использовать OpenGL. В Windows, я думаю, он уже установлен, не уверен насчет MacOS.
  • void initgraph(int *graphdriver, int *graphmode, char *pathtodriver);инициализирует систему и переводит ее в графический режим, в этом случае графический драйвер определяется автоматически. Пожалуйста, обратитесь к этой ссылке для более подробной информации.
  • x и y координаты, которые определяют положение мяча.
  • aи bявляются флагами, aустанавливается в ноль, когда xзначение опускается ниже 60, и bустанавливается в ноль, когдаy опускается ниже 60.
  • Флаги переключаются, когда xиy превышают граничные значения окна, и координаты соответственно корректируются.
  • Я ставлю usleepтак, чтобы мой процессор не напрягался.
  • Обычно нужно использовать closegraph()звонок, чтобы закрыть окно. Но здесь этого не хватает.

Должен быть скомпилирован с флагом компоновщика -lgraph

На реальном оборудовании он работает более плавно. :)

Прыгающий красный шар


Требуются ли операторы import для запуска этой программы?
Kritixi Lithos

@KritixiLithos Да, сэр; Обновлено! вам нужно включить graphics.h. Этот ответ askubuntu.com/questions/525051/… оказался полезным.
Абель Том

1

MATL , 42 байта

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

Это использует экран 70 × 16 и символ O. Если вы подождете несколько отскоков, вы увидите, как мяч попадает в угол.

Попробуйте в MATL Online!

Размер экрана можно легко изменить в коде. Соответствующая часть 8E70, которая толкает 8, удваивает и толкает 70. Например, для экрана 80 × 25 замените на 5W80, который выталкивает 5, возводит его в квадрат и толкает 80(или заменяет на 25 80, но для этого требуется еще один байт).

Кроме того, добавление tDв конце кода показывает текущую позицию в реальном времени (по вертикали, затем по горизонтали, 1 1вверху слева). Например, для 80×18экрана

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

Попробуйте тоже!

объяснение

Это использует бесконечный цикл. Положение сохраняется в буфере обмена Hкак вектор 1 × 2, а направление сохраняется в буфере обмена Iкак вектор 1 × 2 с записями 1или -1.

Каждая итерация очищает экран, определяет матрицу пробелов, записывает Oв соответствующую позицию и отображает ее. Затем положение и направление должны быть обновлены.

Положение на 1основе, и, следовательно, края экрана 1и максимальный размер экрана. Таким образом, если размер экрана по модулю дает 0или 1в первом, или во втором компонентах, что означает, что мы достигли вертикального или горизонтального края соответственно, этот компонент вектора направления отрицается. После этого новое направление добавляется к текущей позиции, чтобы получить новую позицию.


1

Вот список 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 - не могли бы вы включить подсчет байтов. Я предполагаю, что это будет работать на любом Speccy, включая 16K машин?
Шон Бебберс

Привет, это 201 байт, вы можете пропустить первые 4 строки, но затем вы получите просто подпрыгивающий символ «а», но это сэкономит вам 64 байта. Я постараюсь оптимизировать. Это ничего особенного и не будет работать на любой модели Spectrum :)
DrIB

Хорошо, мне удалось сократить его до 185, немного сузив линии без потери графики. Это немного менее читабельно, но это быстрее.
DrIB

1

C + curses, 190 байт

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

Объяснение:

#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 байт

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 - не лучший язык, когда дело доходит до кода гольфа, но вот, пожалуйста! Несколько моментов, которые стоит упомянуть:

  • Размер холста по умолчанию - 800 x 600. Его можно изменить в файле конфигурации, но я не увидел никаких ограничений по размеру, поэтому оставил его как есть.

  • love.draw()это функция рисования LÖVE, и она имеет предопределенное имя. Альтернативные функции LÖVE, которые можно было бы использовать, были бы love.update(dt)и love.run()- первая была бы длиннее в байтах, а вторая короче, да, но без встроенного бесконечного цикла. Таким образом, draw()кажется, наш лучший выбор здесь.

  • Выше версия использует love.graphics.pointsдля рисования мяча. Хотя короче, я не уверен, что это разрешено. Вот GIF как он работает:

Animated screenshot - point

Как вы можете видеть (или, возможно, не можете), на экране движется один пиксель. Хотя это экономит байты, это не самый удовлетворительный результат.

Итак, я сделал альтернативное 131-байтовое решение :

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

Этот использует love.graphics.print- который печатает текст - и 0как шар, делая его намного более заметным и привлекательным.

Animated screenshot - zero


1

ЧИП-8, 36 34 28 байт

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

Никаких хитростей здесь ...

Требуется интерпретатор, который правильно рисует спрайты (в кадре может быть нарисован только один спрайт, что замедляет программу настолько, чтобы вы могли ее видеть).

Видео низкого качества


0

ZX Spectrum BASIC - 179 байтов

Здесь это просто немного сжато. Это 179 байт с включённой графикой

  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

Пожалуйста, посмотрите на разметку, используемую для ответов, также используя символ, oили Oвы можете сохранить некоторые байты в символьном списке; Вы также можете редактировать предыдущие ответы, когда у вас есть улучшенные решения, вместо того, чтобы повторно отвечать на тот же вопрос
Шон Бебберс
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.