시각적 인 눈을 시각화


42

X 윈도우 시스템과 함께 제공되는 데모 프로그램 인 Xeyes를 기억하거나 기억하지 못할 수도 있습니다. 그 목적은 마우스 커서를 따라 한 쌍의 눈을 그리는 것입니다.

Xeyes

당신의 도전은 ASCII 아트로 Xeyes를 재현하는 것입니다. 사용자가 클릭 할 때마다 두 개의 ASCII 아트 아이 (아래에 지정된)를 그리는 프로그램 또는 함수를 작성하고 커서 방향을 가리 키도록 동공을 이동하십시오.

터미널 눈 GIF

위의 GIF는 이 골퍼가 아닌 Ruby 구현에 대한 기록이며 , 최신 Ruby 버전에서 실행할 수 있습니다. Xterm 제어 시퀀스에 대한 참조로 유용 할 수도 있습니다.

사양

이것은 이므로 가장 적은 바이트를 가진 솔루션이 승리합니다.

이것이입니다 프로그램이-특히 문자 ASCII를 사용하여 그릴 수 있어야하므로, 도전, 문자 -, ., |, ', 0, 공간, 줄 바꿈. 1 2

이는 문제이므로 프로그램에서 입력을 수락하고 출력을 실시간으로 그려야합니다.

프로그램이 입력을 수락하기 전에 최소 20 행과 20 열의 빈 캔버스를 초기화해야합니다. 사용자가 캔버스를 클릭 할 때까지 아무것도 그리면 안됩니다.

사용자 가 캔버스에서 4 를 클릭 할 때마다 프로그램은 이전 출력을 지우고 마우스 커서 위치에서 가장 가까운 문자를 중심으로 이러한 ASCII 눈을 캔버스에 그려야합니다. 5 6 (아래, 마우스 커서를 나타내며 그려서는 안됩니다.)

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

동공이 커서를 어떻게 가리키는 지 확인하십시오.

언제든지 캔버스에 마우스 커서 이동, 그들이 커서를 향해 가리키는 계속되도록 학생들을 다시 그려야 프로그램, 7 예 :

             ✧


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

학생을 가리키는

각 눈의 안쪽 9 자 위치를 다음과 같이 열거했다고 가정합니다.

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

동공은 위치 중 하나에 그려집니다 1- 9. 어느 쪽을 결정하려면 문자가 정사각형이고 척수가 문자의 중심이 9(0, 0), 중심이 1(1, 0) 등인 데카르트 그리드 인 척합니다 . 프로그램이 입력 또는 클릭 또는 이동을 수신하면 입력 위치를 가장 가까운 그리드 좌표 𝑀에 매핑해야합니다. 𝑀가 (0, 0)이면, 동공은 (0, 0), 즉 9위 의 위치에 그려 져야합니다 . 그렇지 않으면 아래에 설명 된대로 그려야합니다.

그리드에 중첩 된 직교 평면을 상상해 18의 숫자로 나눈다 고 상상해보십시오 .

팔분 𝑀 내에 놓이는 경우 1 , 그 동공의 위치로 연신한다 1(1, 0)에서 위, 즉. 만약 𝑀이 2 번 에 있다면, 그다음에 그려 져야합니다 2. 예를 들어, 아래 이미지는 마우스 커서가 특정 위치에있을 때 동공을 그려야하는 위치에 따라 색으로 구분 된 그리드의 일부를 보여줍니다. 예를 들어, 커서가 녹색 좌표 중 하나에있을 때 (그리드 좌표는 모서리가 아닌 정사각형 중심에 있음을 명심하십시오) 동공은에서 그려야 4합니다.

두 눈의 동공은 독립적으로 움직이므로 각 눈마다 눈의 중심을 기준으로 𝑀로 과정을 반복합니다.

노트

  1. 이것은 문제 가 아닙니다 . 출력은 문자 그리드 여야합니다. 물론 그래픽 루틴을 사용하여 문자 그리드를 그릴 수도 있습니다.

  2. 공백이 그려 질 수도 있지만 오히려 그려지지 않을 수도 있습니다. 격자의 빈 자리는 공백 문자와 동일하게 보이며 동등한 것으로 간주됩니다.

  3. 여기서 "실시간"은 입력과 해당 출력 사이의 200ms 미만으로 정의됩니다.

  4. 입력 할 마우스 버튼과 프레스 또는 릴리스가 "클릭"을 구성하는지 여부는 사용자의 판단에 달려 있습니다.

  5. 캔버스를 비우거나 시각적으로 동등한 것을 달성해야합니다. 예를 들어, 터미널 기반 솔루션의 경우 이전 캔버스 아래에 새 캔버스를 인쇄하는 것은 동등한 것으로 간주되지 않습니다.

  6. 사용자가 캔버스의 가장자리 근처를 클릭하여 일부 눈 캐릭터가 가장자리를 넘어서 그려 질 때 동작은 정의되지 않습니다. 그러나 후속 클릭시 프로그램은 계속 정상적으로 실행되어야합니다.

  7. 마우스 커서가 "캔버스"를 벗어나면 동작이 정의되지 않지만 커서가 캔버스에 다시 입력 될 때 프로그램이 계속 정상적으로 실행되어야합니다.

  8. 출력을 가리지 않는 한 텍스트 커서가 캔버스에 나타날 수 있습니다.

