What is the best way to create a "tile-based board" for this game?

I am working on a project to create a board made up of tiles, but I am facing difficulty in filling up the entire board area. Currently, I have only managed to create 1 column of the board, as shown in the image. Can someone guide me on how to fill the entire board and make each tile clickable for interaction?

body {
    font-family: Arial, Helvetica, sans-serif;
    text-align: center; 
}

hr {
    width: 500px;
}

#board {
    width: 1000px;
    height: 1000px;
    float: center;
    display: grid;
    background-color: rgb(126, 124, 122);
    border: 6px solid rgb(0, 0, 0);
}

.tile {
    width: 200px;
    height: 200px;
    border: 5px solid bisque;
    border-radius: 10%;
    font-size: 40px;
    font-weight: bold;
    display: flex;
    justify-content: center;
    align-items: center;
}

.picker {
    width: 100px;
    height: 100px;
    border: 5px solid bisque;
    margin: 0 auto;
    border-radius: 10%;
    align-content: left;
    align-self: left;
}

.tile {
    background-color: rgb(255, 255, 255);
    color: black;
}

.float-child {
    width: 10%;
    padding: 10px;
    border: 2px solid rgb(0, 0, 0);
    vertical-align: left;    
}
<body>
  <h1>Play-Color</h1>
  <hr>
  <div class="game">
    <div class="float-child">
      <button class="picker" style="background-color: red"></button>
      <h4>count = 0</h4>
      <br>
      <button class="picker" style="background-color: blue"></button>
      <h4>count = 0</h4>
      <br>
      <button class="picker" style="background-color: green"></button>
      <h4>count = 0</h4>
      <br>
      <button class="picker" style="background-color: yellow"></button>
      <h4>count = 0</h4>
      <br>
      <button class="picker" style="background-color: grey"></button>
      <h4>count = 0</h4>
      <br>
      <button class="picker"></button>
      <br>
    </div>
    <div id="board" class="float-child" style="position:relative; left:900px; top:-1000px" >
      <button class="tile"></button>
      <button class="tile"></button>
      <button class="tile"></button>
      <button class="tile"></button>
      <button class="tile"></button>
    </div>
    </div>
  </div>
</body>

[2]UpdatedImage

........................................................................................................................................................................................

Answer №1

There are numerous steps involved in achieving the desired outcome. Typically, I wouldn't write code like this on a platform such as Stack Overflow. However, I decided to do so for fun. Also, it's important to note that you shouldn't expect others to develop an entire game for you without any compensation!

For more information, refer to the comments provided within the HTML, CSS, and JS code snippets.

  1. To create a color selection mechanism, using radio-buttons seems like the most efficient solution. Radio buttons inherently allow only one choice to be selected:
    <input type="radio" name="color" value="color-name" id="color-name">
  2. To ensure that there is always a color selected initially without breaking the game, use the 'checked' attribute with one of the colors:
    <input type="radio" ... checked>
  3. Hide the checkboxes to make them invisible and not take up any space using CSS:
    input { display: none; }
  4. Add the color as a visual box by incorporating a <label>. Clicking on the label should select the appropriate radio button:
    <label for="color-name">
  5. Color the label according to your preference. Additionally, assign a CSS class to represent the same color for painting purposes:
label[for=color-name],
.color-name {
  background-color: color-name;
}
  1. Create a grid structure either through JavaScript or hardcode it into the HTML. Since explaining the JavaScript approach would be time-consuming, I opted for the latter. In my case, I utilized a grid-container:
    <div class="game-board">
    . Subsequently, I added 25 child elements:
    <div class="card"></div>
    . To establish a 5x5 grid, I employed CSS to define 5 columns:
.game-board {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
}
  1. As previously mentioned in the comments, buttons don't need to be clickable for JavaScript functionality. The labels of the radio buttons already serve this purpose. You can execute a script upon clicking even if it isn't inherently clickable by utilizing the EventListener to detect a click-event via JavaScript:
element.addEventListener('click', e => {
  // statements
});
  1. To selectively target the grid-cards rather than the container or other content, verify if the clicked element contains a specific class:
if (e.target.classList.contains('card')) {
  // statements
}
  1. If the grid-card already possesses a CSS class representing a color, eliminate any conflicting classes that might interfere with proper functioning:
    e.target.className = ''
  2. Subsequently, re-add the 'card' class after removing potential conflicting classes:
    e.target.classList.add('card');
  3. Implement a cleaner logic using a switch-case-statement instead of multiple if/else clauses. This statement evaluates the selected radio button and applies the corresponding class to the clicked element to paint it with the chosen color:
    e.target.classList.add('color-name');

