围绕画布的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

用您选择的语言/平台制作一个类似的程序,以在终端,屏幕,画布或其他视觉显示区域周围反弹类似球的物体。

您不必完全模仿C64的PETSCII图形,也可以简单地模仿Oo将其模仿,GOTO如果您的语言中仍然存在该命令,也不必使用该命令。只要您的球从画布的顶部开始并沿对角线移动,直到达到画布的极限,然后相应地弹跳,如下所示:

  • 向下和向右移动并撞击屏幕区域的底部,向上反弹并继续向右;
  • 向上和向右移动并撞到最右边的边界,然后向左和向上反弹;
  • 左右移动并撞击顶部,左右弹跳;
  • 左右移动并到达最左边界,右下移动;
  • 击中任何角落并反转方向;

那我们都很好

您也不必一次将球移动8个像素,就像C64的BASIC列表中那样。您可以一次移动一个字符块或一个像素,以您认为最合适的方式为准。

要查看此BASIC列表的工作原理,您可以使用此在线Commodore 64仿真器将其键入,前提是您的浏览器支持Flash。


2
JavaScript画布。'
马修·罗

我不确定您现在所说的屏幕是什么。您以前只能通过电视机或VDU来查看屏幕和边框区域,但是现在有了终端机,窗户,画布,标准输出等,这一切都让我感到困惑。
Shaun Bebbers

如果我们有一个恒定的像素大小值会更好。
马修·鲁

4
我们可以假设屏幕尺寸为1x1并永远打印吗?
马修·卢

Answers:


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进行计时,而是使用愚蠢的空循环),仍然无法达到Titus高尔夫C64 BASIC的水平:哦,好。但它看起来不那么闪烁;)

说明:(副拆卸)

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。尽管如此,还是很棒的!
泰特斯

该死的,你是对的:我忘了自我修改!我将在PC上立即进行更新。
菲利克斯·帕尔姆

1
@Titus已修复...只是为了好玩,添加了一个“更好的”变体:)
Felix Palmen

您是否考虑过打包精灵?(嗯...使用的字符集ROM吗?)我倒是更喜欢inc $d020jsr flash;)hitshimselfwithalargetrout It's奇妙!
泰特斯

1
@Titus将节省2个字节,是的。至于加载地址,它是有效.prg文件的一部分,在我的meta问题中,我认为我必须包括它...如果代码与位置无关,则可能会忽略它。
菲利克斯·帕尔姆

14

击+ 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 '17

11

CP-1610组件,6764 62 DECLE = 78字节

该代码旨在在Intellivision上运行。它使用的是其硬件精灵之一,称为MOB(用于移动对象)。

CP-1610操作码使用10位值(称为“ DECLE”)进行编码。这个程序长62 DECLE,开始于$ 4800,结束于$ 483D。

十六进制转储+源

                            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,这很有创意!
Metoniem

为我工作过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

在硬件上看起来更流畅。


您确定这是70个字节吗?看起来比那还少。
17Me21年

@ 12Me21您数多少字节?如果将其保存在计算器上,我将得到80个字节;对于与我的计数相符的空程序,它将得到10个字节。
哈罗德

哦,我想我当时算错了。
17Me21年

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

Java,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 Sequences来重新定位光标,该光标是在85 x 25终端显示周围反弹的对象。保存在名为的文件中A.java

不打高尔夫球

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'2

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

取消高尔夫:

(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

那是一个好人!
rnso

“球拍”是从“方案”编程语言派生而来的:在Scheme(一个不可靠的计划)之后,有Racket(一个骗局或骗局)!
rnso

@mso更好!
ckjbgames

3

果冻,37个字节

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

此答案的帮助下,可以正确实现循环和转义字符。目前,它在80x24屏幕上反弹,但是可以在代码中轻松地对其进行修改。

每个方向上的坐标可以表示为两个列表的元素,[0, 1,..., 24, 23,..., 1]并且[0, 1,..., 80, 79,..., 1]我们将它们称为YX,它们是无限重复的。可以使用模块化索引来模拟这种无限重复- 在Jelly中使用。示例:在第3 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.

可以用2个三角波来模拟球的位置,而我在SmileBASIC中找到它们的最短方法是arcsine(sine(x))。(由于SB使用MOD而不是,因此使用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≥GG≥⎕SD⎕SD小号 creen d 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右上角开始,在40x25的网格上弹跳资本;
打印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);。模在0和N处为假,并反转方向。可悲的是,我们必须将$ d和$ e初始化为-1,但仍然可以节省一些钱。$x%79<=>.5也适用于相同的字节。
克里斯多夫(Christoph)

1
嘿@Christoph欢迎回来。奇怪:当我复制您的内容时,它只有116个字节而不是110个字节。但是,这启发了我,使内容缩短了很多。
泰特斯

我们绝对是一个很好的团队;)复制上奇怪的事情,我不知道为什么。
克里斯多夫(Christoph)

2

Simons的BASIC(C64),66 65字节

感谢@ShaunBebbers,节省了一个字节。