표준 허점은 금지되어 있습니다.


2
@ Οurous이 경우 "몇 분"은 시스템의 메모리 용량에 따라 달라 지므로 "이 솔루션은 환경에 512GB의 RAM이 있다고 가정합니다"영역으로 이어질 수 있습니다. 잠재적으로 무한정 실행해야합니다.
Jordan

1
@TaylorScott 아니요. 노트 6을 참조하십시오 (귀하의 질문을 오해하지 않는 한).
Jordan

1
@ 그렇습니다. 아니요. 대상 환경이 일반적으로 기본 글꼴이 모노 스페이스 (예 : 터미널 에뮬레이터 또는 코드 편집기) 인 환경이면 괜찮습니다. 해당 환경에서 고정 폭 글꼴을 사용하는 경우 일반적으로 브라우저 기반 JS 솔루션에서와 같이 추가 구성이 필요한 경우 해당 구성은 바이트 수의 일부 여야합니다 (예 : <pre>또는 font-family:monospace).
Jordan

9
훌륭한 타이틀 (또는 사용 방법에 따라 나쁜 타이틀) +1
FantaC

1
예기치 않게 종료되지 않는 한 @ Οurous Nope.
Jordan

답변:


12

HTML + CSS + 자바 스크립트 (ES6), 93 + 19 + 278 (276) = 388 바이트

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


둘 다 X||Y골프를 쳐서 X|Y2 바이트를 절약 할 수 있습니다 .
Kevin Cruijssen

컨테이너 하단 근처를 클릭하고 아래로 스크롤해야 할 때 제대로 작동하지 않습니다. i.stack.imgur.com/s44KU.png 스 니펫 래퍼에만 해당되는지 확실하지 않지만 언급 할 가치가 있습니다.
Draco18s

2
@ Οurous "마우스 커서의 위치를 ​​중심으로"라는 애매 모호한 표현입니다. "위치"가 "격자 셀"을 의미합니까? "픽셀"을 의미 할 수 있습니까? 나는 그 의도가 아마도 전자 였음에 동의하지만, 그 표현은 확실히 후자를 허용하는 것으로 보인다.
DLosc

@KevinCruijssen 불행히도, 그것은 작동하지 않습니다 – 결국 삼항식 |보다 우선합니다.
darrylyeo

@darrylyeo 아니에요? : S 이 JavaScript 연산자 우선 순위 테이블|||다소 동일한 층, 및 상기 두 ?:.. 양 X||Y?w*r(cos(a)):0X||Y?h*r(sin(a)):0형태로 현재 boolean_condition?A:B. 변경 그래서 X||YX|Y와 비트 단위 OR 할 것입니다 그것을 다시 부울 조건으로 해석한다. ( (X||Y)?A:Bvs (X|Y)?A:B, not X|(Y?A:B)). 또한 "스 니펫 복사"를 사용하여 ||로 변경해도 아무런 차이가 없습니다 |. 내가 말할 수있는 한 모든 것이 여전히 똑같이 작동합니다.
Kevin Cruijssen

12

Excel VBA, 630 바이트

입력을받지 않고 커서를 따라 눈 쌍을 생성하는 마우스 클릭시 실행되는 선언 된 워크 시트 서브 루틴. 이는 포함 된 헬퍼 함수 및 유형 선언에 따라 달라지며, 일반 모듈에 배치해야합니다.

이 버전은 기본 줌 100 %에서 실행되도록 보정되었습니다. 스크롤하려고하면 중단됩니다.

참고 : VBA는 줄 바꿈에서 종료되지 않은 문자열을 자동 완성하므로 아래 코드에는 "강조 목적으로 만 터미널 이 포함 된 세 가지 인스턴스가 있습니다. 이는 바이트 수에 영향을 미치지 않습니다.

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

도우미 함수 및 형식 선언

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

Ungolfed 및 댓글 달기

