Visualisasikan Mata Visual

42

Anda mungkin atau mungkin tidak ingat Xeyes, program demo yang datang dengan (dan, sejauh yang saya tahu, masih disertai) sistem X window. Tujuannya adalah untuk menggambar sepasang mata yang mengikuti kursor mouse Anda:

Xeyes

Tantangan Anda adalah menciptakan kembali Xeyes dengan seni ASCII. Tulis program atau fungsi yang menarik dua mata seni ASCII (ditentukan di bawah) di mana pun pengguna mengklik dan kemudian menggerakkan murid-murid mereka untuk menunjuk ke arah kursor.

Mata Terminal GIF

GIF di atas adalah rekaman implementasi Ruby non-golf ini , yang dapat dijalankan dengan Ruby versi terbaru. Anda juga dapat menemukan itu berguna sebagai referensi untuk urutan kontrol Xterm.

Spesifikasi

Ini adalah , jadi solusi dengan byte paling sedikit menang.

Ini adalah tantangan, sehingga program Anda harus menggambar menggunakan ASCII karakter-khusus, karakter -, ., |, ', 0, ruang, dan baris baru. 1 2

Ini adalah tantangan , sehingga program Anda harus menerima input dan menggambar outputnya secara realtime. 3

Sebelum program Anda mulai menerima input, ia harus menginisialisasi kanvas kosong setidaknya 20 baris dan 20 kolom. Seharusnya tidak menarik apa pun sampai pengguna mengklik kanvas.

Setiap kali pengguna mengklik 4 pada kanvas, program harus menghapus output sebelumnya dan kemudian menarik mata ASCII ini pada kanvas, berpusat pada karakter terdekat dengan lokasi kursor mouse. 5 6 (Di bawah ini, menunjukkan kursor mouse dan tidak boleh digambar.)

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

Perhatikan bagaimana murid "menunjuk" ke arah kursor.

Setiap kali kursor mouse bergerak di atas kanvas, program harus menggambar ulang pupil sehingga mereka terus menunjuk ke arah kursor, 7 misalnya:




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

Murid menunjuk

Misalkan kita menyebutkan posisi sembilan karakter batin masing-masing mata seperti:

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

Murid akan ditarik di salah satu lokasi 1- 9. Untuk memutuskan yang mana, berpura-pura karakter persegi dan bahwa kanvas adalah kisi Cartesian, dengan pusat 9karakter di (0, 0), pusat 1di (1, 0), dan sebagainya. Ketika program menerima input — klik atau gerakan — ia harus memetakan lokasi input ke koordinat grid terdekat 𝑀. Jika 𝑀 adalah (0, 0), murid harus ditarik pada (0, 0), yaitu lokasi di 9atas. Kalau tidak, itu harus ditarik seperti yang dijelaskan di bawah ini.

Bayangkan sebuah pesawat Cartesius ditumpangkan pada grid dan dibagi menjadi oktan bernomor 1 - 8 :

Jika 𝑀 terletak di dalam oktan 1 , maka murid harus digambarkan di lokasi di 1atas, yaitu di (1, 0). Jika 𝑀 dalam 2 oktan itu harus ditarik pada 2—dan seterusnya. Untuk mengilustrasikan, gambar di bawah ini menunjukkan bagian dari kode warna kotak sesuai dengan di mana murid harus ditarik ketika kursor mouse berada di lokasi tertentu. Ketika, misalnya, kursor berada pada salah satu koordinat hijau (dengan mengingat bahwa koordinat kisi terletak di pusat kotak, bukan sudutnya), murid harus digambar 4.

Murid kedua mata bergerak secara independen, sehingga untuk setiap mata ulangi proses dengan 𝑀 relatif terhadap pusat mata itu.

Catatan

  1. Ini bukan tantangan . Outputnya harus berupa grid karakter. Anda tentu saja dapat menggunakan rutinitas grafik untuk menggambar kisi-kisi karakter.

  2. Ruang kosong dapat digambar (atau, lebih tepatnya, tidak digambar) namun nyaman. Tempat kosong di kisi terlihat sama dengan karakter ruang dan akan dianggap setara.

  3. "Real-time" didefinisikan di sini sebagai kurang dari 200 ms antara input dan output yang sesuai ditarik.

  4. Sesuai kebijaksanaan Anda tombol mouse mana yang diamati untuk input, dan apakah pers atau rilis merupakan "klik".

  5. Kanvas harus dibersihkan, atau setara visual harus dicapai. Dengan solusi berbasis terminal, misalnya, mencetak kanvas baru di bawah kanvas sebelumnya tidak dianggap setara.

  6. Ketika pengguna mengklik di dekat tepi kanvas sehingga beberapa karakter mata akan ditarik keluar dari tepi kanvasnya, perilaku tidak terdefinisi. Namun, program harus terus berjalan secara normal pada klik berikutnya.

  7. Ketika kursor mouse meninggalkan "kanvas," perilaku tidak terdefinisi, tetapi program harus terus berjalan secara normal ketika kursor masuk kembali ke kanvas.

  8. Kursor teks dapat muncul di kanvas, selama itu tidak mengaburkan output.

