首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Javascript链接列表冻结程序

Javascript链接列表冻结程序
EN

Stack Overflow用户
提问于 2021-12-23 22:28:21
回答 1查看 29关注 0票数 0

我试图用javascript编写一个简单的网页嵌入程序。现在,我正试图在任何给定的时间在屏幕上写一个所有活动按钮的链接列表。但是,当我试图迭代一个不为空的链接列表时,程序会冻结。

这是相关的代码块:

代码语言:javascript
复制
document.addEventListener("click", (event) => {

    if (seekButtons) {

        if (!(activeButtons.isEmpty())) {
            var runner = activeButtons.head;

            /*
             * 
             * This while loop seems to run indefinitely if the activeButtons list has anything in it.
             * 
             */ 
            while (runner) {
                //this list should be populated only by buttons
                console.log("a button! \n");

                if (runner.element.isInside(mouseX, mouseY)) {
                    document.getElementById("fiddleText").innerHTML = ('clicked');
                    console.log("We are in the button! \n");

                    //This line doesn't seem to work correctly. It's meant to move on to the next item in the list (and to exit the while loop if it's the last item), but the loop runs forever.
                    runner = runner.next;
                }
            }
            

        }
        
    }
});

我想我需要另一双眼睛来观察这件事,帮我找出为什么这不起作用的原因。

链接列表代码(不是由我编写的)如下所示:

代码语言:javascript
复制
//this code shamelessly stolen from https://www.geeksforgeeks.org/implementation-linkedlist-javascript/

// User defined class node
class Node {
    // constructor
    constructor(element) {
        this.element = element;
        this.next = null
    }
}

// linkedlist class
class LinkedList {
    constructor() {
        this.head = null;
        this.size = 0;
    }

    // adds an element at the end
    // of list
    add(element) {
        // creates a new node
        var node = new Node(element);

        // to store current node
        var current;

        // if list is Empty add the
        // element and make it head
        if (this.head == null)
            this.head = node;
        else {
            current = this.head;

            // iterate to the end of the
            // list
            while (current.next) {
                current = current.next;
            }

            // add node
            current.next = node;
        }
        this.size++;
    }

    // insert element at the position index
    // of the list
    insertAt(element, index) {
        if (index < 0 || index > this.size)
            return console.log("Please enter a valid index.");
        else {
            // creates a new node
            var node = new Node(element);
            var curr, prev;

            curr = this.head;

            // add the element to the
            // first index
            if (index == 0) {
                node.next = this.head;
                this.head = node;
            } else {
                curr = this.head;
                var it = 0;

                // iterate over the list to find
                // the position to insert
                while (it < index) {
                    it++;
                    prev = curr;
                    curr = curr.next;
                }

                // adding an element
                node.next = curr;
                prev.next = node;
            }
            this.size++;
        }
    }

    // removes an element from the
    // specified location
    removeFrom(index) {
        if (index < 0 || index >= this.size)
            return console.log("Please Enter a valid index");
        else {
            var curr, prev, it = 0;
            curr = this.head;
            prev = curr;

            // deleting first element
            if (index === 0) {
                this.head = curr.next;
            } else {
                // iterate over the list to the
                // position to removce an element
                while (it < index) {
                    it++;
                    prev = curr;
                    curr = curr.next;
                }

                // remove the element
                prev.next = curr.next;
            }
            this.size--;

            // return the remove element
            return curr.element;
        }
    }

    // removes a given element from the
    // list
    removeElement(element) {
        var current = this.head;
        var prev = null;

        // iterate over the list
        while (current != null) {
            // comparing element with current
            // element if found then remove the
            // and return true
            if (current.element === element) {
                if (prev == null) {
                    this.head = current.next;
                } else {
                    prev.next = current.next;
                }
                this.size--;
                return current.element;
            }
            prev = current;
            current = current.next;
        }
        return -1;
    }

    // finds the index of element
    indexOf(element) {
        var count = 0;
        var current = this.head;

        // iterate over the list
        while (current != null) {
            // compare each element of the list
            // with given element
            if (current.element === element)
                return count;
            count++;
            current = current.next;
        }

        // not found
        return -1;
    }

    // Helper Methods