이 버전은 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

도우미 함수 및 형식 선언

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

산출

GIF

Moving_Eyes

고해상도 이미지

정적 _ 눈


이것은 몇 가지 방식으로 사양과 일치하지 않습니다. 1. "문자 그리드"는 위치가 다른 단일 문자를 의미합니다. 마우스 커서가 켜져 있으면 가장 오른쪽에있는 '문자와 가장 오른쪽에있는 문자가 출력됩니다 '. 2. 눈의 위치는 고정되어 있지 않습니다. 마우스를 클릭하면 클릭 한 위치로 이동해야합니다. 나는 입력 방법에 융통성이 있지만 (화살표 키로 제어되는 가상 마우스 커서를 받아 들일 것입니다), 마우스 동작과 마우스 클릭이라는 뚜렷한 동작을 갖는 두 가지 입력 이벤트가 있습니다.
Jordan

@ 요르단 1 점의 의미가 무엇인지 잘 모르겠습니다. 정교하게 설명해 주시겠습니까? 지점 2에 대해, 눈은 정지하지 않고, 서브 루틴을 트리거한다 배치 된 시트상의 셀 클릭 Worksheet_SelectionChange이벤트 및 (호출 범위를 통과 Target또는 T이 경우에는) - 이는 눈 및 재 묘화 *호출에 세포
테일러 스콧

1
@Jordan - 나는 그렇게, 내가 64 비트 Excel로 내 솔루션을 제한 할 수 있었다 나는이 순간에서 ungolfed 및 주석 버전 일하고 있지만 내가 우려의 모든를 해결했다고 생각
테일러 스콧

1
@Jordan 32 비트와 64 비트에 대한 Windows API 선언이 있지만 연결 및 지수의 특성에 따라 VBA가 다르기 때문에 32 비트는 거의 항상 짧습니다. 현재 32 비트 버전의 Office에 액세스 할 수 없습니다 : P
Taylor Scott

3
두 스크린 샷을 screen-to-gif ?
Kevin Cruijssen

7

QBASIC ( QB64 ) 361 305 바이트

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

마우스 왼쪽 버튼을 클릭하면 눈이 배치됩니다. 눈의 배치로 인해 눈의 일부가 범위를 벗어나는 경우, 올바른 배치가 이루어질 때까지 프로그램이 "동결"됩니다.

가장 까다로운 부분은 학생들을 배치하는 것입니다. 대부분의 경우, 동공의 좌표는 눈의 중심에 더하기 (sign (Δx), sign (Δy))이지만, 1 번과 5 번의 y 좌표는 y 중심과 같고, 8 번은 y 중심입니다. 도 3 및도 7에서 x 좌표는 x 중심과 동일하다. 팔각 경계는 m눈의 중심에서 마우스 좌표까지의 선의 기울기 를 사용하여 계산할 수 있습니다 . 편리하게도, 기울기를 계산할 때 0으로 나누면 오류가 아닌 부동 소수점 무한대 (+/-)가 발생합니다.

QB64의 시각적 눈

언 골프

' 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

QB를 사용한 지 10 년이 지났지 만 ?0대신 사용할 수 없었 ?"0"습니까? 이것은 문자열뿐만 아니라 숫자 식을 사용할 수 있음을 나타냅니다.
Joey

@ 조이 흠. 숫자로 인쇄하면 전후에 공백이 인쇄되지만 ... 생각하면, 학생들을 먼저 인쇄 한 다음 문제가되지 않습니다. 그런 다음을 제외하고 왼쪽 대신 오른쪽 테두리를로 인쇄해야합니다 "| |". 따라서 아무것도 저장하지 않을 것입니다. "0"2 바이트 만 더 깁니다.
DLosc

7

6502 머신 코드 (C64 + 1351 마우스 ), 630 바이트

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

실제로 :

데모

온라인 데모가 없습니다 . 죄송합니다. AFAIK에는 마우스를 지원하는 js C64 에뮬레이터가 없습니다. 직접 시도하려면 VICE를 잡고 바이너리 실행 파일을 다운로드 하여 C64 에뮬레이터에서 시작하십시오.

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

실행중인 에뮬레이터에서 마우스 입력을 가져 오려면 ctrl+mUnix / Linux 및 ctrl+qWindows에서 사용하십시오.


