Trực quan hóa mắt


42

Bạn có thể hoặc không thể nhớ Xeyes, một chương trình demo đi kèm (và, theo như tôi biết, vẫn đi kèm) hệ thống cửa sổ X. Mục đích của nó là vẽ một đôi mắt theo con trỏ chuột của bạn:

Xeyes

Thách thức của bạn là tái tạo Xeyes với nghệ thuật ASCII. Viết chương trình hoặc chức năng vẽ hai mắt nghệ thuật ASCII (được chỉ định bên dưới) bất cứ nơi nào người dùng nhấp và sau đó di chuyển con ngươi của chúng để chỉ theo hướng của con trỏ.

GIF mắt thiết bị đầu cuối

GIF ở trên là bản ghi thực hiện Ruby không chơi gôn này , có thể chạy với bất kỳ phiên bản gần đây nào của Ruby. Bạn cũng có thể thấy nó hữu ích khi tham chiếu cho các chuỗi điều khiển Xterm.

Thông số kỹ thuật

Đây là , vì vậy giải pháp có ít byte nhất sẽ thắng.

Đây là một thách thức, vì vậy chương trình của bạn phải vẽ bằng ký tự ASCII-cụ thể, các nhân vật -, ., |, ', 0, không gian, và xuống dòng. 1 2

Đây là một thách thức , vì vậy chương trình của bạn phải chấp nhận đầu vào và rút ra đầu ra của nó trong thời gian thực. 3

Trước khi chương trình của bạn bắt đầu chấp nhận đầu vào, nó sẽ khởi tạo một khung trống có ít nhất 20 hàng và 20 cột. Nó không nên vẽ bất cứ điều gì cho đến khi người dùng nhấp vào khung vẽ.

Bất cứ khi nào người dùng nhấp vào 4 trên khung vẽ, chương trình sẽ xóa bất kỳ đầu ra nào trước đó và sau đó vẽ các mắt ASCII này trên khung vẽ, tập trung vào ký tự gần vị trí của con trỏ chuột. 5 6 (Dưới đây, đại diện cho con trỏ chuột và không nên được vẽ.)

.---. .---.
|   | |   |
|  0|✧|0  |
|   | |   |
'---' '---'

Lưu ý cách học sinh "chỉ" về phía con trỏ.

Bất cứ khi nào con trỏ chuột di chuyển trên khung vẽ, chương trình sẽ vẽ lại các con ngươi để chúng tiếp tục hướng về phía con trỏ, 7 , vd:




.---. .---.
|  0| |  0|
|   | |   |
|   | |   |
'---' '---'

Học sinh chỉ

Giả sử chúng ta liệt kê vị trí của chín ký tự bên trong của mỗi mắt như vậy:

.---.
|678|
|591|
|432|
'---'

Học sinh sẽ được rút ra tại một trong những địa điểm 1- 9. Để quyết định cái nào, giả vờ các ký tự là hình vuông và khung vẽ là lưới Cartesian, với tâm của 9ký tự tại (0, 0), tâm của 1(1, 0), v.v. Khi chương trình nhận được đầu vào, một cú nhấp hoặc chuyển động, nó sẽ ánh xạ vị trí đầu vào tới tọa độ lưới gần nhất. Nếu 𝑀 là (0, 0), học sinh nên được vẽ tại (0, 0), tức là vị trí của 9ở trên. Nếu không, nó nên được vẽ như mô tả dưới đây.

Hãy tưởng tượng một mặt phẳng của Cartesian được đặt chồng lên lưới và chia thành các octant được đánh số 1 - 8 :

Nếu 𝑀 dối trá trong chòm sao bát nhân 1 thì học sinh nên được rút ra tại vị trí của 1trên, tức là tại (1, 0). Nếu 𝑀 nằm trong octant 2 thì nên rút ra tại ngay bây giờ 2. Để minh họa, hình ảnh dưới đây cho thấy một phần của lưới được mã hóa màu theo vị trí con ngươi sẽ được vẽ khi con trỏ chuột ở một vị trí cụ thể. Ví dụ, khi con trỏ ở bất kỳ tọa độ màu xanh lá cây nào (hãy nhớ rằng tọa độ lưới nằm ở tâm của hình vuông, không phải góc của chúng), nên vẽ đồng tử tại 4.

Đồng tử của hai mắt di chuyển độc lập, do đó, đối với mỗi mắt lặp lại quá trình với so với tâm của mắt đó.

