Hiển thị con trỏ chuột đường mòn của tương lai!


24

Lấy cảm hứng từ ví dụ này về việc sử dụng d3js , tôi thách bạn tạo ra một khung vẽ (hoặc ngôn ngữ tương đương với lựa chọn ngôn ngữ của bạn) trong đó các vệt con trỏ chuột sẽ được hiển thị, với cách xoắn sau:

Vắt

Bạn không nên hiển thị những con đường mòn về nơi con trỏ chuột , nhưng "con đường mòn" của nơi mà nó sẽ (có thể) được trong tương lai.

Bạn có thể làm điều đó bằng cách sử dụng một trong hai:

  1. Một cỗ máy thời gian, hoặc

  2. Ước tính xác suất dựa trên chuyển động chuột trước đó

Giả định

Trong trường hợp bạn không chọn thực hiện cỗ máy thời gian, khi chuột không di chuyển quá ngưỡng mili giây, bạn không thể hiển thị bất kỳ dấu vết nào. ( Giá trị ngưỡng tùy thuộc vào bạn chọn).

Hình ảnh con trỏ tùy thuộc vào bạn và không nhất thiết phải giống với con trỏ của HĐH (thậm chí bạn có thể vẽ một vòng tròn hoặc dấu chấm nhỏ đơn giản).

Không có đầu vào xấu sẽ được kiểm tra: Bạn có thể giả sử các chuyển động được trơn tru. Định nghĩa 'Smooth' cho trường hợp này là: nếu chuyển động của chuột là một hàm trên trục x và y của khung vẽ - thì đó sẽ là một hàm liên tục.

Chiến thắng

Câu trả lời hợp lệ với ít ký tự nhất trong mã sẽ giành chiến thắng. Trong trường hợp hòa - cái nào được đăng đầu tiên sẽ thắng.

EDIT: Câu trả lời hợp lệ với hầu hết các upvote sẽ giành chiến thắng. Trong trường hợp hòa - cái nào được đăng đầu tiên sẽ thắng. Bạn có thể sáng tạo trong việc thực hiện, hoặc chính xác với dự đoán. Tôi không còn là thẩm phán nữa, tất cả chúng ta đều vậy :)

  • Một câu trả lời hợp lệ phải bao gồm một cách để tôi chơi (kiểm tra! Ý tôi là kiểm tra), trên công cụ trực tuyến hoặc trên trình biên dịch / trình thông dịch / thời gian chạy / v.v.

2
Tôi nghĩ rằng câu hỏi này có thể phù hợp hơn với một cuộc thi phổ biến hơn là môn đánh gôn, bởi vì nó khá chủ quan về những gì đủ điều kiện là một dự đoán đủ tốt. Tôi sẽ khuyên bạn nên làm rõ điều đó hoặc thay đổi thẻ. Tuy nhiên, trông vui vẻ.
isaacg

2
Bạn đúng. Tôi đã chỉnh sửa câu hỏi và thay đổi thẻ.
Jacob

Thời gian để ai đó thực hiện các thuật toán học máy!
Ingo Bürk

6
Đối với mục đích thử nghiệm, bạn có quyền truy cập vào mô hình nào của cỗ máy thời gian? Và chúng ta có thể sử dụng các thư viện tiêu chuẩn để giao tiếp với chúng không?
Peter Taylor

1
Chỉ cần một nhà toán học rên rỉ ở đây: trơn tru! = Liên tục. Trong thực tế phong trào tăng vọt hoang dã vẫn sẽ được liên tục.
CompuChip

Câu trả lời:


33

Javascript

Chương trình của tôi dự đoán hướng của con trỏ bằng cách sử dụng trung bình của sự thay đổi góc theo hướng của 20 lần di chuyển chuột cuối cùng. Nó cũng sử dụng phương sai của thay đổi góc để tạo ra một "đám mây" các vị trí và hướng có thể của con trỏ. Màu sắc của mỗi con trỏ trong "đám mây" được cho là thể hiện khả năng nó là vị trí mới của con trỏ chuột, trong đó màu tối hơn thể hiện khả năng lớn hơn. Khoảng cách của đám mây con trỏ phía trước chuột được tính bằng tốc độ di chuyển của chuột. Nó không đưa ra dự đoán tốt nhất nhưng có vẻ gọn gàng.

Đây là một câu đố: http://jsfiddle.net/5hs64t7w/4/

Tăng kích thước của đám mây con trỏ là điều thú vị để xem. Nó có thể được đặt bằng cách thay đổi cloudSizebiến trên dòng đầu tiên của chương trình. Dưới đây là một câu đố với kích thước đám mây là 10: http://jsfiddle.net/5hs64t7w/5/