EDIT

  1. To include a counter, you can utilize the JavaScript length method:

    document.querySelectorAll('.game-board .color-name').length
    . This function calculates the number of elements containing a specific class.

  2. Display the count using the innerHTML property:

    element.innerHTML = document.querySelectorAll('.game-board .color-name').length

var board = document.querySelector('.game-board')

// eventListener to listen to click events on the game board
board.addEventListener('click', e => {
  console.clear();
  // checks if a card and not the agme baord itself was clicked on
  if (e.target.classList.contains('card')) {
    const card = e.target.classList;
    // checks which color has been selected
    var color = document.querySelector('.color-picker input:checked').value;
    
    // removes all classes from the clicked on element to allow re-painting
    e.target.className = '';
    // re-adds the "card" class to the clicked element
    card.add('card');
    
    // switch statement to add the class with the selected color to paint the grid-card
    switch (color) {
      case "red":
        card.add('red');
        break;
      case "blue":
        card.add('blue');
        break;
      case "green":
        card.add('green');
        break;
      case "yellow":
        card.add('yellow');
        break;
      case "gray":
        card.add('gray');
        break;
    }
    
    // color-counter
    var countRed = document.querySelectorAll('.game-board .red').length,
        countBlue = document.querySelectorAll('.game-board .blue').length,
        countGreen = document.querySelectorAll('.game-board .green').length,
        countYellow = document.querySelectorAll('.game-board .yellow').length,
        countGray = document.querySelectorAll('.game-board .gray').length;
        
    // displaying the counter
    var labelRed = document.querySelector('#count-red span'),
        labelBlue = document.querySelector('#count-blue span'),
        labelGreen = document.querySelector('#count-green span'),
        labelYellow = document.querySelector('#count-yellow span'),
        labelGray = document.querySelector('#count-gray span');
    labelRed.innerHTML = countRed;
    labelBlue.innerHTML = countBlue;
    labelGreen.innerHTML = countGreen;
    labelYellow.innerHTML = countYellow;
    labelGray.innerHTML = countGray;    
  }
});
/* aligning the color picker and game board next to each other */
body {
  margin: 0;
  padding: 10px;
  box-sizing: border-box;
  display: flex;
  gap: 10px;
  min-height: 100vh;
}


/* box for the color */
.color-picker {
  border: 1px solid black;
  display: flex;
  flex-direction: column;
  padding: 5px 30px;
  gap: 10px;
}

/* hides the radio button */
.color-picker > input {
  display: none;
}

/* creatign a visual border to see what color has been selected */
input:checked + label {
  border: 3px solid black;
}

/* setting a "color-box" to the radio-button */
.color-picker > label {
  display: block;
  box-sizing: border-box;
  aspect-ratio: 1 / 1;
  min-width: 50px;
}

/* settign the color of the color picker and classes for painting */
label[for=red],
.red {
  background-color: red;
}

label[for=blue],
.blue {
  background-color: blue;
}

label[for=green],
.green {
  background-color: green;
}

label[for=yellow],
.yellow {
  background-color: yellow;
}

label[for=gray],
.gray {
  background-color: gray;
}

/* game board that creates a board of 5x5 with equal dimensions */
.game-board {
  flex-grow: 1;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  grid-gap: 5px;
}

/* Setting the grid-cards to be squares */
.game-board > .card {
  aspect-ratio: 1 / 1;
  border: 1px solid red;
  border-radius: 5px;
  display: flex;
  justify-content: center;
  align-items: center;
}

/* To make the grid-cards and label appear like buttons on hover */
.color-picker > label:hover,
.card:hover {
  cursor: pointer;
}
<!-- Letting you select the color -->
<div class="color-picker">
  <input type="radio" name="color" value="red" id="red" checked>
  <label for="red"></label>
  <div id="count-red">Count: <span>0</span></div>
  <input type="radio" name="color" value="blue" id="blue">
  <label for="blue"></label>
  <div id="count-blue">Count: <span>0</span></div>
  <input type="radio" name="color" value="green" id="green">
  <label for="green"></label>
  <div id="count-green">Count: <span>0</span></div>
  <input type="radio" name="color" value="yellow" id="yellow">
  <label for="yellow"></label>
  <div id="count-yellow">Count: <span>0</span></div>
  <input type="radio" name="color" value="gray" id="gray">
  <label for="gray"></label>
  <div id="count-gray">Count: <span>0</span></div>
</div>

<!-- The game board as a grid -->
<div class="game-board">
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
</div>

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

How to Create a DataTable Responsive Feature Where All Columns Collapse on Click, Except the Last One?

I am currently utilizing the DataTables library to generate a responsive table. I am aiming to create a feature where all columns in the DataTable can toggle between collapse and expand states when clicked, with the exception of the last column. Below is a ...