Ghi chú

  1. Đây không phải là một thách thức . Đầu ra phải là một lưới các ký tự. Tất nhiên, bạn có thể sử dụng các thói quen đồ họa để vẽ một lưới các ký tự.

  2. Khoảng trắng có thể được vẽ (hoặc, đúng hơn, không được vẽ) tuy nhiên là thuận tiện. Một điểm trống trong lưới trông giống như một ký tự khoảng trắng và sẽ được coi là tương đương.

  3. "Thời gian thực" được định nghĩa ở đây là ít hơn 200ms giữa đầu vào và đầu ra tương ứng được rút ra.

  4. Theo quyết định của bạn, nút chuột nào được quan sát cho đầu vào và liệu một lần nhấn hoặc nhả có cấu thành "nhấp chuột" hay không.

  5. Canvas phải được xóa, hoặc tương đương trực quan phải đạt được. Ví dụ, với một giải pháp dựa trên thiết bị đầu cuối, việc in một khung vẽ mới bên dưới khung vẽ trước đó không được coi là tương đương.

  6. Khi người dùng nhấp vào gần mép của khung vẽ sao cho một số ký tự mắt sẽ được vẽ bên ngoài cạnh của nó, hành vi không được xác định. Tuy nhiên, chương trình phải tiếp tục chạy bình thường khi có các lần nhấp tiếp theo.

  7. Khi con trỏ chuột rời khỏi "khung vẽ", hành vi không được xác định, nhưng chương trình phải tiếp tục chạy bình thường khi con trỏ vào lại khung vẽ.

  8. Một con trỏ văn bản có thể xuất hiện trên khung vẽ, miễn là nó không làm mờ đầu ra.

Sơ hở tiêu chuẩn bị cấm.


2
@ Οurous Vì bao nhiêu phút là "một vài" trong trường hợp đó sẽ phụ thuộc vào dung lượng của bộ nhớ và điều đó có thể dẫn chúng ta đến "giải pháp này giả định môi trường có 512GB RAM", tôi sẽ nói rằng nó phải có khả năng chạy vô thời hạn.
Jordan

1
@TaylorScott Không. Xem ghi chú số 6 (trừ khi tôi hiểu nhầm câu hỏi của bạn).
Jordan

1
@ Urous Có, và không. Nếu môi trường đích của bạn thường là một trong đó phông chữ mặc định là không gian đơn (giả sử, trình giả lập thiết bị đầu cuối hoặc trình soạn thảo mã), thì điều đó tốt. Nếu sử dụng phông chữ đơn cách trong môi trường đó thường có cấu hình bổ sung (như trong giải pháp JS dựa trên trình duyệt), cấu hình đó phải là một phần của số byte của bạn (ví dụ <pre>hoặc font-family:monospace).
Jordan

9
+1 cho tiêu đề tuyệt vời (hoặc tiêu đề xấu, tùy thuộc vào cách bạn lấy nó)
FantaC

1
@ Οurous Nope, miễn là nó không chấm dứt bất ngờ.
Jordan

Câu trả lời:


12

HTML + CSS + JavaScript (ES6), 93 + 19 + 278 276 = 388 byte