Tôi đã sử dụng các nguồn này để có được công thức cho trung bình và phương sai vòng tròn:
Thông tư trung bình: http://en.wikipedia.org/wiki/Circular_mean
Thông số phương sai: http://www.ebi.ac.uk/thornton-srv/software/ PROCHECK / nmr_manual / man_cv.html

Đây là mã nếu có ai quan tâm:

    var cloudSize = 3;

    var canvas = document.getElementById('canvas_element');
    var c = canvas.getContext('2d');
    var prevX = -1;
    var prevY = -1;
    var curX = -1;
    var curY = -1;
    var distance = 0;
    var direction = 0;

    function drawMouse(x, y, angle, gray){
        var grayVal = Math.round(gray*255);
        var grayString = "rgb(" + grayVal + "," + grayVal +"," + grayVal + ")";
        c.fillStyle = grayString;
        c.strokeStyle = grayString;
        c.lineWidth = 1;
        c.beginPath();
        c.moveTo(x, y);
        c.lineTo(x + 16*Math.cos(angle + Math.PI/2.0 + Math.PI/8.0), y + 16*Math.sin(angle + Math.PI/2.0 + Math.PI/8.0));
        c.moveTo(x, y);
        c.lineTo(x + 16*Math.cos(angle + Math.PI/2.0 - Math.PI/8.0), y + 16*Math.sin(angle + Math.PI/2.0 - Math.PI/8.0));
        c.lineTo(x + 16*Math.cos(angle + Math.PI/2.0 + Math.PI/8.0), y + 16*Math.sin(angle + Math.PI/2.0 + Math.PI/8.0));
        c.stroke();
        c.fill();
        c.beginPath();
        c.moveTo(x, y);
        c.lineTo(x + 24*Math.cos(angle + Math.PI/2), y + 24*Math.sin(angle + Math.PI/2));
        c.stroke();
    }

    function sum(array){
        var s = 0.0;
        for(var i=0; i<array.length; i++){
            s += array[i];
        }
        return s;
    }

    var sins = [];
    var coss = [];
    var lengths = [];
    var times = [];
    var index = 0;
    var limit = 20;
    var variance = 0;
    var prevTime = new Date().getTime();
    function updateDistanceAndDirection(x, y){
        var angle = Math.atan2(prevY - curY, prevX - curX);
        sins[index] = Math.sin(angle);
        coss[index] = Math.cos(angle);
        lengths[index] = Math.sqrt((curX-prevX)*(curX-prevX) + (curY-prevY)*(curY-prevY));
        var time = new Date().getTime();
        times[index] = time - prevTime;

        variance = 1.0 - Math.sqrt(sum(coss)*sum(coss)+sum(sins)*sum(sins))/sins.length;

        direction = Math.atan2(1/sins.length*sum(sins),1/coss.length*sum(coss));
        var speed = sum(lengths)/(sum(times)/200);
        distance = Math.min(Math.max(40, speed), 100);
        prevTime = time;
        index = (index+1)%limit;
    }

    function drawMice(count){
        c.clearRect(0, 0, canvas.width, canvas.height);

        for(var i=count; i>=0; i--){
            var dir = direction + i*variance;
            drawMouse(curX - distance*Math.cos(dir), curY - distance*Math.sin(dir), dir - Math.PI/2, i/count);
            dir = direction - i*variance;
            drawMouse(curX - distance*Math.cos(dir), curY - distance*Math.sin(dir), dir - Math.PI/2, i/count);
        }
    }

    canvas.onmousemove = function (event) {
        curX = event.clientX;
        curY = event.clientY;

        updateDistanceAndDirection(curX, curY);

        drawMice(cloudSize);

        prevX = curX;
        prevY = curY;
    };

2
Bạn có thể hiển thị một chuỗi các con trỏ chuột (với hướng cố định) thay vì một con trỏ trỏ đến hướng thay đổi? Tôi đã mong đợi được nhìn thấy "những con đường mòn chuột" nhưng không thể thấy bất kỳ thứ gì, haha
ngay lúc

Rất đẹp, nhưng sẽ không hợp lý hơn khi con trỏ sẽ đi lên trong tương lai khi nó hiện đang đi xuống? Imho, chương trình nên làm chính xác điều ngược lại để nó dự đoán con trỏ vẫn ở trên màn hình.
Madmenyo

@MennoGouw nó không hoàn hảo nhưng cũng khá tốt
NimChimpsky