    // checks the list for empty
    isEmpty() {
        return this.size == 0;
    }

    // gives the size of the list
    size_of_list() {
        console.log(this.size);
    }

    // prints the list items
    printList() {
        var curr = this.head;
        var str = "";
        while (curr) {
            str += curr.element + " ";
            curr = curr.next;
        }
        console.log(str);
    }
}

我的主要代码如下所示:

代码语言:javascript
复制
//canvas elements
var canvas = document.getElementById("SnekGamCanvas");
var ctx = canvas.getContext("2d");
canvas.addEventListener('click', function () { }, false);


//some important variables
var px = canvas.width / 2;
var py = canvas.height / 2;

var snekColor = "#EC942D";

var clock = 0;

var mouseX = 0.5;
var mouseY = 0.5;

var activeButtons = new LinkedList();

var seekButtons = true;

//classes

class clickButton {
    constructor(text, color, altColor, width, height, radius, xpos, ypos) {
        this.text = text;
        this.color = color;
        this.altColor = altColor;
        this.width = width;
        this.height = height;
        this.radius = radius;
        this.xpos = xpos;
        this.ypos = ypos;
    }

    isInside(datX, datY) {
        //usually, datX will be mouseX, and datY will be mouseY.
        if (datX > (this.xpos) && datX < (this.xpos + this.width)) {
            if ((datY > this.ypos) && datY < (this.ypos + this.height)) {
                return true;
            }
        }
        return false;
    }

    drawButton() {
        ctx.strokeStyle = "#000000"
        if (this.isInside(mouseX, mouseY)) {
            ctx.fillStyle = this.altColor;

            roundRect(this.xpos, this.ypos, this.width, this.height, this.radius, true, true, this.altColor);

            ctx.fillStyle = "#000000";
            ctx.strokeStyle = "#000000";
            ctx.font = '40px san-serif';

            ctx.strokeText(this.text, this.xpos + 10, this.ypos + 40);
            ctx.fillText(this.text, this.xpos + 10, this.ypos + 40);
        }
        else {
            ctx.fillStyle = this.color;

            roundRect(this.xpos, this.ypos, this.width, this.height, this.radius, true, true, this.color);

            ctx.fillStyle = "#000000";
            ctx.strokeStyle = "#000000";
            ctx.font = '40px san-serif';

            ctx.strokeText(this.text, this.xpos + 10, this.ypos + 40);
            ctx.fillText(this.text, this.xpos + 10, this.ypos + 40);
        }
        

        //draw_Ball(303, 500, 50, snekColor);
    }

    clickOnButton() {
        document.getElementById("fiddleText").innerHTML = ('clicked');
    }

}

//buttons

var startButton = new clickButton("Start Game", "#74B5ED", "#1824C7", 200, 50, 20, ((canvas.width / 2) - 100), (canvas.height * (4 / 5)));

//images
var seel = new Image();
seel.onload = function () {
    ctx.drawImage(seel, 0, 0, canvas.width, canvas.height);
}
seel.src = "https://assets.pokemon.com/assets/cms2/img/pokedex/full/086.png"

var snek_title = new Image();
snek_title.onload = function () {
    ctx.drawImage(snek_title, 0, 0, canvas.width, canvas.height);
}
snek_title.src = "https://globin347.com/images/Snake%20Title.png"

//stuff about mouse moving
//the relative mouse position code came from this stackoverflow page: https://stackoverflow.com/questions/17130395/real-mouse-position-in-canvas

function getMousePosX(canvas, evt) {
    var rect = canvas.getBoundingClientRect(), // abs. size of element
        scaleX = canvas.width / rect.width;    // relationship bitmap vs. element for X

    return (evt.clientX - rect.left) * scaleX;   // scale mouse coordinates after they have
}

function getMousePosY(canvas, evt) {
    var rect = canvas.getBoundingClientRect(), // abs. size of element
        scaleY = canvas.height / rect.height;  // relationship bitmap vs. element for Y

    return (evt.clientY - rect.top) * scaleY;
}