w=7.8125
h=15
with(Math)r=round,
(onclick=e=>F.style=`margin:-3.5em -6.5ch;left:${x=r(e.x/w)*w}px;top:${y=r(e.y/h)*h}px`)({y:-40}),onmousemove=e=>(s=($,o)=>$.style=`left:${a=atan2(Y=r((e.y-y)/h),X=r((e.x-x)/w+o)),X|Y?w*r(cos(a)):0}px;top:${X|Y?h*r(sin(a)):0}px`)(L,3)&&s(R,-3)
*{position:relative
<pre id=F>.---. .---.
|   | |   |
| <a id=L>0</a> | | <a id=R>0</a> |
|   | |   |
'---' '---'


Cả hai X||Ycó thể được đánh gôn X|Yđể tiết kiệm 2 byte.
Kevin Cruijssen

Không hoạt động tốt khi bạn nhấp vào gần dưới cùng của container và phải cuộn xuống. i.stack.imgur.com/s44KU.png Không chắc chắn nếu cụ thể cho trình bao bọc đoạn trích, nhưng đáng được đề cập.
Draco18

2
@ Οurous Đó là từ khá mơ hồ: "tập trung tại vị trí của con trỏ chuột." "Vị trí" có nghĩa là "ô lưới" hay có thể có nghĩa là "pixel"? Tôi đồng ý rằng ý định có lẽ là trước đây, nhưng từ ngữ dường như cho phép cái sau.
DLosc

@KevinCruijssen Thật không may, điều đó không hiệu quả - |cuối cùng được ưu tiên hơn biểu thức ternary.
darrylyeo

@darrylyeo Không phải không? : S Bảng ưu tiên toán tử JavaScript này hiển thị |||ở cùng một mức độ và cả hai mức trên ?:.. Cả hai X||Y?w*r(cos(a)):0X||Y?h*r(sin(a)):0hiện đang ở dạng boolean_condition?A:B. Vì vậy, khi bạn thay đổi X||Yđể X|Ynó sẽ làm một chút khôn ngoan OR và sau đó giải thích như một điều kiện boolean một lần nữa. ( (X||Y)?A:Bso với (X|Y)?A:B, không X|(Y?A:B)). Ngoài ra, tôi không thấy bất kỳ sự khác biệt nào khi tôi sử dụng "Sao chép đoạn trích để trả lời" và thay đổi ||thành |. Mọi thứ vẫn hoạt động chính xác như xa như tôi có thể nói ..
Kevin Cruijssen

12

VBA Excel, 630 byte

Chương trình con bảng tính được khai báo chạy trên nhấp chuột mà không cần nhập liệu và tạo ra một cặp mắt theo con trỏ. Điều này phụ thuộc vào chức năng của trình trợ giúp và khai báo kiểu bao gồm, phải được đặt trong một mô-đun bình thường.

Phiên bản này được hiệu chỉnh để chạy ở mức thu phóng mặc định 100%. Phá vỡ nếu bạn cố gắng cuộn.

Lưu ý: VBA tự động hoàn thành chuỗi unterminated tại dòng mới, do đó, trong đoạn mã dưới đây, có ba trường hợp trong đó một thiết bị đầu cuối "chỉ được đưa vào cho mục đích làm nổi bật - những điều này không đóng góp cho bytecount

Sub Worksheet_SelectionChange(ByVal t As Range)
With Cells
.Clear
.Font.Name="Courier"'<--- `"` included only for highlighting
.ColumnWidth=1.3
.RowHeight=15
End With
[A1]=" "'<--------------- `"` included only for highlighting
Dim l As p,p As p
GetCursorPos l
While[A1]=" "'<---------- `"` included only for highlighting
DoEvents
GetCursorPos p
For i=0To 1
x=l.x+IIf(i,-56,56)
n=Evaluate("=-Int(-8/Pi()*ATan2("& x-p.x &","& l.y-p.y+0.1 &"))")
n=Asc(-Int(-IIf(Abs(p.x-x)<7And Abs(p.y-l.y)<10,9,IIf(n<-6,8,n)-1)/2)+4)
j=1
For Each c In t.Offset(-2,IIf(i,-5,1)).Resize(5,5)
d=Mid(".---.|567||498||321|'---'",j,1)
c.Value=IIf(d Like"[0-9]",IIf(Asc(d)=n,0," "),"'"&d)
j=j+1
Next c,i
Wend
End Sub

Hàm trợ giúp và khai báo kiểu

Declare Sub GetCursorPos Lib"user32"(l As p)
Type p
x As Long
y As Long
End Type

Ungolfed và bình luận

Phiên bản này được hiệu chỉnh để được chạy ở mức thu phóng 400%.

''  must be placed in a worksheet code module

''  define this module to run whenever the user either clicks
''  or moves the selection with the arrow keys
Private Sub Worksheet_SelectionChange(ByVal T As Range)

    ''  Declare vars
    Dim refPos  As POSITION, _
        curPos  As POSITION, _
        c       As Range, _
        d       As String, _
        i       As Integer, _
        j       As Integer, _
        n       As Integer, _
        x       As Integer

    ''  Explicitly state that this works only on the
    ''  Worksheet for which this code has been defined
    With Application.ActiveSheet

        ''  Clear eyes and escape var
        Call .Cells.ClearContents

        ''  Define escape var
        Let .[A1] = " "

        ''  Define reference position
        Call GetCursorPos(refPos)

        ''  While not escaped
        Do While [A1] = " "

            ''  Prevent Excel from appearing to freeze
            Call VBA.DoEvents

            ''  Check where the cursor is
            Call GetCursorPos(curPos)

            ''  Iterate over the eyes' indexes
            For i = 0 To 1 Step 1

                ''  Define the reference center of the eye, left first
                Let x = refPos.x + IIf(i, -168, 168)

                '' figure out which of the directions to point the eye and assign that value to `n`
                Let n = Evaluate("=-Int(-8/Pi()*ATan2(" & x - curPos.x & "," & refPos.y - curPos.y + 0.1 & "))")
                Let n = Asc(-Int(-IIf(Abs(curPos.x - x) < 28 And Abs(curPos.y - refPos.y) < 40, 9, IIf(n < -6, 8, n) - 1) / 2) + 4)

                ''  define character index
                Let j = 1

                ''  Iterate over the range in which the eye is to be drawn
                For Each c In T.Offset(-2, IIf(i, -5, 1)).Resize(5, 5)

                    ''  get correct char from the reference data
                    Let d = Mid(".---.|567||498||321|'---'", j, 1)

                    ''  check if the char is a number, if so only keep it if it matches `n`
                    Let c.Value = IIf(d Like "[0-9]", IIf(Asc(d) = n, 0, " "), "'" & d)

                    '' iterate j
                    j = j + 1
            Next c, i
        Loop
    End With
End Sub

Hàm trợ giúp và khai báo kiểu

''  Declare the 64-Bit Window API function
Declare PtrSafe Function GetCursorPos Lib "user32" (ByRef posObj As POSITION) As LongLong

''  Define the POSITION type; 0,0 is top left of screen
Type POSITION
x As Long
y As Long
End Type

''  Pre-Operations for optimization
Sub Initialize()
    With Cells

        ''  Define the font as being mono-spaced
        .Font.Name = "Lucida Console"

        ''  Define the size of the cells to be tightly bound around a single char
        .ColumnWidth = 1.5
        .RowHeight = 15
    End With
End Sub

Đầu ra

Ảnh động

Di chuyển_Eyes

Hình ảnh độ phân giải cao hơn

Tĩnh_Eyes


Điều này không phù hợp với đặc điểm kỹ thuật theo một số cách. 1. Lưới của các nhân vật có nghĩa là các ký tự đơn có vị trí riêng biệt. Khi con trỏ chuột được bật, giả sử, 'ký tự ngoài cùng bên phải , đầu ra sẽ khác với khi nó ở 'ký tự ngoài cùng bên trái . 2. Vị trí của mắt không cố định. Một lần nhấp chuột sẽ khiến chúng di chuyển đến vị trí được nhấp. Tôi linh hoạt về phương thức nhập liệu (tôi chấp nhận, giả sử, một con trỏ chuột ảo được điều khiển bởi các phím mũi tên), nhưng có hai sự kiện đầu vào riêng biệt với hành vi khác biệt: di chuyển chuột và nhấp chuột.
Jordan

@Jordan Tôi không chắc ý của bạn về điểm 1, bạn có thể giải thích rõ hơn không? Đối với điểm 2, mắt không tĩnh và nhấp vào bất kỳ ô nào trên trang tính đặt chương trình con sẽ kích hoạt Worksheet_SelectionChangesự kiện và vượt qua phạm vi cuộc gọi ( Targethoặc Ttrong trường hợp này) - vẽ lại mắt và *trong cuộc gọi di động
Taylor Scott

1
@Jordan - Tôi tin rằng tôi đã giải quyết bất kỳ và tất cả các mối quan tâm của bạn, mặc dù khi làm như vậy, tôi đã phải giới hạn giải pháp của mình với 64-bit Excel và tôi đang làm việc trên một phiên bản không được nhận xét và nhận xét tại thời điểm này
Taylor Scott

1
@Jordan Đó là vì các khai báo API của windows cho 32 và 64 nhưng VBA khác nhau, như là các đặc trưng của phép nối và lũy thừa, trong đó 32 bit hầu như luôn luôn ngắn hơn - và hiện tại tôi không có quyền truy cập vào phiên bản Office 32 bit: P
Taylor Scott

3
Có thể thay đổi hai ảnh chụp màn hình thành một màn hình thành gif ?
Kevin Cruijssen

7

QBasic ( QB64 ), 361 305 byte

DO
WHILE _MOUSEINPUT
x=CINT(_MOUSEX)
y=CINT(_MOUSEY)
IF _MOUSEBUTTON(1)THEN l=x-3:k=y
IF(2<l)*(73>l)*(2<k)*(22>k)THEN CLS:FOR i=0TO 1:h=l+6*i:LOCATE k-2,h-2:?".---.":FOR j=1TO 3:LOCATE,h-2:?"|   |":NEXT:LOCATE,h-2:?"'---'":d=x-h:e=y-k:m=ABS(e/d):LOCATE k-SGN(e)*(m>=.5),h-SGN(d)*(m<=2):?"0":NEXT
WEND
LOOP

Nhấp chuột trái đặt mắt. Nếu vị trí của mắt sẽ dẫn đến một phần của mắt nằm ngoài giới hạn, chương trình sẽ "đóng băng" cho đến khi vị trí hợp lệ được thực hiện.

Phần khó khăn chính là đặt học sinh. Hầu hết thời gian, tọa độ của đồng tử chỉ là tâm của mắt cộng (dấu (Δx), dấu (Δy)), ngoại trừ trong các quãng tám 1 và 5, tọa độ y bằng tâm y và trong các quãng tám 3 và 7, tọa độ x bằng tâm x. Ranh giới có thể được tính bằng cách sử dụng độ dốc mcủa đường thẳng từ tâm mắt đến tọa độ chuột. Thuận tiện, chia cho số 0 khi tính độ dốc cho điểm vô cực (+/-) thay vì sai số.

Mắt trực quan trong QB64

Bị đánh cắp

' Loop forever
DO
    ' Do stuff if there is new mouse data (movement or click)
    IF _MOUSEINPUT THEN
        ' Store the mouse coords rounded to the nearest integer
        mouse_x = CINT(_MOUSEX)
        mouse_y = CINT(_MOUSEY)
        ' If left mouse button was clicked, change location of eyes
        IF _MOUSEBUTTON(1) THEN
            ' Store center coordinates of left eye
            left_center_x = mouse_x - 3
            center_y = mouse_y
        END IF
        ' If eye location is in bounds, print the eyes and pupils
        x_in_bounds = left_center_x > 2 AND left_center_x < 73
        y_in_bounds = center_y > 2 AND center_y < 22
        IF x_in_bounds AND y_in_bounds THEN
            CLS
            FOR eye = 1 TO 2
                ' eye = 1 for left eye, eye = 2 for right eye
                IF eye = 1 THEN center_x = left_center_x
                IF eye = 2 THEN center_x = left_center_x + 6
                ' Print eye borders
                LOCATE center_y - 2, center_x - 2
                PRINT ".---."
                FOR row = 1 TO 3
                    LOCATE , center_x - 2
                    PRINT "|   |"
                NEXT row
                LOCATE , center_x - 2
                PRINT "'---'"
                ' Calculate coordinates of pupil
                xdiff = mouse_x - center_x
                ydiff = mouse_y - center_y
                slope = ydiff / xdiff
                ' For most cases, adding the sign of the diff to the center
                ' coordinate is sufficient
                pupil_x = center_x + SGN(xdiff)
                pupil_y = center_y + SGN(ydiff)
                ' But in octants 3 and 7, the x-coordinate is centered
                IF ABS(slope) > 2 THEN pupil_x = center_x
                ' And in octants 1 and 5, the y-coordinate is centered
                IF ABS(slope) < 0.5 THEN pupil_y = center_y
                LOCATE pupil_y, pupil_x
                PRINT "0"
            NEXT eye
        END IF   ' in bounds
    END IF   ' mouse data
LOOP   ' forever

Đã một hoặc hai thập kỷ kể từ khi tôi sử dụng QB, nhưng bạn không thể sử dụng ?0thay vì ?"0"? Điều này cho thấy bạn có thể sử dụng một biểu thức số cũng như chuỗi.
Joey

@Joey Hmm. In nó dưới dạng số cũng in một khoảng trắng trước và sau nó ... nhưng khi nghĩ về nó, tôi cá là tôi có thể in đồng tử trước và sau đó sẽ không thành vấn đề. Ngoại trừ sau đó tôi phải in riêng các viền trái và phải thay vì "| |". Vì vậy, nó có thể sẽ không tiết kiệm bất cứ điều gì. "0"chỉ dài hơn 2 byte.
DLosc

7

Mã máy 6502 ( chuột C64 + 1351 ), 630 byte

00 C0 20 44 E5 A9 FF 85 5E A2 3F A9 00 8D 10 D0 8D 1B D0 9D C0 02 CA 10 FA A0
0A A2 1E B9 5A C2 9D C0 02 CA CA CA 88 10 F4 A9 0B 8D F8 07 A9 18 8D 00 D0 A9
32 8D 01 D0 A9 0D 8D 27 D0 A9 01 8D 15 D0 78 A9 60 8D 14 03 A9 C1 8D 15 03 58
D0 FE 84 FD 85 FE A8 38 E5 FD 29 7F C9 40 B0 04 4A F0 0A 60 09 C0 C9 FF F0 03
38 6A 60 A9 00 60 20 44 E5 A5 69 38 E9 05 B0 02 A9 00 C9 1E 90 02 A9 1D 85 FD
18 69 02 85 5C 69 06 85 5D A5 6A 38 E9 02 B0 02 A9 00 C9 15 90 02 A9 14 85 FE
18 69 02 85 5E A9 65 8D BB C0 A9 C2 8D BC C0 A9 04 85 02 A6 FE 20 F0 E9 A9 02
85 5F A4 FD A2 00 BD FF FF 91 D1 C8 E8 E0 05 D0 F5 C8 C6 5F D0 EE E6 FE A9 6A
8D BB C0 A9 C2 8D BC C0 C6 02 30 0E D0 D1 A9 6F 8D BB C0 A9 C2 8D BC C0 D0 C5
60 C5 69 90 0A F0 5D E5 69 85 5F A9 C6 D0 09 49 FF 38 65 69 85 5F A9 E6 8D 1C
C1 8D 23 C1 8D 3E C1 A5 6A C5 5E 90 21 F0 12 E5 5E C5 5F 90 12 4A C5 5F B0 02
C6 FD A6 5E E8 D0 33 C6 FD A6 5E D0 2D 0A C5 5F B0 EE 90 F3 49 FF 38 65 5E C5
5F 90 0C 4A C5 5F B0 02 C6 FD A6 5E CA D0 11 0A C5 5F B0 F4 90 D7 A5 6A C5 5E
90 EE F0 D1 B0 C8 20 F0 E9 A9 30 A4 FD 91 D1 60 AD 19 D4 A4 FB 20 4E C0 84 FB
85 5F 18 6D 00 D0 8D 00 D0 6A 45 5F 10 08 A9 01 4D 10 D0 8D 10 D0 AD 10 D0 4A
AD 00 D0 B0 08 C9 18 B0 16 A9 18 D0 0F C9 58 90 0E 24 5F 10 05 CE 10 D0 B0 EF
A9 57 8D 00 D0 AD 1A D4 A4 FC 20 4E C0 84 FC 49 FF 85 5F 38 6D 01 D0 8D 01 D0
6A 45 5F 10 06 24 5F 10 11 30 07 AD 01 D0 C9 32 B0 04 A9 32 D0 06 C9 FA 90 05
A9 F9 8D 01 D0 A5 69 85 6B A5 6A 85 6C AD 10 D0 4A AD 00 D0 6A 38 E9 0C 4A 4A
85 69 AD 01 D0 38 E9 32 4A 4A 4A 85 6A AD 01 DC 29 10 C5 6D F0 0B 85 6D 29 10
D0 05 20 6C C0 30 10 A5 5E 30 46 A5 69 C5 6B D0 06 A5 6A C5 6C F0 3A A6 5E CA
86 5F A9 03 85 02 A6 5F 20 F0 E9 A9 20 A2 03 A4 5C 88 91 D1 C8 CA D0 FA A2 03
A4 5D 88 91 D1 C8 CA D0 FA E6 5F C6 02 D0 DD A5 5C 85 FD 20 E9 C0 A5 5D 85 FD
20 E9 C0 4C 31 EA 80 C0 E0 F0 F8 FC F0 D8 18 0C 0C 2E 2D 2D 2D 2E 5D 20 20 20
5D 27 2D 2D 2D 27

Trong hành động:

bản giới thiệu

Không có bản demo trực tuyến , xin lỗi, vì có trình giả lập AFAIK no js C64 hỗ trợ chuột. Nếu bạn muốn tự mình thử, hãy lấy VICE , tải xuống tệp thực thi nhị phân và khởi động nó trong trình giả lập C64:

x64sc -autoload xeyes.prg -controlport1device 3 -keybuf 'sys49152\n'

Để lấy / gỡ lỗi đầu vào chuột trong trình giả lập đang chạy, hãy sử dụng ctrl+mtrên Unix / Linux và ctrl+qtrên các cửa sổ.


Vâng, đây phải được thực hiện;) Sau khi tất cả, có một Commodore chuột ban đầu cho C64, nhưng tất nhiên, hệ điều hành được xây dựng trong không hỗ trợ nó, vì vậy lần đầu tiên tôi cần một trình điều khiển chuột, mà đã mất 230 byte ( bao gồm một sprite phần cứng hình con trỏ chuột và mã kiểm tra giới hạn cho khu vực màn hình, nhưng không dịch các tọa độ con trỏ sang tọa độ màn hình văn bản).

  • Để đảm bảo an toàn cho một số byte, tôi quyết định giữ cho IRQ của HĐH hoạt động và sử dụng một vài thói quen Kernal nếu có thể (xóa màn hình và lấy con trỏ cơ sở cho một hàng màn hình văn bản).
  • Mã này cũng đặt tất cả các biến trong zeropage, giúp tiết kiệm thêm một số byte, nhưng phá hủy các giá trị dấu phẩy động được BASIC sử dụng. Vì chương trình không bao giờ thoát ra, nên điều này không thành vấn đề.
  • Bí quyết thứ ba để giảm kích thước là tự sửa đổi: Chỉ có mã để kiểm tra đặt con ngươi ở bên trái mắt. Mã tương tự được sử dụng lại sau khi vá một số hướng dẫn giảm dần thành hướng dẫn tăng cho phía bên phải.