@nimchimpsky Chỉ cần nói xác suất chuột tăng lên là cao hơn nếu chuột hiện đang đi xuống. Chương trình này là tuyệt vời.
Madmenyo

Bạn có nghĩ rằng cũng có thể sử dụng hành vi thông thường của con người để xử lý chuột không? Giống như các vòng tròn, các đường thẳng ... Chúng có thể được dự đoán xa hơn trong tương lai (tính bán kính của vòng tròn sau một vài câu chuyện và hoàn thành vòng tròn ngay cả trước khi bạn phác thảo nó)
Saffron

14

Java

Tôi quyết định thực hiện phương pháp tiếp cận cỗ máy thời gian. Hóa ra thành phần chính của cỗ máy thời gian là java.awt.Robot. Chương trình của tôi cho phép bạn di chuyển chuột trong vòng 10 giây. Sau 10 giây, nó quay ngược thời gian và tái tạo chuyển động chuột của bạn, đồng thời dự đoán nó một cách hoàn hảo.

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

Đây là mã:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Robot;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.TimerTask;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;


public class TimeMachine extends JPanel implements MouseMotionListener {

    Timer timer;
    int time = 10;
    java.util.Timer taskTimer;
    ArrayList<Point> mousePoints;
    ArrayList<Long> times;
    Robot robot;
    int width, height;
    ArrayList<Point> drawMousePoints;

    public TimeMachine(){
        width = 500;
        height = 500;
        drawMousePoints = new ArrayList<Point>();

        robot = null;
        try{
            robot = new Robot();
        }
        catch(Exception e){
            System.out.println("The time machine malfunctioned... Reverting to 512 BC");
        }
        mousePoints = new ArrayList<Point>();
        times = new ArrayList<Long>();

        taskTimer = new java.util.Timer();

        ActionListener al = new ActionListener(){
            public void actionPerformed(ActionEvent e){
                time--;
                if(time == 0)
                    rewind();
                repaint();
            }
        };
        timer = new Timer(1000, al);
        start();
    }

    public void paint(Graphics g){
        g.clearRect(0, 0, width, height);
        g.drawString("Time Machine activiates in: " + time, 15, 50);
        for(int i=0; i<drawMousePoints.size(); i++){
            Point drawMousePoint = drawMousePoints.get(i);
            drawMouse(drawMousePoint.x-getLocationOnScreen().x, drawMousePoint.y-getLocationOnScreen().y, g, Color.BLACK, Color.LIGHT_GRAY, (double)i/drawMousePoints.size());
        }
    }

    public void drawMouse(int x, int y, Graphics g, Color line, Color fill, double alpha){
        Graphics2D g2d = (Graphics2D)g;
        g2d.setColor(new Color(fill.getRed(), fill.getGreen(), fill.getBlue(), (int)Math.max(Math.min(alpha*255, 255), 0)));
        g2d.fillPolygon(new int[]{x, x, x+4, x+8, x+10, x+7, x+12}, new int[]{y, y+16, y+13, y+20, y+19, y+12, y+12}, 7);

        g2d.setColor(new Color(line.getRed(), line.getGreen(), line.getBlue(), (int)Math.max(Math.min(alpha*255, 255), 0)));
        g2d.drawLine(x, y, x, y + 16);
        g2d.drawLine(x, y+16, x+4, y+13);
        g2d.drawLine(x+4, y+13, x+8, y+20);
        g2d.drawLine(x+8, y+20, x+10, y+19);
        g2d.drawLine(x+10, y+19, x+7, y+12);
        g2d.drawLine(x+7, y+12, x+12, y+12);
        g2d.drawLine(x+12, y+12, x, y);
    }

    public void start(){
        timer.start();
        prevTime = System.currentTimeMillis();
        mousePoints.clear();
    }

    public void rewind(){
        timer.stop();
        long timeSum = 0;
        for(int i=0; i<times.size(); i++){
            timeSum += times.get(0);
            final boolean done = i == times.size()-1;
            taskTimer.schedule(new TimerTask(){
                public void run(){
                    Point point = mousePoints.remove(0);
                    drawMousePoints.clear();
                    drawMousePoints.addAll(mousePoints.subList(0, Math.min(mousePoints.size(), 30)));
                    robot.mouseMove(point.x, point.y);
                    repaint();
                    if(done)
                        System.exit(0);
                }
            }, timeSum);
        }
    }

    long prevTime = 0;
    public void record(MouseEvent m){
        if(timer.isRunning()){
            long time = System.currentTimeMillis();
            mousePoints.add(new Point(m.getXOnScreen(), m.getYOnScreen()));
            times.add((time-prevTime)/10);
            prevTime = time;
        }
    }

