แสดงเส้นทางตัวชี้เมาส์ ... ของอนาคต!


24

แรงบันดาลใจจากตัวอย่างของการใช้d3jsนี้ฉันขอท้าให้คุณสร้าง Canvas (หรือเทียบเท่าภาษาที่คุณเลือก) ซึ่งตัวชี้เมาส์จะปรากฏขึ้นโดยมีการบิดดังต่อไปนี้:

The Twist

คุณไม่ควรแสดงเส้นทางที่ตัวชี้เมาส์อยู่แต่ "เส้นทาง" ที่จะ (อาจ) เป็นอนาคต

คุณสามารถทำได้โดยใช้:

  1. เครื่องย้อนเวลาหรือ

  2. การประมาณความน่าจะเป็นขึ้นอยู่กับการเคลื่อนไหวของเมาส์ก่อนหน้า

สมมติฐาน

ในกรณีที่คุณไม่ได้เลือกการนำไทม์แมชชีนไปใช้เมื่อเมาส์ไม่เคลื่อนที่เกินขีด จำกัดมิลลิวินาทีคุณจะไม่สามารถแสดงเส้นทางได้ ( ค่าเกณฑ์ขึ้นอยู่กับคุณที่จะเลือก)

ภาพเคอร์เซอร์ขึ้นอยู่กับคุณและไม่จำเป็นต้องเหมือนกับเคอร์เซอร์ของระบบปฏิบัติการ (คุณสามารถวาดวงกลมหรือจุดเล็ก ๆ ได้)

จะไม่มีการทดสอบอินพุตที่ชั่วร้าย: คุณสามารถสันนิษฐานได้ว่าการเคลื่อนไหวนั้นราบรื่น นิยาม 'ราบรื่น' สำหรับกรณีนี้คือ: หากการเคลื่อนไหวของเมาส์เป็นฟังก์ชันเหนือแกน x และ y ของผืนผ้าใบ - มันจะเป็นฟังก์ชั่นต่อเนื่อง

การชนะ

คำตอบที่ถูกต้องพร้อมด้วยตัวอักษรน้อยที่สุดในรหัสจะเป็นผู้ชนะ ในกรณีที่เสมอกัน - คนที่ถูกโพสต์ก่อนจะเป็นผู้ชนะ

แก้ไข:คำตอบที่ถูกต้องกับupvotes ที่สุดจะเป็นผู้ชนะ ในกรณีที่เสมอกัน - คนที่ถูกโพสต์ก่อนจะเป็นผู้ชนะ คุณสามารถสร้างสรรค์ในการใช้งานหรือแม่นยำกับการทำนาย ฉันไม่ใช่ผู้ตัดสินอีกต่อไปเราทุกคนเป็น :)

  • คำตอบที่ถูกต้องจะต้องมีวิธีที่ฉันจะเล่นด้วย (ทดสอบ! ฉันหมายถึงการทดสอบ) ไม่ว่าจะเป็นเครื่องมือออนไลน์หรือบนคอมไพเลอร์ / ล่าม / นักแปล / รันไทม์ / ดาวน์โหลดได้อย่างอิสระ

2
ฉันคิดว่าคำถามนี้อาจเหมาะกับการประกวดความนิยมมากกว่าโค้ดกอล์ฟเพราะมันค่อนข้างเป็นอัตนัยว่าสิ่งใดที่มีคุณสมบัติเป็นการทำนายที่ดีพอ ฉันขอแนะนำให้อธิบายอย่างชัดเจนหรือเปลี่ยนแท็ก อย่างไรก็ตามดูสนุก
isaacg

2
คุณถูก. ฉันแก้ไขคำถามและเปลี่ยนแท็ก
จาค็อบ

ถึงเวลาที่ใครบางคนจะใช้อัลกอริทึมการเรียนรู้ของเครื่อง!
Ingo Bürk

6
สำหรับจุดประสงค์ในการทดสอบคุณสามารถเข้าถึงไทม์แมชชีนแบบใดได้บ้าง และเราอาจใช้ไลบรารีมาตรฐานเพื่อเชื่อมต่อกับพวกเขาได้ไหม
Peter Taylor

1
เป็นนักคณิตศาสตร์ที่ส่งเสียงครวญครางที่นี่: ราบรื่น! = ต่อเนื่อง ในความเป็นจริงการเคลื่อนไหวแหลมป่าจะยังคงต่อเนื่อง
CompuChip

คำตอบ:


33

จาวาสคริ

โปรแกรมของฉันทำนายทิศทางของตัวชี้โดยใช้ค่าเฉลี่ยของการเปลี่ยนแปลงเชิงมุมในทิศทางของการเคลื่อนที่ของเมาส์ 20 ครั้งล่าสุด นอกจากนี้ยังใช้ความแปรปรวนของการเปลี่ยนแปลงเชิงมุมเพื่อสร้าง "คลาวด์" ของตำแหน่งและทิศทางของตัวชี้ที่เป็นไปได้ สีของตัวชี้แต่ละตัวใน "คลาวด์" นั้นควรจะเป็นตัวแทนของโอกาสในการเป็นตำแหน่งใหม่ของตัวชี้เมาส์ซึ่งสีที่เข้มกว่าแสดงถึงโอกาสที่มากขึ้น ระยะทางของคลาวด์พอยน์ก่อนเมาส์คำนวณโดยใช้ความเร็วในการเคลื่อนที่ของเมาส์ มันไม่ได้ทำการทำนายที่ดีที่สุด แต่มันก็ดูเรียบร้อย

นี่คือซอ: http://jsfiddle.net/5hs64t7w/4/