document.addEventListener('mousemove', (event) => {
    //document.getElementById("fiddleText").innerHTML = (`Mouse X: ${event.clientX}, Mouse Y: ${event.clientY}`);


    mouseX = getMousePosX(canvas, event);
    mouseY = getMousePosY(canvas, event);
    //document.getElementById("fiddleText").innerHTML = ('mouseX: ' + mouseX + ', mouseY: ' + mouseY);

    //now convert total position to canvas position
    //mouseX, mouseY = getMousePos(canvas, event);

    //document.getElementById("fiddleText").innerHTML = ('mouseX: ' + mouseX + ', mouseY: ' + mouseY);
});

//mouse clicking

document.addEventListener("click", (event) => {

    if (seekButtons) {

        if (!(activeButtons.isEmpty())) {
            var runner = activeButtons.head;

            /*
             * 
             * This while loop seems to run indefinately if the activeButtons list has anything in it.
             * 
             */ 
            while (runner) {
                //this list should be populated only by buttons
                console.log("a button! \n");

                if (runner.element.isInside(mouseX, mouseY)) {
                    document.getElementById("fiddleText").innerHTML = ('clicked');
                    console.log("We are in the button! \n");

                    //This line doesn't seem to work correctly. It's meant to move on to the next item in the list (and to exit the while loop if it's the last item), but the loop runs forever.
                    runner = runner.next;
                }
            }
            
        }
        
    }
});


//begin
var gameState = -1;

function draw() {

    clock += 1;
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    //document.getElementById("fiddleText").innerHTML = ("Clock: " + clock);
    if (gameState == -1) {
        //startup
        setup();
    }
    else if (gameState == 0) {
        //this hasn't been implemented yet
        startMenu();
    }
    else if (gameState == 1) {
        //this hasn't been implemented yet either
        playGame();
    }
    else if (gameState == 2) {
        //ditto
        gameOver();
    }
    else {
        //something's wrong

        ctx.drawImage(seel, 0, 0, canvas.width, canvas.height);

        ctx.fillStyle = "#b30000";
        ctx.strokeStyle = "#000000";
        ctx.font = '140px san-serif';

        ctx.fillText('OH NO', 120, 120);
        ctx.strokeText('OH NO', 120, 120);

        ctx.fillText('IT BLOKE', 200, 630);
        ctx.strokeText('IT BLOKE', 200, 630);
    }

}
setInterval(draw, 10);

function setup() {

    //this should be added to the buttons list before the program starts in earnest

    activeButtons.add(startButton);
    activeButtons.printList();

    //document.getElementById("fiddleText").innerHTML = ('Oh Boy Baby');
    //document.getElementById("fiddleText").innerHTML = ('large');

    gameState = 0;

}

function startMenu() {
    ctx.drawImage(snek_title, 0, 0, canvas.width, canvas.height);

    startButton.drawButton();

    //draw_Ball(mouseX, mouseY, 50, snekColor);
}

function playGame() {
    draw_Ball(200, 700, 50, snekColor);
    draw_Ball(400, 700, 50, snekColor);
    draw_Ball(300, 500, 50, snekColor);
}

function gameOver() {

}

//this function was stolen from stack overflow
function showImage(width, height, image_source, alt_text) {
    var img = document.createElement("img");
    img.src = image_source;
    img.width = width;
    img.height = height;
    img.alt = alt_text;

}

function draw_Ball(bx, by, size, ballColor) {
    ctx.beginPath();
    ctx.arc(bx, by, size, 0, (Math.PI * 2));
    ctx.fillStyle = ballColor;
    ctx.fill();
    ctx.strokeStyle = "#000000";
    ctx.stroke();
    ctx.closePath();
}

//This next function was taken from stack overflow

function roundRect(x, y, width, height, radius, stroke, fill, color) {
    ctx.beginPath();
    ctx.moveTo(x + radius, y);
    ctx.lineTo(x + width - radius, y);
    ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
    ctx.lineTo(x + width, y + height - radius);
    ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
    ctx.lineTo(x + radius, y + height);
    ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
    ctx.lineTo(x, y + radius);
    ctx.quadraticCurveTo(x, y, x + radius, y);
    if (stroke) {
        ctx.stroke();
    }
    if (fill) {
        ctx.fill();
    }
    ctx.closePath();
    return;
}