결국,이) 예,이 완료되어야했다 입니다 C64에 대한 원래의 제독 마우스,하지만 내가 먼저 이미 230 바이트를했다 마우스 드라이버를 (필요한 있도록 물론, 내장 운영 시스템은 지원하지 않습니다 마우스 커서 모양의 하드웨어 스프라이트 및 화면 영역에 대한 경계 검사 코드 포함 (포인터 좌표를 텍스트 화면 좌표로 변환하지 않음)

  • 바이트를 안전하게 유지하기 위해 OS의 IRQ를 계속 작동시키고 가능한 한 몇 가지 Kernal 루틴을 사용하기로 결정했습니다 (화면을 지우고 텍스트 화면 행의 기본 포인터를 얻음).
  • 이 코드는 모든 변수를 제로 페이지에 저장하여 바이트를 더 절약하지만 BASIC에서 사용하는 부동 소수점 값을 제거합니다. 프로그램이 종료되지 않으므로 이것은 중요하지 않습니다.
  • 크기를 줄이는 세 번째 요령은 자기 수정입니다. 눈동자를 눈 의 왼쪽 에 놓는 것을 확인하는 코드 만 있습니다 . 오른쪽에 대한 명령어를 증가시키기 위해 일부 감소 명령어를 패치 한 후에 동일한 코드가 재사용됩니다.

관심이 있으시면 여기에서 어셈블리 소스 코드 읽을 수 있습니다. :)


나는 때때로 C64 코드와 경쟁하려고하는 유일한 사람 인 것 같습니다. C64의 마우스는 "이국적인"것이므로이 문제를 좋아 했습니다! 내가 최근에 활동이 적은 이유를 궁금해하는 사람은 다음과 같습니다. csdb.dk/release/?id=161435- 마침내 C64를위한 모든 기능을 갖춘 게임을 시도합니다 :)
Felix Palmen

1
그것의 재미를 위해, 나는 "디럭스 버전"을했다 : csdb.dk/release/?id=161762
Felix Palmen

7

면도 , 1,014 904 892 884 840 814 782 772 769 바이트

눈이 그리드에 스냅 될 필요가없는 경우 -6 바이트

쉽지 않았습니다. 기능적 언어의 UI는 거의 없습니다.

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

iTasks Clean을 사용하고, Courier서체를 설치하고, 모듈 검색 경로에 StdLib하위 폴더가 ObjectIO있기 전에 확인하십시오 .

다음과 같이 컴파일하십시오 (예 : 다를 수 있음). clm -IL StdLib -IL ObjectIO -IL "ObjectIO/OS <YOUR_OS_HERE>" -IL Dynamics -IL Generics -IL Platform -nci <MODULE_NAME_HERE>

전에 Clean을 실행 한 적이 없다면이 프로젝트를 컴파일하는 데 5 분 이상 걸릴 것으로 예상합니다.

언 골프 드 :

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

ungolfed 버전에서 알 수 있듯이 대부분의 코드는 "단일 글꼴"과 "마우스에 응답"의 조합을 설정하는 것입니다. 그리고 Courier말하기가 쉽지 않지만 실제로는 .s와 's를 그립니다. 같은 것으로 바꾸면 Consolas더 명확 해집니다.

여기에 이미지 설명을 입력하십시오


1
나는 Clean을 전혀 모른다. 그래서 아마도 이상한 것을 말하고 있지만로 바꿀 (abs m)<9&&(abs n)<w='9'(abs m)<9&(abs n)<w='9'있습니까? 또한 스크린 샷 대신 screen-to-gif를 추가하는 것이 좋습니다 .
Kevin Cruijssen

1
@KevinCruijssen 여러 가지 이유로 작동하지 않지만 같은 식으로 대괄호를 삭제하여 4 바이트를 절약했습니다. 감사합니다! 나는 또한 화면 GIF를 추가했습니다!
OUurous

1

루비, 335 + 13 = 348 바이트

-rio/console플래그가 사용 가능하게하려면 +13 바이트 IO#getch.

아래와 0x1b같이 리터럴 ESC ( ) 문자를 포함 합니다. xxd 덤프는 다음과 같습니다.

주의 : 종료 후 자체 정리되지 않습니다. 아래 xxd 덤프 아래의 참고 사항을 참조하십시오 .

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

언 골프

이것은 나의 원래 Ruby 구현 의 꽤 순진한 골프 다 .

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

xxd 덤프

이 프로그램은 xterm 제어 순서로 마우스 추적을 설정 \e[?1003h하지만 종료시 끄지 않습니다. 전원을 끄려면 제어 순서를 사용하십시오 ( \e[?1003l예 :

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

프로그램이 모든 입력을 먹기 때문에 종료하기가 어렵습니다. Ctrl + C를 눌러 종료하려면 아래 행을 추가하십시오 (s<<STDIN.getch.

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

더 이상 고민하지 않고 :

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.