Celah standar dilarang.

Jordan
sumber
2
@ Surous Karena berapa menit "beberapa" dalam kasus itu akan tergantung pada berapa banyak memori yang dimiliki sistem, dan itu bisa membawa kita ke "solusi ini mengasumsikan lingkungan memiliki 512GB RAM" wilayah, saya akan mengatakan bahwa itu harus berpotensi berjalan tanpa batas.
Jordan
1
@TaylorScott Tidak. Lihat catatan # 6 (kecuali saya salah mengerti pertanyaan Anda).
Jordan
1
@ Οurous Ya, dan tidak. Jika lingkungan target Anda biasanya satu di mana font default adalah monospace (katakanlah, emulator terminal, atau editor kode), maka itu tidak masalah. Jika menggunakan font monospace di lingkungan itu biasanya membutuhkan konfigurasi tambahan (seperti pada solusi JS berbasis browser), konfigurasi itu harus menjadi bagian dari jumlah byte Anda (misalnya <pre>atau font-family:monospace).
Jordan
9
+1 untuk judul hebat (atau judul buruk, tergantung pada cara Anda mengambilnya)
FantaC
1
@ Οurous Tidak, asalkan tidak berhenti secara tak terduga.
Jordan

Jawaban:

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

Darrylyeo
sumber
Keduanya X||Ydapat di-golf X|Yuntuk menghemat 2 byte.
Kevin Cruijssen
Tidak berfungsi dengan baik ketika Anda mengklik di dekat bagian bawah wadah dan harus menggulir ke bawah. i.stack.imgur.com/s44KU.png Tidak yakin apakah khusus untuk bungkus snippet, tetapi layak disebutkan.
Draco18s
2
@ Οurous Kata ini agak ambigu: "berpusat di lokasi kursor mouse." Apakah "lokasi" berarti "sel jaringan" atau dapatkah itu berarti "piksel"? Saya setuju bahwa maksudnya mungkin yang pertama, tetapi kata-katanya jelas memungkinkan yang terakhir.
DLosc
@KevinCruijssen Sayangnya, itu tidak berhasil - |berakhir diutamakan daripada ekspresi ternary.
darrylyeo
@ Darrylyeo Tidak, bukan? : S Tabel diutamakan operator JavaScript ini menampilkan |dan ||pada tingkat yang agak sama, dan keduanya di atas ?:.. Keduanya X||Y?w*r(cos(a)):0dan X||Y?h*r(sin(a)):0saat ini dalam bentuk boolean_condition?A:B. Jadi, ketika Anda mengubah X||Yuntuk X|Yitu akan melakukan sedikit-ATAU bijak dan kemudian menafsirkan sebagai kondisi boolean lagi. ( (X||Y)?A:Bvs (X|Y)?A:B, tidak X|(Y?A:B)). Juga, saya tidak melihat perbedaan ketika saya menggunakan "Salin cuplikan untuk menjawab" dan ubah ||ke |. Semuanya masih berjalan persis sama sejauh yang saya tahu ..
Kevin Cruijssen
12

Excel VBA, 630 Bytes

Mengumumkan subrutin lembar kerja yang berjalan pada klik mouse yang tidak mengambil input dan menghasilkan sepasang mata yang mengikuti kursor. Ini tergantung pada fungsi pembantu yang disertakan dan deklarasi jenis, yang harus ditempatkan dalam modul normal.

Versi ini dikalibrasi untuk dijalankan pada zoom default 100%. Hancur jika Anda mencoba menggulir.

Catatan: VBA secara otomatis melengkapi string yang tidak ditentukan pada di baris baru, jadi dalam kode di bawah ini, ada tiga contoh di mana terminal "telah dimasukkan semata-mata untuk tujuan penyorotan - ini tidak berkontribusi pada 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

Fungsi Pembantu dan Deklarasi Jenis

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

Tidak Disatukan dan Dikomentari