而且,以防万一,这里是我的css和html文件:

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - Portfolio</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="~/css/site.css" />
</head>
<body class="background_gradient">
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-dark dark-bg border-bottom box_shadow mb-0">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">Portfolio</a>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
                        </li>
                        <!--
                        <li class="nav-item">
                            <a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
                        </li>
                        -->
                        <li class="nav-item">
                            <a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Resume">Resume</a>
                        </li>
                        <!----
                        <li class="nav-item">
                            <a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Art3D">3D Art</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Art2D">2D Art</a>
                        </li>
                        <!---->
                        <li class="nav-item">
                            <a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Snake">Snake</a>
                        </li>
                        
                        <li class="nav-item">
                            <a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="CodeExamples">Code Examples</a>
                        </li>

                        <li class="nav-item">
                            <a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Ballad">Ballad of the Masked Bandits</a>
                        </li>
                        <!--
    <li class="nav-item">
        <a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="DataBaseHub">Database Hub</a>
    </li>
    --->
                        <!--
    <li class="nav-item">
        <a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Unavailable">???</a>
    </li>
        -->
                        <!--Temporary Links-->
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container-fluid" id="MainDiv">
        <main role="main" class="pb-0" style="width:100%">
            <!--Where the other code goes-->
            
                @{
                    ViewData["Title"] = "Snake Game";
                }
                
                <div class="container-fluid purple_gradient text-center">
                    <h1>Snake Game</h1>
                </div>
                <div class="buffer"></div>
                <div class="container">
                    <div class="fancy_text_box">
                        <div class="container buffer">
                            <div class="ghostly_text_box text-center">
                                <h1>By the power of Javascript, here is a playable snake game.</h1>
                                <div class="buffer"></div>
                                <h1 id="fiddleText">Give it a moment to load.</h1>
                            </div>
                
                            <div class="buffer"></div>
                
                            <div class="ghostly_text_box text-center">
                                <canvas onload="draw()" class="simple_text_box" id="SnekGamCanvas" width="1000" height="1000"></canvas>
                            </div>
                
                        </div>
                
                    </div>
                
                    <div class="text-center">
                        <div class="buffer"></div>
                
                        <a class="button glo_button big_r_button big_text" asp-area="" asp-controller="Home" asp-action="Index">Back to Home</a>
                
                        <div class="buffer"></div>
                    </div>
                
                    <!--The code be here but if you are reading this you probably already knew that-->
                    <script src="~/js/Snake.js"></script>
                
                </div>
                
        </main>
    </div>

    <footer class="border-top footer dark-bg text-light">
        <div class="container">
            &copy; 2021 - Portfolio - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
        </div>
    </footer>
    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>
    <script src="../jsc3d-master/jsc3d/jsc3d.js"></script>
    @RenderSection("Scripts", required: false)
</body>
</html>

代码语言:javascript
复制
/* Please see documentation at https://learn.microsoft.com/aspnet/core/client-side/bundling-and-minification
for details on configuring this project to bundle and minify static web assets. */

a.navbar-brand {
  white-space: normal;
  text-align: center;
  word-break: break-all;
}

/* Provide sufficient contrast against white background */
a {
  color: #0366d6;
}