Nếu bạn quan tâm, bạn có thể đọc mã dưới dạng nguồn lắp ráp tại đây :)


Tôi dường như là người duy nhất cố gắng cạnh tranh ở đây theo thời gian với mã C64. Yêu thích thử thách này, bởi vì một con chuột trên C64 là một cái gì đó "kỳ lạ"! Nếu có ai thắc mắc tại sao gần đây tôi ít hoạt động hơn, thì đây là lý do: csdb.dk/release/?id=161435 - cuối cùng đã cố gắng thực hiện một trò chơi đầy đủ tính năng cho C64 :)
Felix Palmen

1
Chỉ để cho vui, tôi đã làm một "phiên bản cao cấp": csdb.dk/release/?id=161762
Felix Palmen

7

Sạch , 1014 904 892 884 840 814 782 772 769 byte

-6 byte nếu mắt không cần phải nhìn vào lưới

Điều này không dễ dàng. UI trong các ngôn ngữ chức năng hiếm khi được.

import StdEnv,StdIO,osfont,ostoolbox
a=toReal
c=1>0
Start w#(d,w)=openId w
#(t,w)=worldGetToolbox w
#(_,f,_)=osSelectfont("Courier",[],9)t
=let$p#(s,p)=accPIO getProcessWindowSize p
    =snd(openWindow NilLS(Window""NilLS[WindowId d,WindowMouse(\_=c)Able(noLS1@),WindowViewSize s,WindowPen[PenFont f]])p);@(MouseUp p _)s={s&ls=p};@(MouseMove p _)s=:{ls={x,y},io}={s&io=setWindowLook d c(c,(\_{newFrame}i#(w,i)=getFontCharWidth f' '(unfill newFrame i)
    =let g v=let m=y-p.y;n=p.x-x-v*w;s=abs(a m/a n);k|abs m<9&&abs n<w=5|s<0.4142=if(n>0)6 4=sign if(s>2.4143)0n+if(m>0)2 8in[".---.":["|"+++{if(k==e)'0'' '\\e<-[j..j+2]}+++"|"\\j<-[1,4,7]]]++["'---'"]in foldr(\e=drawAt{x=(x/w-5)*w,y=(y/9+e-2)*9}([a+++" "+++b\\a<-g -3&b<-g 3]!!e))i[0..4]))io};@_ s=s