    public static void main(String[] args){

        TimeMachine timeMachine = new TimeMachine();

        JFrame frame = new JFrame("Time Machine");
        frame.setSize(timeMachine.width, timeMachine.height);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        frame.addMouseMotionListener(timeMachine);

        frame.add(timeMachine);
    }

    public void mouseDragged(MouseEvent m) {
        record(m);
    }

    public void mouseMoved(MouseEvent m) {
        record(m);
    }

}

Mã được tối ưu hóa một chút bởi Netbeans (đã thoát khỏi các cảnh báo): pastebin.com/E57LZ4zY
Kaz Wolfe

10

Vani Javascript

Chỉ cần bắt đầu mọi thứ, đây là một dự đoán đơn giản dựa trên hai giá trị. Các tư thế nchuột cuối cùng được ghi nhớ và giữ trong một hàng đợi, dự đoán là phép ngoại suy tuyến tính đơn giản của phần tử đầu tiên và cuối cùng trong hàng đợi.

Đây chỉ là mã dự đoán, mã đầy đủ bao gồm cả bản demo có thể được nhìn thấy trong this fiddle:

function predict(trail) {
    var b = trail.pop(),
        a = trail[0],
        d = {
            x: b.x - a.x,
            y: b.y - a.y
        },
        m = Math.sqrt( d.x * d.x + d.y * d.y );

    d.x = 5 * d.x / m;
    d.y = 5 * d.y / m;

    var predictions = [];
    for(var i = 1; i <= 10; i++) {
        predictions.push({
            x: b.x + i * d.x,
            y: b.y + i * d.y
        });
    }

    return predictions;
}

Bản demo chứa một nhận xét trong dự đoán cho phép bạn thay vào đó sử dụng hai yếu tố cuối cùng trong hàng đợi cho dự đoán. Làm cho kết quả "thời gian thực" hơn, nhưng cũng ít "trơn tru" hơn.

Nếu bất cứ ai muốn sử dụng boilerplate workđể thực hiện một thuật toán dự đoán khác nhau, hãy thoải mái. Dù sao đó cũng không phải là nhiều việc.


Bạn có thể hiển thị một con trỏ chuột thay vì một dòng? Tôi đã mong đợi được nhìn thấy "những con đường mòn chuột" nhưng không thể thấy bất kỳ thứ gì, haha
ngay lúc

Câu hỏi nói rằng nó không phải là một con trỏ;)
Ingo Bürk

4

Javascript

Quá khứ là dự đoán tốt nhất cho tương lai - tôi, và cũng có thể là người khác

Giải pháp của tôi rất đơn giản. Đầu tiên, đây là >>> Fiddle! <<<

Tất cả những gì nó làm là dịch chuyển con đường quá khứ, vì vậy nó trông giống như con đường tương lai. Về cơ bản không có môn Toán nào tham gia (Tôi biết, khá nhàm chán). Bạn có thể dễ dàng nhìn thấy các lỗi, đặc biệt là khi di chuyển con trỏ theo vòng tròn. Đó là lý do tại sao tôi thực hiện đường mòn quá ngắn;)

Mật mã:

<!DOCTYPE html>
<html>
    <head>
        <style type="text/css">
            .cursor {
                width: 12px;
                height: 19px;
                position: absolute;
                background-image: url(https://i.imgur.com/h8imKBP.png);
            }
        </style>
        <script type="text/javascript">

            var x, y;
            window.onmousemove = function(e) {x=e.clientX; y=e.clientY;}

            var p = [0,0,0,0,0,0,0,0,0,0];
            window.setInterval(function() {
                p.shift();
                p.push([x, y]);
                var diff = [x-p[0][0], y-p[0][1]];
                for (var i = 0; i < 10; i++) {
                    var e = document.getElementById(i);
                    e.style.left = (p[9-i][0]+diff[0])+"px";
                    e.style.top = (p[9-i][1]+diff[1])+"px";
                }
            }, 10);

        </script>
    </head>
    <body>
    <div id="0" class="cursor"></div>
    <div id="1" class="cursor"></div>
    <div id="2" class="cursor"></div>
    <div id="3" class="cursor"></div>
    <div id="4" class="cursor"></div>
    <div id="5" class="cursor"></div>
    <div id="6" class="cursor"></div>
    <div id="7" class="cursor"></div>
    <div id="8" class="cursor"></div>
    <div id="9" class="cursor"></div>
    </body>
</html>

haha tôi chỉ có một cái nhìn vào ngày
Sao cũng được
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.