JS and its dynamic color changes

A game has been developed using JavaScript and HTML. The game features a table with cells that are assigned IDs for toggling colors using an onClick function. The objective is simple: when a cell is clicked, all neighboring cells, including the clicked one, should change their color (toggle). The game continues until all cells turn red.

Now, there's a requirement to make certain cells default to red, not randomly. How can this be achieved? Additionally, any suggestions on optimizing the code for a more concise execution would be appreciated!

window.onload = function() {

  document.getElementById("zero0").style.backgroundColor = "red";
  document.getElementById("one3").style.backgroundColor = "red";
  document.getElementById("three2").style.backgroundColor = "red";

}

function zero0() {

  var cell00 = document.getElementById("zero0");
  let cell01 = document.getElementById("zero1");
  let cell10 = document.getElementById("one0");

  if (cell00.style.backgroundColor == "red") {
    cell00.style.backgroundColor = "white"
  } else {
    cell00.classList.toggle('reed')
  }
  if (cell01.style.backgroundColor == "red") {
    cell01.style.backgroundColor = "white"
  } else {
    cell01.classList.toggle('reed')
  }
  if (cell10.style.backgroundColor == "red") {
    cell10.style.backgroundColor = "white"
  } else {
    cell10.classList.toggle('reed')
  }
}

...
// More functions here

body {
  text-align: center;
  display: flex;
  justify-content: center;
}

table {
  /*border-radius: 10px;*/
  margin-top: 60px;
  border: 1px solid;
  background-color: lightcyan;
  box-shadow: 5px 5px 40px royalblue;
}

td {
  border: 1px solid;
  width: 40px;
  height: 40px;
}

p {
  font-weight: bold;
  font-size: 17px;
}

td {
  background-color: white;
}

.reed {
  background-color: red;
}
<div class="container">
  <h2>Table game</h2>
  <p>Try to color all of the cells to <b>red</b></p>
  <table>
    <tr>
      <td id="zero0" onclick="zero0()"></td>
      <td id="zero1" onclick="zero1()"></td>
      <td id="zero2" onclick="zero2()"></td>
      <td id="zero3" onclick="zero3()"></td>
      <td id="zero4" onclick="zero4()"></td>
    </tr>
    ... // More table rows
  </table>
</div>

Answer №1

After reviewing the problem, I came up with a more streamlined solution to simplify the code and address some issues (such as the first cell not turning red). Hopefully, my interpretation is accurate, and you find this version helpful!

// Representing colors: 0=white, 1=red
const cellsToStartRed = [
  [1, 0, 0, 0, 0],
  [0, 0, 0, 1, 0],
  [0, 0, 0, 0, 0],
  [0, 0, 1, 0, 0],
  [0, 0, 0, 0, 0],
];

const simpleWin = [
  [1, 1, 1, 1, 1],
  [1, 1, 0, 1, 1],
  [1, 0, 0, 0, 1],
  [1, 1, 0, 1, 1],
  [1, 1, 1, 1, 1],
];

function newGame(startConfig) {
  document.querySelector("#youWon").classList.add("invisible");

  startConfig.forEach((row, rowNo) => {
    row.forEach((cell, cellNo) => {
      // Reset table to white
      document.querySelector(`tr[data-row="${rowNo}"] td[data-cell="${cellNo}"]`).classList.remove("bg-red");
      
      if (cell === 1) document.querySelector(`tr[data-row="${rowNo}"] td[data-cell="${cellNo}"]`).classList.add("bg-red");
    });
  });
}

newGame(cellsToStartRed);

const cells = document.querySelectorAll("td[data-cell]");
cells.forEach((cell) => {
  cell.addEventListener("click", () => {
    const rowNo = parseInt(cell.parentNode.getAttribute("data-row"));
    const cellNo = parseInt(cell.getAttribute("data-cell"));

    cell.classList.toggle("bg-red");

    // Toggle adjacent cells
    if (cellNo > 0) document.querySelector(`tr[data-row="${rowNo}"] td[data-cell="${cellNo - 1}"]`).classList.toggle("bg-red");
    if (cellNo < cellsToStartRed[rowNo].length - 1) document.querySelector(`tr[data-row="${rowNo}"] td[data-cell="${cellNo + 1}"]`).classList.toggle("bg-red");
    if(rowNo > 0) document.querySelector(`tr[data-row="${rowNo - 1}"] td[data-cell="${cellNo}"]`).classList.toggle("bg-red");
    if(rowNo < cellsToStartRed.length - 1) document.querySelector(`tr[data-row="${rowNo + 1}"] td[data-cell="${cellNo}"]`).classList.toggle("bg-red");

    checkIfWon();
  });
});