in startIO SDI zero$[]w

Đảm bảo rằng bạn đang sử dụng iT Nhiệm vụ sạch, Couriercài đặt phông chữ và StdLibTRƯỚC bất kỳ thư mục con nào ObjectIOtrong đường dẫn tìm kiếm mô-đun.

Biên dịch với (ví dụ, có thể khác nhau): clm -IL StdLib -IL ObjectIO -IL "ObjectIO/OS <YOUR_OS_HERE>" -IL Dynamics -IL Generics -IL Platform -nci <MODULE_NAME_HERE>

Nếu bạn chưa bao giờ chạy Clean trước đó, hãy hy vọng dự án này sẽ mất hơn 5 phút để biên dịch.

Ung dung:

module main
import StdEnv,StdIO,osfont,ostoolbox
height=9
SlopeFor225 :== 0.4142

StartSize :== 8

Universe :== {corner1={x=0,y=0},corner2={x=1,y=1}}

Start :: *World -> *World
Start world = startConsole (openIds 1 world)

startConsole :: ([Id],*World) -> *World
startConsole ([windowID],world)
    # (toolbox,world) = worldGetToolbox world
    # (_,font,toolbox) = osSelectfont ("Consolas",[],height) toolbox
    = startIO SDI {x=0,y=0} (initialise font) [ProcessClose closeProcess] world
