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

Is the H1 tag styled differently when located within an article element? Additionally, what is the best way to style multiple paragraphs within a

What is the best and most effective way to style multiple paragraphs within a div or semantic tag, each with different styles? Also, I have noticed that when I include an h1 tag inside the article, it does not display at the expected size. Does anyone know ...

I am having trouble with $(this) in my jQuery click event handler

When I click my function, I want to change a parent element that contains this function. However, $(this) is not working. What could be the issue? function accountConfirm(message, title, yes_label, no_label, callback) { console.log($(this)); $(&qu ...

Error Module in Angular 1.4.2: $injector:modulerr

I have exhausted all the solutions available on StackOverflow and other sources, but none of them seem to work for me. I have ensured that all scripts are loaded properly. I am using Visual Studio 2015 and trying to create a menu using Mobile Angular Ver ...

Adding additional text within the paragraph will result in the images shifting backwards when utilizing flexbox

It seems like there might be something obvious that I'm missing here, but essentially my goal is to create a footer with 2 columns and 2 rows. In each column, there will be an icon (32x32) and 2 lines of text next to it. The issue I'm facing is ...

Browse through content without displaying the page title on the navigation bar and without the use of frames

When I sign into certain websites, I have noticed that the address displayed is often something like this: https://examplesite.com/access Even though all the links on the landing page are clickable and functional, their corresponding addresses never show ...

The error message states: `res.Send function is not recognized as a valid

Recently, I've been working on a function that goes like this: app.get('/counter', function (req, res) { console.log('/counter Request'); var counter = 0; fs.readFile(COUNTER_FILE_NAME, function(err, data) { c ...

I keep receiving the same error (ENOENT) for all npm commands

Currently, I am running windows 8.1 x64 with all the latest updates installed. I encountered an error while using nodejs version 8.9.1 when running the command "npm -v". As a result, I decided to uninstall this version and switch to version 8.9.3. However ...

"Troubleshooting problem: Table rendering incorrectly outside of its designated div

My table's CSS is giving me trouble, despite my attempts to fix it. You can see that the table is currently positioned outside of my div. What I want: The table needs to be contained within my "Logs" div. I believe displaying the data in one line ...

Create a website that can expand in size without relying on percentage values

At the moment, I am in the process of building a responsive website. The issue I am currently facing is that the layout for the responsive design (which was created by someone else and not me) has a fixed width of 745px. Obviously, this width does not acco ...

Access various results from a jQuery function

Is there a way to efficiently extract the values of petKeys and employeeKey using the jQuery functions provided below? var whenSelectDateFromCalendar = function () { initKeyValues(); petKeys = ? employeeKey = ? }; var initKeyValues = function ...

Node.js application experiencing bug with End of Line (EOL) not displaying correctly

I've encountered an issue with my node.js application that involves writing the following code: word_meaning = 'line 1' + os.EOL +'line 2'; When attempting to render this in an HTML file using the following code: <p> <% ...

Why is this basic HTML code not functioning as expected?

I attempted to combine HTML and JS to change the color of a box upon clicking it, but after reviewing the code multiple times, I am unable to pinpoint the issue. <!doctype html> <html> <head> </head> <body> <d ...

Is it possible to examine elements within Outlook?

Creating HTML emails can be quite the challenge, especially when trying to make them compatible with Outlook. Is there a method to inspect elements in Outlook similar to how we do on a browser's console? ...

Is it possible to modify a JavaScript array variable without having to refresh the page by utilizing Ajax?

Is it possible to update a JavaScript array variable without having to reload or refresh the page? I have an existing list of data in an array, and I retrieve additional data using PHP and Ajax. Now I want to add the new data obtained from PHP Ajax to th ...

Assistance needed in obtaining the ID of a specific table row using jQuery

Currently, I am working on an AJAX request using Jquery and PHP. The task involves looping through an array to generate a table. During each iteration, a new ID is assigned to the table row. When users click on the "read me" link, additional content is f ...

Using ng-pattern to validate that a text field does not conclude with a particular term

In this code snippet, I am attempting to prevent a textfield from ending with any of the specified letters in the $scope.pointPattern variable. $scope.pointPattern = /^(?!.*ess|ence|sports|riding?$)/; $scope.error = "not valid"; Upon executio ...

The visibility feature in knockout.js appears to be malfunctioning

I am relatively new to using knockout.js and I'm attempting to control the visibility of a label on a slider item based on a specific condition. Even when the condition is false, the label still appears. Any suggestions would be greatly appreciated. ...

Adjust the bootstrap switch component to be in the 'checked' state when the mode is set to Dark

I have stored a theme for my web application in the localStorage and I want to dynamically add the checked value to the Switch component if the mode is set to 'dark', or unchecked if the mode is 'light'. However, whenever I set the them ...

Tips for segmenting text into pages according to the dimensions of the viewport and the font style

Here's a puzzle for you. I have a horizontal slider that loads pages via Ajax, with pre-loading features to maintain smooth performance. Similar to Facebook Billboarding but with a slight twist. By determining the viewport size, I calculate boxSizeX a ...

Numerous routers available for enhancing functionality in an Ember application

Can an Ember app have multiple router.js files? By default, one router.js file will look like this: import Ember from 'ember'; import config from '../../config/environment'; var Router = Ember.Router.extend({ location: config.locat ...