function checkIfWon() {
  if ([...cells].every((cell) => cell.classList.contains("bg-red"))) {
    document.querySelector("#youWon").classList.remove("invisible");
  }
}
body {
  text-align: center;
  display: flex;
  justify-content: center;
}

table {
  /*border-radius: 10px;*/
  margin-top: 60px;
  border: 1px solid;
  background-color: lightcyan;
  box-shadow: 5px 5px 40px royalblue;
}

td {
  border: 1px solid;
  width: 40px;
  height: 40px;
}

p {
  font-weight: bold;
  font-size: 17px;
}

p span {
  color: red;
}

td {
  background-color: white;
}

.bg-red {
  background-color: red;
}

.invisible {
  display: none;
}
<body>
    <div class="container">
      <h2>Table game</h2>
      <p>Try to color all cells to <span onclick="newGame(simpleWin)">red</span></p>
      
      <div id="youWon" class="invisible">
        <h2>You won!</h2>
        <button onclick="newGame(cellsToStartRed)">New Game</button>
      </div>

      <table>
        <tbody>
          <tr data-row="0">
            <td data-cell="0" />
            <td data-cell="1" />
            <td data-cell="2" />
            <td data-cell="3" />
            <td data-cell="4" />
          </tr>
          <tr data-row="1">
            <td data-cell="0" />
            <td data-cell="1" />
            <td data-cell="2" />
            <td data-cell="3" />
            <td data-cell="4" />
          </tr>
          <tr data-row="2">
            <td data-cell="0" />
            <td data-cell="1" />
            <td data-cell="2" />
            <td data-cell="3" />
            <td data-cell="4" />
          </tr>
          <tr data-row="3">
            <td data-cell="0" />
            <td data-cell="1" />
            <td data-cell="2" />
            <td data-cell="3" />
            <td data-cell="4" />
          </tr>
          <tr data-row="4">
            <td data-cell="0" />
            <td data-cell="1" />
            <td data-cell="2" />
            <td data-cell="3" />
            <td data-cell="4" />
          </tr>
        </tbody>
      </table>
    </div>
</body>

A dynamic way to generate the table structure by manipulating the DOM is shown below:

const table = document.querySelector("table");
cellsToStartRed.forEach((row, rowNo) => {
    table.innerHTML += `<tr data-row="${rowNo}"></tr>`;

    row.forEach((cell, cellNo) => {
      document.querySelector(`tr[data-row="${rowNo}"]`).innerHTML += `<td data-cell="${cellNo}"></td>`;

      if (cell === 1) document.querySelector(`tr[data-row="${rowNo}"] td[data-cell="${cellNo}"]`).classList.add("bg-red");
    });
});

This approach enables a flexible table size based on the provided data.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Testing for packet loss using JavaScript

Do you know if there is a method in JavaScript to determine packet loss from the client side using AJAX, XMLHttpRequest, or any other approach? Your assistance is greatly appreciated. ...

I encountered no response when attempting to trigger an alert using jQuery within the CodeIgniter framework