where
    initialise font pst
        # (size,pst) = accPIO getProcessWindowSize pst
        # (error,pst) = openWindow undef (window font size) pst
        | error<>NoError = abort "bad window"
        = pst

    window font size
        = Window "Xeyes" NilLS
            [WindowId           windowID
            ,WindowClose        (noLS closeProcess)
            ,WindowMouse        mouseFilter Able (noLS1 track)
            ,WindowViewDomain   Universe//(getViewDomain StartSize)
            ,WindowViewSize     size
            ,WindowPen          [PenFont font]
            ]

    track (MouseDown pos _ _) state=:{ls=point=:{x,y},io}
        # point = pos
        // move to mouse position
        = {state & ls=pos}

    track (MouseMove pos _) state=:{ls=point=:{x,y},io}
        //redraw to point at mouse
        # io = setWindowLook windowID True (True, look) io
        = {state & ls=point,io=io}
    where
        look _ {newFrame} picture
            # picture = unfill newFrame picture
            # (width,picture) = getPenFontCharWidth' 'picture
            = let
                determineSector u
                    # yDist = (y - pos.y)
                    # xDist = (pos.x - u)
                    # slope = abs(toReal yDist / toReal xDist)
                    | (abs yDist) < height && (abs xDist) < width = '9'
                    | slope < SlopeFor225 = if(xDist > 0) '1' '5'
                    | yDist > 0
                        | slope > (2.0+SlopeFor225) = '7'
                        = if(xDist > 0) '8' '6'
                    | slope > (2.0+SlopeFor225) = '3'
                    = if(xDist > 0) '2' '4'
                getEye u=map(map(\e|isDigit e=if(e==determineSector(x+u*width))'0'' '=e))[['.---.'],['|678|'],['|591|'],['|432|'],['\'---\'']]
            in foldr(\i pic=drawAt{x=(x/width-5)*width,y=(y/height+i-2)*height}([toString(a++[' ':b])\\a<-getEye -3&b<-getEye 3]!!i)pic)picture[0..4]

    mouseFilter (MouseDown _ _ _) = True
    mouseFilter (MouseMove _ _) = True
    mouseFilter _ = False