Versi ini dikalibrasi untuk dijalankan pada tingkat pembesaran 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

Fungsi Pembantu dan Deklarasi Jenis

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

Keluaran

Gif

Moving_Eyes

Gambar Res Tinggi

Static_Eyes

Taylor Scott
sumber
Ini tidak sesuai dengan spesifikasi dalam beberapa cara. 1. "Kisi karakter" berarti karakter tunggal dengan posisi berbeda. Ketika kursor mouse aktif, katakanlah, 'karakter paling kanan output akan berbeda dari ketika berada di 'karakter paling kiri . 2. Posisi mata tidak tetap. Klik mouse harus menyebabkan mereka pindah ke posisi yang diklik. Saya fleksibel pada metode input (saya akan menerima, katakanlah, kursor mouse virtual yang dikendalikan oleh tombol panah), tetapi ada dua peristiwa input yang berbeda dengan perilaku yang berbeda: gerakan mouse dan klik mouse.
Jordan
@ Jordan, saya tidak yakin apa yang Anda maksud dengan poin 1, bisa tolong jelaskan? Adapun poin 2, mata tidak statis, dan mengklik pada sel mana pun pada lembar di mana subrutin ditempatkan akan memicu Worksheet_SelectionChangeacara dan melewati rentang panggilan ( Targetatau Tdalam kasus ini) - yang menggambar ulang mata dan *panggilan. sel
Taylor Scott
1
@Jordan - Saya percaya bahwa saya telah membahas setiap dan semua masalah Anda, meskipun dengan melakukan itu, saya harus membatasi solusi saya ke 64-Bit Excel dan saya sedang mengerjakan versi yang tidak diklik dan dikomentari saat ini
Taylor Scott
1
@Jordan Itu karena deklarasi windows API untuk 32 dan 64 tetapi VBA berbeda, seperti spesifikasi gabungan dan eksponensial, di mana 32 bit hampir selalu lebih pendek - dan saya saat ini tidak memiliki akses ke versi 32 bit Office: P
Taylor Scott
3
Mungkin mengubah dua tangkapan layar menjadi layar-ke-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

Klik kiri menempatkan mata. Jika penempatan mata akan menyebabkan sebagian mata keluar dari batas, program "membeku" sampai penempatan yang benar dilakukan.

Bagian rumit utama adalah menempatkan murid. Sebagian besar waktu, koordinat pupil hanya pusat mata plus (tanda (Δx), tanda (Δy)), kecuali bahwa dalam oktan 1 dan 5, koordinat y sama dengan pusat-y, dan dalam oktan 3 dan 7, koordinat x sama dengan x-center. Batas oktan dapat dihitung menggunakan kemiringan mgaris dari pusat mata ke koordinat mouse. Dengan mudah, membaginya dengan nol saat menghitung kemiringan memberikan floating-point infinity (+/-) daripada kesalahan.

Mata visual dalam QB64

Tidak disatukan

' 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
DLosc
sumber
Sudah satu atau dua dekade sejak saya menggunakan QB, tetapi tidak bisakah Anda menggunakan ?0bukan ?"0"? Ini menunjukkan bahwa Anda dapat menggunakan ekspresi numerik dan juga string.
Joey
@ Joey Hmm. Mencetaknya sebagai angka juga mencetak spasi sebelum dan sesudahnya ... tapi kalau dipikir-pikir, aku bertaruh aku bisa mencetak murid dulu dan kemudian itu tidak akan menjadi masalah. Kecuali saya harus mencetak perbatasan kiri dan kanan secara terpisah, bukan sebagai "| |". Jadi mungkin tidak akan menyelamatkan apa pun. "0"hanya 2 byte lebih lama.
DLosc
7

6502 kode mesin ( mouse 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

Beraksi:

demo

Tidak ada demo online , maaf, karena ada emulator AFAIK no js C64 yang mendukung mouse. Jika Anda ingin mencobanya sendiri, ambil VICE , unduh biner yang dapat dieksekusi dan jalankan di emulator C64:

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

Untuk mengambil / menghapus tab input mouse dalam menjalankan emulator, gunakan ctrl+mdi Unix / Linux dan ctrl+qdi windows.


Ya, ini harus dilakukan;) Setelah semua, ada adalah sebuah Commodore tikus asli untuk C64, tapi tentu saja, sistem builtin operasi tidak mendukung, jadi saya pertama membutuhkan driver mouse, yang sudah mengambil 230 bytes ( termasuk sprite hardware berbentuk kursor mouse dan batas memeriksa kode untuk area layar, tetapi tanpa menerjemahkan koordinat pointer ke koordinat layar teks).

  • Untuk mengamankan beberapa byte, saya memutuskan untuk menjaga IRQ OS berfungsi dan menggunakan beberapa rutinitas Kernal di mana mungkin (membersihkan layar dan mendapatkan pointer dasar untuk baris layar teks).
  • Kode juga menempatkan semua variabel di zeropage, yang menyimpan lebih banyak byte, tetapi menghancurkan nilai floating point yang digunakan oleh BASIC. Karena program tidak pernah keluar, ini tidak masalah.
  • Trik ketiga untuk mengurangi ukuran adalah modifikasi diri: Hanya ada kode untuk memeriksa menempatkan murid di sisi kiri mata. Kode yang sama digunakan kembali setelah menambal beberapa instruksi pengurangan ke instruksi kenaikan untuk sisi kanan.