การเพิ่มขนาดของคลาวด์พอยน์เตอร์นั้นน่าสนใจ มันสามารถตั้งค่าได้โดยการเปลี่ยนcloudSizeตัวแปรในบรรทัดแรกของโปรแกรม นี่คือซอที่มีขนาดเมฆ 10: http://jsfiddle.net/5hs64t7w/5/

ฉันใช้แหล่งข้อมูลเหล่านี้เพื่อรับสูตรสำหรับค่าเฉลี่ยวงกลมและความแปรปรวน:
ค่าเฉลี่ยแบบวงกลม: http://en.wikipedia.org/wiki/Circular_mean
ความแปรปรวนแบบวงกลม: http://www.ebi.ac.uk/thornton-srv/software/ PROCHECK / nmr_manual / man_cv.html

นี่คือรหัสหากใครสนใจ:

    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
คุณสามารถแสดงลำดับของตัวชี้เมาส์ (ที่มีการวางแนวคงที่) แทนการใช้ตัวชี้ที่ชี้ไปยังทิศทางที่ผันแปรได้หรือไม่? ฉันคาดหวังว่าจะเห็น "เส้นทางของหนู" แต่มองไม่เห็นฮ่า ๆ
justhalf

เยี่ยมมาก แต่ไม่น่าจะเป็นไปได้มากกว่าที่ตัวชี้จะขึ้นในอนาคตเมื่อลงไปในขณะนี้ อิมโฮโปรแกรมควรทำสิ่งที่ตรงกันข้ามดังนั้นจึงคาดการณ์ว่าตัวชี้จะอยู่บนหน้าจอ
Madmenyo

@MennoGouw มันไม่สมบูรณ์แบบ แต่เป็นคำสาปที่ดี
ทีเดียว

@nimchimpsky เพียงแค่บอกว่าความน่าจะเป็นของเมาส์ที่เพิ่มขึ้นจะสูงกว่าถ้าหากเมาส์นั้นลง โปรแกรมตัวนี้ยอดเยี่ยมมาก
Madmenyo

คุณคิดว่าเป็นไปได้หรือไม่ที่จะใช้พฤติกรรมของมนุษย์ตามปกติในการจัดการกับเมาส์? เช่นเดียวกับแวดวง, เส้นตรง ... สิ่งเหล่านี้สามารถคาดการณ์ได้มากขึ้นในอนาคต (คำนวณรัศมีของวงกลมหลังจาก mesures สองสามครั้ง, และตกแต่งวงก่อนที่คุณจะร่างมันเสร็จ)
Saffron

14

ชวา

ฉันตัดสินใจใช้แนวทางไทม์แมชชีน ปรากฎส่วนผสมหลักของเครื่องย้อนเวลาคือ java.awt.Robot โปรแกรมของฉันให้คุณเลื่อนเมาส์ไปรอบ ๆ เป็นเวลา 10 วินาที หลังจากผ่านไป 10 วินาทีมันจะย้อนเวลากลับไปและสร้างการเคลื่อนไหวของเมาส์ใหม่ในขณะที่ทำนายได้อย่างสมบูรณ์แบบ

ป้อนคำอธิบายรูปภาพที่นี่

นี่คือรหัส:

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

}

โค้ดปรับให้เหมาะสมโดย Netbeans เล็กน้อย (กำจัดคำเตือน): pastebin.com/E57LZ4zY
Kaz Wolfe

10

Vanilla Javascript

เพียงเพื่อเริ่มต้นสิ่งต่าง ๆ นี่คือการทำนายอย่างง่ายโดยยึดตามค่าสองค่า การโพสต์ของnเมาส์ครั้งสุดท้ายจะถูกจดจำและเก็บไว้ในคิวการทำนายเป็นการคาดการณ์เชิงเส้นอย่างง่ายขององค์ประกอบแรกและสุดท้ายในคิว

นี่เป็นเพียงรหัสทำนายรหัสเต็มรวมถึงตัวอย่างสามารถดูได้ใน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;
}

การสาธิตประกอบด้วยความคิดเห็นในการทำนายที่ช่วยให้คุณสามารถใช้สององค์ประกอบสุดท้ายในคิวสำหรับการทำนายแทน ทำให้ผลลัพธ์ "เรียลไทม์" มากขึ้น แต่ก็ยัง "ราบรื่น" น้อยลง

หากใครต้องการที่จะใช้การboilerplate workใช้อัลกอริทึมการทำนายที่แตกต่างกันรู้สึกฟรี มันไม่ได้ทำงานมากนัก


คุณสามารถแสดงตัวชี้เมาส์แทนบรรทัดได้หรือไม่? ฉันคาดหวังว่าจะเห็น "เส้นทางของหนู" แต่มองไม่เห็นฮ่า ๆ
justhalf

คำถามบอกว่าไม่จำเป็นต้องเป็นเคอร์เซอร์;)
Ingo Bürk

4

จาวาสคริ

อดีตคือคำทำนายที่ดีที่สุดสำหรับอนาคต - ฉันและคนอื่นเช่นกัน

ทางออกของฉันง่ายมาก อันดับแรกนี่คือ>>> ซอ! <<<

สิ่งที่มันทำคือการเปลี่ยนเส้นทางที่ผ่านมาดังนั้นมันจึงดูเหมือนเส้นทางในอนาคต โดยทั่วไปไม่มีส่วนเกี่ยวข้องทางคณิตศาสตร์ (ฉันรู้ว่าน่าเบื่อมาก) คุณสามารถดูข้อผิดพลาดได้อย่างง่ายดายโดยเฉพาะเมื่อเลื่อนเคอร์เซอร์เป็นวงกลม นั่นเป็นเหตุผลที่ฉันทำเส้นทางสั้นมาก;)

รหัส:

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

ฮ่าฮ่าฉันเพิ่งดูวันที่ อะไรก็ตามที่ฉันชอบ
Felk
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.