Như bạn có thể thấy từ phiên bản không được chỉnh sửa, hầu hết các mã chỉ là thiết lập sự kết hợp của "phông chữ đơn cách" với "phản hồi cho chuột". Và mặc dù Courierkhông làm cho nó dễ dàng để nói, nó thực sự đang vẽ .s và 's. Trao đổi với một cái gì đó như Consolaslàm cho nó rõ ràng hơn.

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


1
Tôi hoàn toàn không biết Clean, vì vậy có lẽ tôi đang nói điều gì đó kỳ lạ, nhưng liệu có thể đổi (abs m)<9&&(abs n)<w='9'thành (abs m)<9&(abs n)<w='9'? Ngoài ra, tôi khuyên bạn nên thêm một màn hình vào gif thay vì ảnh chụp màn hình.
Kevin Cruijssen

1
@KevinCruijssen Điều đó sẽ không hoạt động vì nhiều lý do, nhưng tôi đã lưu 4 byte thả dấu ngoặc trong cùng một biểu thức, cảm ơn! Tôi cũng đã thêm một gif màn hình!
Οurous

1

Ruby, 335 + 13 = 348 byte

+13 byte cho -rio/consolecờ để kích hoạt IO#getch.

Chứa các ký tự ESC ( 0x1b) theo nghĩa đen , được hiển thị như bên dưới. xxd đổ sau.

Thận trọng: Điều này không làm sạch sau khi thoát. Xem ghi chú dưới xxd dump bên dưới.