Jquery/Javascript seem to be causing issues in codeigniter. Here is what I have done so far: In my config.php file, I made the following additions: $config['javascript_location'] = 'libraries/javascript/jquery.js'; $config['javas ...

I have successfully converted an SQL Join query into JSON, but now I am unsure of how to interact with the

I recently ran an SQL Join on two tables and obtained the following results: _____People_____ name: "Jane" age: 35 job_id: 1 _____Professions_____ job_id: 1 title: "Teacher" "SELECT * FROM People INNER JOIN Professions ON People.job_id = Professions.job ...

The command is failing to include functionality with the yarg npm package

I have been attempting to incorporate a command using yargs, however, after executing my code, the command does not seem to be added successfully. Below is the snippet of what I am attempting: const yargs = require('yargs') //create add command ...

Effortless gliding towards the left

I am looking to incorporate buttons for smooth horizontal scrolling within my container. Currently, the functionality is in place but I would like to enhance its smoothness. How can I improve the scrolling experience? Should I consider using a different p ...

Problem with the show/hide feature on jQuery. Automatically scrolls to the beginning of the page

On my website, I have successfully implemented two basic Show / Hide links that are working great. Here is the HTML code: <!DOCTYPE html> <html lang="en"> <head profile="http://gmpg.org/xfn/11"> <meta http-equiv="Content-Type" conte ...

Incorporating Chakra UI, what is the best way to display a modal box upon page load?

Is there a way to display a modal box when the page loads in Chakra UI? I have been searching through Chakra's documentation but couldn't find any information on this. import { useDisclosure, Modal, ModalOverlay, ModalContent, ...

Implementing a video background within a dynamic two-column layout, accompanied by text within a separate column

While viewing on a large screen with Bootstrap 5, everything looks good: https://i.sstatic.net/Vm6bH.png However, when I resize the screen, the text in the first column overflows onto the sections below instead of adjusting properly. https://i.sstatic.n ...

The vertexUv in three.js is currently undefined and needs to be

I'm currently facing an issue while trying to combine multiple meshes, one of which is created by inputting the vertices coordinates. This specific mesh is causing the following error: THREE.DirectGeometry.fromGeometry(): Undefined vertexUv 256 W ...

Is there a way to instruct Google to include my site in its index using Angular.js?

I am currently working on an angular.js app and have been following Google's guide for ajax-based applications. Here are the steps I have taken: Added meta tags <base href="/"> <meta name="fragment" content="!"> Configured angular.js ...

What are the steps to shift columns to the left within a table?

I need to adjust the alignment of the columns and also create a fixed size space between them. Currently, it appears like this: https://i.sstatic.net/F7Rqk.png My desired outcome is something similar to: https://i.sstatic.net/ALKa9.png CSS Code: .tabl ...

Customizing Vue: Implementing an automatic addition of attributes to elements when using v-on:click directive

We are currently working with single file Vue components and we're facing a challenge in our mousemove event handler. We want to be able to determine if the target element is clickable. Within our Vue templates, we utilize v-on directives such as: v- ...

Challenges with aligning Fontawesome stacks

I utilized the code example from Fontawesome's website to create a pair of stacked social media buttons and enclosed it in a div element to float them to the right side of the page. <div class="social-icons"> <span class="fa-stack fa-lg"> ...

Exploring the concept of 'Abstract classes' within the Svelte framework

As someone who is relatively new to Svelte and frontend development (with primary experience in Rust/C++/Python), I hope you can forgive me for asking what might seem like a basic question. My goal is to showcase different kinds of time-indexed data, with ...

Choose or deselect images from a selection

I am currently working on a feature for an album creation tool where users can select photos from a pool of images and assign them to a specific folder. However, I'm facing difficulty in selecting individual photos and applying customized attributes t ...

Access User Information from Facebook using Nativescript {N} oAuth Plugin

Developing an Android App with NativeScript I am in the process of creating an Android app using JavaScript and NativeScript. The initial page asks users to connect with Facebook, and my goal is to verify if an account exists with their email address. To ...

Error: The function exec in matchExpr[type] is not defined

I made some changes to Object.prototype and now I'm running into errors with jQuery's methods on selectors. The error message I'm getting is: Uncaught TypeError: matchExpr[type].exec is not a function Additionally, when trying to use $.po ...

Plot data points from geojson onto a leaflet map using markers

How can I efficiently import geoJson data (containing over 2000 coordinates) into a leaflet map? Below is a brief snippet of geo json: { "type": "FeatureCollection", "features": [ { "type": "Feature", "geometry": { ...

Auto-closing dropdown menus in the navbar of a Shiny app with Bootstrap

Is there a way to customize the behavior of a shiny navbarMenu so that when I click inside or outside it, the dropdown does not automatically hide? I have seen mentions of using data-bs-auto-close="false" in the Bootstrap documentation, has anyon ...

Error: Module not located in Custom NPM UI Library catalog

I have recently developed an NPM package to store all of my UI components that I have created over the past few years. After uploading the package onto NPM, I encountered an issue when trying to use a button in another project. The error message "Module no ...