我在这里只需要一行,因为Simons的Basic具有取模功能。
再次,这需要一个物理C64和一个Simons的BASIC模块
(或任何其他具有mod功能的BASIC扩展)。

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键入它。

字节数

当保存到磁盘,它需要65个字节,这是因为命令被标记化:
fortopokeabsnextgoto是一个字节的每个; mod占用两个字节。
这使得59个字节的代码加上4个字节的指针和2个字节的行号。

供参考,请参阅映射C64并搜索$800(BASIC程序文本)。
(您可以在找到视频屏幕存储区$400。)

分解

程序I从0 循环到623(LCM为48和78减1)。在循环

  • 屏幕被清除
  • I 分别映射到39..0..38 24..0..23
  • 然后将斑点(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
准将命令分隔符是:不是;
肖恩·贝伯斯

1
另外,如果您从第0行开始,则可以简单地goto在两线版本中使用,因为在BASIC 2上goto没有数字假设goto 0
Shaun Bebbers

如果要在C64 BASIC列表中获取更多命令,请将其输入到128模式的C128中,将其保存到磁盘上,然后再加载回C64模式,C128默认情况下限制为160个字符,因此可以通过使用Commodore关键字的缩写。
Shaun Bebbers

@ShaunBebbers很高兴认识。已经好久了。我也想在机器代码中实现这一点...试图回顾一下内核例程;不知道何时必须备份哪些寄存器;完整的内核清单在线 ; 我就是不能花时间进一步挖掘。您想完成这个吗?
泰特斯

我打算制作一个MC版本,尽管我认为即使对我来说,将其提交给我自己的挑战也将过于放纵。最快的方法是将字节直接写入到从屏幕$0400$07e7; 或使用精灵。将Kernal与$ffd2(输出累加器)配合使用将可以工作,因为您可以轻松地在光标上设置X和Y pos(我不记得有此要求),但是您可能必须避免最后一个字符的位置,以防它强制换行。
Shaun Bebbers

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)

感谢R. Kap建议使用x%79 <1而不是x <1或x> 79,并建议将y保持不变。


您可以通过更换节省几个字节x<1or x>78x%79<0y<1or y>22y%23<1
R. Kap

1

Rebol / View,284266字节

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

取消高尔夫:

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目录中。因此,我搜索了,就是我所发现的。它是一个使用SDL for Linux的TurboC图形实现。也可以使用OpenGL。在Windows中,我猜它已经安装了,不确定MacOS。
  • void initgraph(int *graphdriver, int *graphmode, char *pathtodriver);初始化系统并将其置于图形模式,在这种情况下,将自动检测图形驱动程序。请参阅此链接以获取更多详细信息。
  • x并且y是决定球的位置坐标。
  • ab是标志,ax值低于60 b时设置为零,y而低于60 时设置为零。
  • xy超过窗口的边界值时,将切换标志,并相应地调整坐标。
  • 我放了一个,usleep这样我的CPU就不会感到紧张。
  • 通常应该使用一个closegraph()呼叫,以关闭窗口。但是这里不见了。

必须使用链接器标志进行编译 -lgraph

它在实际硬件上运行更流畅。:)

弹跳红球


运行该程序是否需要导入语句?
Kritixi Lithos'2

@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向量保留在剪贴板中,方向以1×2向量保留在剪贴板中I,其中包含条目1-1

每次迭代都会清除屏幕,定义空间矩阵,并写入 O在相关位置并显示它。然后,位置和方向需要更新。

位置1基于-,因此屏幕的边缘为1和最大屏幕尺寸。因此,如果位置模屏幕大小在第一个或第二个分量中给出01在其中给出,或者这意味着我们分别达到了垂直或水平边缘,则方向矢量的那个分量将被取反。之后,将新方向添加到当前位置以获得新位置。


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-您能否提供一个字节数。我认为这对包括16K机器在内的任何Speccy都适用吗?
Shaun Bebbers

嗨,这是201个字节,您可以省略前4行,但之后只会得到一个跳动的“ a”字符,但可以节省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

LuaLÖVE2D),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 x600。可以在配置文件中更改它,但是我没有看到任何大小限制,因此我将其保留原样。

  • love.draw()是LÖVE的绘图功能,它有一个预定名称。可用于将替代LÖVE功能love.update(dt)love.run()-第一个是更长的时间,以字节为单位,而后者是更短的,是的,但没有一个内置的无限循环。因此,这draw()似乎是我们最好的选择。

  • 上面的版本用于love.graphics.points绘制球。虽然较短,但我不确定是否允许。这是运行方式的GIF:

动画截图-点

如您所见(或可能看不到),屏幕上移动了一个像素。虽然可以节省字节,但这并不是最令人满意的结果。

因此,我提出了另一种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-打印文字-和a 0作为球,使它更加可见和吸引人。

动画截图-零


1

CHIP-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您可以在符号列表中保存一些字节;您还可以在改进解决方案后编辑先前的答案,而不必重新回答同一问题
Shaun Bebbers
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.