include Math
$><<"␛[?1003h"
s=""
(s<<STDIN.getch
($><<"␛[2J"
x,y=$3.ord-32,$4.ord-32
u,v=x,y if$2
u&&[x-u+3,x-u-3].map{|a|b=y-v
e=4*asin(b/sqrt(a**2+b**2))/PI
printf"␛[%d;%dH.---.@|567|@|480|@|321|@'---'".gsub(/(#{(a<0?4-e:b<0?8+e:e).round%8rescue 8})|([0-8])|@/){$1?0:$2?" ":"␛[5D␛[1B"},v-2,x-a-2}
s="")if /M(C|(#))(.)(.)$/=~s)while 1

Bị đánh cắp

Đây là một sân golf khá ngây thơ trong quá trình thực hiện Ruby ban đầu của tôi .

include Math       # Saves a few bytes for asin, sqrt, and PI
$> << "␛[?1003h"   # Print xterm control sequence to start mouse tracking
s = ""             # Variable to hold input-so-far
(
  s << STDIN.getch   # Read a character from STDIN
  (
    $> << "␛[2J"                     # Clear terminal
    x, y = $3.ord - 32, $4.ord - 32  # Get cursor x and y from last match
    u, v = x, y if $2                # Update eye position if last matched control sequence was click ("#")

    u && [x-u+3, x-u-3].map {|a|     # For each eye's x-position
      b = y - v                                       # Eye's y position
      e = 4 * asin(b / sqrt(a**2 + b**2)) / PI        # Convert cursor (x,y) to angle w/ x-axis as 1/8 turns

      printf "␛[%d;%dH.---.@|567|@|480|@|321|@'---'"  # Control code to move text cursor, followed by template for eye
        .gsub(
          /(#{
            (a < 0 ? 4-e : b < 0 ? 8+e : e).round % 8 rescue 8  # Octant number 0-7 or 8 for center
          })|([0-8])|@/
        ){ $1 ? 0 : $2 ? " " : "␛[5D␛[1B" },            # Replace octant number with pupil; other digits with space; and @s with code to move cursor left and down for next line of eye
        v-2, x-a-2                                      # (y, x) position of top left corner of eye
    }
    s = ""                           # Clear input-so-far
  ) if /M(C|(#))(.)(.)$/ =~ s      # ...when input-so-far matches a movement ("C") or click ("#") control sequence
) while 1                        # ...forever

bãi rác xxd

Chương trình này bật theo dõi chuột với trình tự điều khiển xterm \e[?1003hnhưng không tắt khi thoát. Để tắt nó, sử dụng trình tự điều khiển \e[?1003l, ví dụ:

ruby -rio/console visual_eyes.rb; printf '\e[1003l'

Vì chương trình ăn tất cả đầu vào, thật khó để thoát ra. Nếu bạn muốn có thể thoát bằng cách nhấn Ctrl + C, hãy thêm dòng dưới đây (s<<STDIN.getch:

exit 130 if s.end_with?(?\003)

Nếu không có thêm rắc rối:

00000000: 696e 636c 7564 6520 4d61 7468 0a24 3e3c  include Math.$><
00000010: 3c22 1b5b 3f31 3030 3368 220a 733d 2222  <".[?1003h".s=""
00000020: 0a28 733c 3c53 5444 494e 2e67 6574 6368  .(s<<STDIN.getch
00000030: 0a28 243e 3c3c 221b 5b32 4a22 0a78 2c79  .($><<".[2J".x,y
00000040: 3d24 332e 6f72 642d 3332 2c24 342e 6f72  =$3.ord-32,$4.or
00000050: 642d 3332 0a75 2c76 3d78 2c79 2069 6624  d-32.u,v=x,y if$
00000060: 320a 7526 265b 782d 752b 332c 782d 752d  2.u&&[x-u+3,x-u-
00000070: 335d 2e6d 6170 7b7c 617c 623d 792d 760a  3].map{|a|b=y-v.
00000080: 653d 342a 6173 696e 2862 2f73 7172 7428  e=4*asin(b/sqrt(
00000090: 612a 2a32 2b62 2a2a 3229 292f 5049 0a70  a**2+b**2))/PI.p
000000a0: 7269 6e74 6622 1b5b 2564 3b25 6448 2e2d  rintf".[%d;%dH.-
000000b0: 2d2d 2e40 7c35 3637 7c40 7c34 3830 7c40  --.@|567|@|480|@
000000c0: 7c33 3231 7c40 272d 2d2d 2722 2e67 7375  |321|@'---'".gsu
000000d0: 6228 2f28 237b 2861 3c30 3f34 2d65 3a62  b(/(#{(a<0?4-e:b
000000e0: 3c30 3f38 2b65 3a65 292e 726f 756e 6425  <0?8+e:e).round%
000000f0: 3872 6573 6375 6520 387d 297c 285b 302d  8rescue 8})|([0-
00000100: 385d 297c 402f 297b 2431 3f30 3a24 323f  8])|@/){$1?0:$2?
00000110: 2220 223a 221b 5b35 441b 5b31 4222 7d2c  " ":".[5D.[1B"},
00000120: 762d 322c 782d 612d 327d 0a73 3d22 2229  v-2,x-a-2}.s="")
00000130: 6966 202f 4d28 437c 2823 2929 282e 2928  if /M(C|(#))(.)(
00000140: 2e29 242f 3d7e 7329 7768 696c 6520 31    .)$/=~s)while 1
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.