.btn-primary {
  color: #fff;
  background-image: linear-gradient(30deg, #b6e2dd, #2a5efe);
  border-color: #1861ac;
}

/*Link colors*/
.nav-pills .nav-link.active, .nav-pills .show > .nav-link {
  color: #fff;
  background-color: #1b6ec2;
  border-color: #1861ac;
}

/* Sticky footer styles
-------------------------------------------------- */
html {
  font-size: 14px;
}
@media (min-width: 768px) {
  html {
    font-size: 16px;
  }
}

.border-top {
  border-top: 1px solid #e5e5e5;
}
.border-bottom {
  border-bottom: 1px solid #e5e5e5;
}

.box-shadow {
  box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
}

button.accept-policy {
  font-size: 1rem;
  line-height: inherit;
}

/* Sticky footer styles
-------------------------------------------------- */
html {
  position: relative;
  min-height: 100%;
}

body {
  /* Margin bottom by footer height */
  margin-bottom: 60px;
}
.footer {
  position: absolute;
  bottom: 0;
  width: 100%;
  white-space: nowrap;
  line-height: 60px; /* Vertically center the text there */
}

/* My Stuff
--------------------------------------------------------------------------
--------------------------------------------------------------------------
--------------------------------------------------------------------------
*/

/*This gives me more control over the exact dark background color*/
.dark-bg
{
    background-color: #161631;
}

.purple_gradient 
{
    /*The image used*/
    background-image: linear-gradient(#4b1ac4, #fff);

    height:100%;
    width:100%;

    background-position: center;
    background-repeat: no-repeat;
    background-size: cover;
}

.test_box_blue
{
    /* A container with a solid color and an outline */
    background-color: #2d1eb2;

    width: 100%;
    height: 100%;
    margin: 0px;

}

.test_box
{
    border:solid #000000;
}

#MainDiv
{
    padding:0;
    margin:0;

    left:0;
    top:0;

    width:100%;
    height:100%;
}

.tundra_backround
{
    background-image: url('../images/Tundra_Fixed.png');
    width:100%;
    height:100%;
}

.white_space_box
{
    height:50 px;
}

.background_gradient
{
    background-image:linear-gradient(320deg, #fff, #96cbde);
}

.glo_button
{
    min-width: 30%;
    height: 20%;
    border-radius: 25px;
    padding: 20px;
    margin: 10px;
    box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19);
    transition-duration: 0.4s;
    border: 4px solid #000;
}

.big_r_button {
    background-color: #a10000;
    color: #fff;
}

.big_r_button:hover {
    color: #fff;
    background-color: #4e0505;
}

.big_b_button {
    background-color: #080e9f;
    color: #fff;
}

.big_b_button:hover {
    color: #fff;
    background-color: #161631;
}

.big_g_button {
    background-color: #0a7727;
    color: #fff;
}

.big_g_button:hover {
    color: #fff;
    background-color: #07340e;
}

.big_p_button {
    background-color: #6f1cbf;
    color: #fff;
}

.big_p_button:hover {
   color: #fff;
   background-color: #2a073e;

}

.buffer
{
    padding: 20px;
}

.big_text
{
    font-size: 60px;
    font-family:'Times New Roman', Times, serif;
    text-shadow: 2px 2px rgb(12 14 39 / 0.67);
}

.fancy_text_box{
    background-image: linear-gradient(300deg, #ece1c4, #c99e69);
    border-radius: 25px;
    border: 4px solid #5d3c08;
}

.simple_text_box{
    background-color: #fff;

    border: 2px solid #000;
}

.ghostly_text_box{
    background-color: rgb(255 255 255 / 0.60);
    border-radius: 25px;
    padding: 10px;
    border: 3px solid #000;
}

.thick_border{
    border: 4px solid #000;
}

.black_and_white_gradient{
    background-image: linear-gradient(310deg, #fff, #000);
}

.red_border{
    padding: 0px;
    margin: 0px;
    border: 4px solid #8f0000;
}

.model_box{
    border: 4px solid #000;
    background-color: #fff;
    border-radius: 25px;
}

.image_box{
    border: 4px solid #000;
    background-color: #fff;
}

.chain_image_box {
    border-top: 4px solid #000;
    border-left: 4px solid #000;
    border-right: 4px solid #000;
    border-bottom: 0px;
    background-color: #fff;
}

.margin_setter {
    margin: 20px;
    padding: 20px;
}

#model_display_1{

}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-12-24 00:46:08

只有当当前的跑步者在按钮内时,你才会移动到下一个跑步者。因此,当您的while循环到达不在按钮中的运行程序时,它会被该元素卡住,并无限循环。

runner = runner.next;行从if中取出。

代码语言:javascript
复制
            while (runner) {
                //this list should be populated only by buttons
                console.log("a button! \n");

                if (runner.element.isInside(mouseX, mouseY)) {
                    document.getElementById("fiddleText").innerHTML = ('clicked');
                    console.log("We are in the button! \n");
                }
                runner = runner.next;
            }

for循环可能会使事情变得更简单:

代码语言:javascript
复制
for (let runner = activeButtons.head; runner; runner = runner.next) {
    if (runner.element.isInside(mouseX, mouseY)) {
        document.getElementById("fiddleText").innerHTML = ('clicked');
        console.log("We are in the button! \n");
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70467983

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档