Is there a way for me to identify the scrolling height and dynamically adjust the title using jQuery?

I am in the process of creating a list of shops from different countries for my website. I want to implement a feature that detects when the user has scrolled to a specific area so I can update the title at the top accordingly. My idea is to assign classe ...

No assets detected in sails.js

Recently, I began a new sails project using 'sails new project --linker'. Initially, everything was functioning correctly but today I encountered a problem. Every time I start the server with 'sails lift', I now receive a 404 error for ...

Ways to resolve the issue of code not relocating the channel within a specific

The script I wrote to create a new category and channel produced an error message: TypeError: Cannot read property 'hasOwnProperty' of undefined. The issue occurs when the channel is not properly placed within the category. Here is the code snipp ...

Obtaining the value of an input field in HTML

I am currently working on a text input field that triggers a JavaScript function when a numeric value is entered. <input type="text" value="key" ng-keypress="submit(key)" ng-model="pager.page"/> Controller $scope.submit = function (val) { ...

What is the best way to style the current element being targeted in React?

In my React application, I am trying to dynamically adjust the height of a textarea element based on its content. I want to achieve this by utilizing an 'onchange' listener to trigger a resize function. While I have successfully implemented the ...

Phase 2 "Loading" visual backdrop

I'm attempting to include a loading animation GIF in my Cycle 2 plugin. Is there a way to ensure that the GIF loads before the images? Right now, I have set my loading.gif as a background image. The issue is that the loading.gif isn't displaying ...

"Exploring ways to pass live data from the controller to the view in CodeIgniter for dynamic chart values

I currently have the following code where I am statically assigning values. Now, I need to dynamically retrieve values and display a chart. I want to populate the 'items' variable from the controller in the same format, and then display the chart ...

showing sections that collapse next to each other

I am currently designing a portfolio website using HTML, CSS, and vanilla JavaScript. I have implemented collapsing sections that expand when clicked on. However, the buttons for these sections are stacked vertically and I want to place them side by side. ...

Transmit and receive information between Javascript and Node.js through Express framework

Currently, I am utilizing the Express platform along with the Twilio Node.js SMS API and JavaScript to send text messages to my users. However, I am facing an issue in sending data through GET variables on the front-end and capturing those values with node ...

Ways to align various paragraphs within a single Bootstrap row

Looking to include notes on the right side of each input field? Check out this example I put together using a bootstrap layout. <head> <meta charset="utf-8"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4 ...

The Typescript module in question does not contain any exported components or functions related to

I've encountered an unusual issue while working on a React, Redux TypeScript application. It seems that after making some changes, one of the modules has stopped exporting its members. Here is the folder structure: src |---- components |---- contain ...

Trouble with value updating in PostgreSQL with NodeJs

var express = require('express'); var app = express(); var pg = require('pg'); var connectionString = "postgresql://postgres:sujay123@localhost:3001/redc"; app.use(express.static('public')); app.get('/index.h ...

Vue.js - Problem with loading image on screen

Although I have experience with React, I am currently facing the challenge of using Vue for a code assessment for the first time. My struggle lies in creating a reusable image component with WAI-ARIA accessibility. Despite my efforts, I cannot get the imag ...

Passing PHP loop values to JavaScript

In my current project, I made a decision to avoid using a database and instead opted for files and folders. Each folder in a directory is represented as a button, clicking on which displays a list of files within that folder on the screen. Now, my challeng ...

Determine if the object's value is present

My current JavaScript setup looks like this: var NAMES = []; function INFO(id,first,middle,last){ var newMap = {}; newMap[id] = [first, middle, last]; return newMap ; } Next, I have the following code block: for (var j = 0; j < NUMBER.leng ...

Broken image path in the Model-View-Controller framework

When using the jQuery DatePicker plugin in my MVC application, I face an issue with displaying a certain image for the Calendar pop-up. Here is the code snippet: $.datepicker.setDefaults({ showOn: "both", buttonImage: "../images/Calendar.png", ...

Vue.js fails to update view after file status changes

I am currently working with Vue.js and have the following code snippet: <div class="file has-name is-fullwidth is-light"> <label class="file-label"> <input class="file-input" ...

Utilizing d3 Charts in Angular 4 Framework

I need assistance with integrating a bar chart in an Angular 4 project, which includes HTML and TypeScript files as components. Can someone please provide guidance on this? The bar chart should show the increase in the number of employees each month, star ...

Issue with mediaelement in Angular 8: video playback does not display after 2 seconds

I'm encountering an issue with MediaElement js when trying to play videos in .m3u8 format within a slider containing multiple videos. Whenever I click on the play button for any video, only a 2-second clip is shown before the video disappears. Any as ...