Build a Sorting Visualizer - Build a Sorting Visualizer

Tell us what’s happening:

I’m creating a Bubble Sort visualizer and Step 18 fails because the number of

elements doesn’t match the required number of sorting steps. I think I’m rendering steps at the wrong time (before/after swap) or missing the final step. Need help fixing the step count.

Your code so far

<!-- file: index.html -->
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Sorting Visualizer</title>
    <link rel="stylesheet" href="styles.css">
</head>

<body>
    <main>
        <div id="array-container">
            <div id="starting-array"></div>
        </div>
        <div id="btn-container">
            <button id="generate-btn" type="button">Generate Array</button>
            <button id="sort-btn" type="button">Sort Array</button>
        </div>
    </main>
    <script src="script.js"></script>
</body>

</html>
/* file: styles.css */
* {
    box-sizing: border-box;
}

main {
    height: 100vh;
    display: flex;
    justify-content: center;
    flex-direction: column;
    align-items: center;
}

#array-container {
    max-height: 95vh;
    display: flex;
    flex-direction: column;
    flex-wrap: wrap;
    gap: 2px;

}

#array-container>div {
    min-width: 8rem;
    height: 2rem;
    box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;
    border-radius: 10px;
    margin-bottom: 0.2rem;
    border: 2px solid darkgray;
    display: flex;
    justify-content: space-evenly;
    align-items: center;
}

#starting-array {
    border: 4px solid darkblue !important;
}

#btn-container {
    display: flex;
    justify-content: space-around;
}

button {
    padding: 2px;
    margin: 5px;
}

span {
    border-radius: 2px;
    padding: 0.5px;
    margin: 0
}

@media (min-width: 430px) {
  #array-container>div {
    min-width: 12rem;    
  }
  span {
    padding: 1px;
    margin: 1px;
  }
}
/* file: script.js */
let currentArray = []

function generateElement() {
  return Math.floor(Math.random() * 100) + 1
}

function generateArray() {
  const arr = []
  for (let i = 0; i < 5; i++) {
    arr.push(generateElement())
  }
  return arr
}

function generateContainer() {
  return document.createElement("div")
}

function fillArrContainer(container, arr) {
  container.innerHTML = "" // Clear existing content
  arr.forEach((num) => {
    const span = document.createElement("span")
    span.textContent = num
    container.appendChild(span)
  })
}

function isOrdered(a, b) {
  return a <= b
}

function swapElements(arr, index) {
  if (!isOrdered(arr[index], arr[index + 1])) {
    const temp = arr[index]
    arr[index] = arr[index + 1]
    arr[index + 1] = temp
  }
}

function highlightCurrentEls(container, index) {
  const children = container.children
  if (index < children.length) {
    children[index].style.border = "2px dashed red"
  }
  if (index + 1 < children.length) {
    children[index + 1].style.border = "2px dashed red"
  }
}

document.getElementById("generate-btn").addEventListener("click", () => {
  const arrayContainer = document.getElementById("array-container")
  arrayContainer.innerHTML = ""

  const startingArrayDiv = document.createElement("div")
  startingArrayDiv.id = "starting-array"
  arrayContainer.appendChild(startingArrayDiv)

  currentArray = generateArray()
  fillArrContainer(startingArrayDiv, currentArray)
})


document.getElementById("sort-btn").addEventListener("click", () => {
 if (currentArray.length === 0) return

 const arrayContainer = document.getElementById("array-container")
 const startingArrayDiv = document.getElementById("starting-array")

 fillArrContainer(startingArrayDiv, currentArray)
 highlightCurrentEls(startingArrayDiv, 0)

 const arr = currentArray.slice()
 const n = arr.length

 for (let i = 0; i < n - 1; i++) {
 for (let j = 0; j < n - i - 1; j++) {
 if (!isOrdered(arr[j], arr[j + 1])) {
 swapElements(arr, j)
 }

 const stepContainer = generateContainer()
 fillArrContainer(stepContainer, arr)
 highlightCurrentEls(stepContainer, j + 1)
 arrayContainer.appendChild(stepContainer)
 }
 }
})

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36

Challenge Information:

Build a Sorting Visualizer - Build a Sorting Visualizer

Hi @Roda152,

Please check the loop variables in your #sort-btn listener.

How many iterations does the first loop do? Is that count equal to arr.length?

How many iterations does the second loop do? Is that the number of pairs in the array?

Happy coding!

I checked my loops — the outer loop runs n - 1 times, and the inner loop runs n - i - 1 times, which matches the number of adjacent pairs being compared.

Are you sure about that? Looks to me like your inner loop is getting cut off:

i 0
j 0
j 1
j 2
j 3
i 1
j 0
j 1
j 2
i 2
j 0
j 1
i 3
j 0

Spent a bit digging through that Bubble Sort visualizer issue, and the problem with step count actually makes sense once you look at when each render happens. Feels like the extra or missing step comes from pushing updates inside the inner loop without handling the final state cleanly. I’ve run into similar tracking quirks in Phonexa, where timing of events completely changes the outcome.