Jika Anda tertarik, Anda dapat membaca kode sebagai sumber perakitan di sini :)

Felix Palmen
sumber
Saya tampaknya menjadi satu-satunya yang mencoba bersaing di sini dari waktu ke waktu dengan kode C64. Menyukai tantangan ini, karena mouse pada C64 adalah sesuatu yang "eksotis"! Jika ada yang bertanya-tanya mengapa saya kurang aktif akhir-akhir ini, inilah alasannya: csdb.dk/release/?id=161435 - akhirnya mencoba melakukan permainan berfitur lengkap untuk C64 :)
Felix Palmen
1
Hanya untuk bersenang-senang, saya melakukan "versi mewah": csdb.dk/release/?id=161762
Felix Palmen
7

Bersih , 1014 904 892 884 840 814 782 772 769 byte

-6 byte jika mata tidak perlu membentur kisi

Ini tidak mudah. UI dalam bahasa fungsional jarang.

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

Pastikan Anda menggunakan iTasks Clean, Courierinstal font, dan StdLibSEBELUM ada subfolder ObjectIOdi jalur pencarian modul.

Kompilasi dengan (misalnya, mungkin berbeda): clm -IL StdLib -IL ObjectIO -IL "ObjectIO/OS <YOUR_OS_HERE>" -IL Dynamics -IL Generics -IL Platform -nci <MODULE_NAME_HERE>

Jika Anda belum pernah menjalankan Bersihkan sebelumnya, perkirakan proyek ini membutuhkan waktu 5+ menit untuk dikompilasi.

Tidak Disatukan:

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

Seperti yang dapat Anda lihat dari versi yang tidak disunting, sebagian besar kode hanya mengatur kombinasi "font monospace" dengan "response to the mouse". Dan meskipun Couriertidak membuatnya mudah untuk dikatakan, itu sebenarnya menggambar .dan '. Bertukar dengan sesuatu seperti Consolasmembuatnya lebih jelas.

masukkan deskripsi gambar di sini

Suram
sumber
1
Saya tidak tahu Bersih sama sekali, jadi mungkin aku mengatakan sesuatu yang aneh, tetapi apakah itu mungkin untuk mengubah (abs m)<9&&(abs n)<w='9'ke (abs m)<9&(abs n)<w='9'? Juga, saya sarankan menambahkan layar-ke-gif bukan tangkapan layar.
Kevin Cruijssen
1
@KevinCruijssen Itu tidak akan berfungsi karena beberapa alasan, tapi saya menghemat 4 byte dengan menjatuhkan tanda kurung pada ekspresi yang sama, jadi terima kasih! Saya juga menambahkan gif layar!
Surous
1

Ruby, 335 + 13 = 348 byte

+13 byte untuk -rio/consolemengaktifkan flag IO#getch.

Berisi 0x1bkarakter ESC ( ) literal , yang ditunjukkan seperti di bawah ini. xxd dump mengikuti.

Perhatian: Ini tidak membersihkan setelah itu sendiri saat keluar. Lihat catatan di bawah xxd dump di bawah ini.

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

Tidak disatukan

Ini adalah golf yang cukup naif dari implementasi Ruby asli saya .

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

dump xxd

Program ini menyalakan pelacakan tetikus dengan urutan kontrol xterm \e[?1003htetapi tidak mematikannya saat keluar. Untuk mematikannya, gunakan urutan kontrol \e[?1003l, misalnya:

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

Karena program memakan semua input, sulit untuk keluar. Jika Anda ingin dapat keluar dengan menekan Ctrl + C, tambahkan baris berikut di bawah ini (s<<STDIN.getch:

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

Tanpa basa-basi:

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
Jordan
sumber