I am creating a lottery card, but I have doubted myself.
I have attached some models, v2 and v3, I am using buttons, the idea is that each button has an identifier and an assigned value, in v2 I have thought that when the button is clicked on the mouse it stays red and that the buttons that correspond to spaces with nothing left disabled and with a black background.
In version 3 it occurred to me to create the cell and the button at the same time, and assign an identifier and a value, the value would come out of 9 arrays that have the values from 1 to 9, from 10 to 19, etc... they would be traversed from top to bottom, and previously so that it would not be sequential, the array is disordered and values are assigned, only 3 values would be taken and those of the first column would be traversed, then those of the second and so on.
Now I have to see how to assign it a value and an identifier, the identifier would be from 1 to 27, and the value will be the one that gets it from the array, I'm a bit stuck at this point now.
To disable buttons I have thought of putting 4 buttons with value 0, these values are assigned by going through the cardboard from left to right row by row and putting the value in random positions, the thing is that when the button has a value 0 the color is put in black and the button is deactivated, this would be done for the first two rows, and for the third it would be necessary to check that in the corresponding boxes all the buttons were not deactivated, that is, that the buttons in the two boxes above did not have value 0, if this happened the process would have to be repeated for the last row assigning values 0 until everything was fine.
to check a line or a bingo I think you could make a counter, for bingo every time you click it will increase a counter that would give it up to 15 and for line, having all the buttons enabled at once and having their identifier, add them up, if the buttons in the first row add up, for example, 180, and I add the clicked values of that row, and as they are clicked, the value of that button is added to an array, when this value reaches the value of the row line would be given (the button every time it was clicked should be disabled so that it could not be clicked twice).
Anyway, ideas to achieve a better approach are appreciated.
Enfoque del v.2
.button {width:30px;}
<tr>
<td><button class="button" id="uno">1</button></td>
<td><button class="button" id="dos">2</button></td>
<td><button class="button" id="tres">3</button></td>
<td><button class="button" id="cuatro">4</button></td>
<td><button class="button" id="cinco">5</button></td>
<td><button class="button" id="seis">6</button></td>
<td><button class="button" id="siete">7</button></td>
<td><button class="button" id="ocho">8</button></td>
<td><button class="button" id="nueve">9</button></td>
</tr>
<tr>
<td><button class="button" id="diez" >10</button></td>
<td><button class="button" id="once">11</button></td>
<td><button class="button" id="doce">12</button></td>
<td><button class="button" id="trece">13</button></td>
<td><button class="button" id="catorce">14</button></td>
<td><button class="button" id="qince">15</button></td>
<td><button class="button" id="dieciseis">16</button></td>
<td><button class="button" id="diecisiete">17</button></td>
<td><button class="button" id="dieciocho">18</button></td>
</tr>
<tr>
<td><button class="button" id="diecinueve">19</button></td>
<td><button class="button" id="veinte">20</button></td>
<td><button class="button" id="veintiuno">21</button></td>
<td><button class="button "id="veintidos">22</button></td>
<td><button class="button "id="veintitres">23</button></td>
<td><button class="button" id="veinticuatro">24</button></td>
<td><button class="button" id="veinticinco">25</button></td>
<td><button class="button" id="veintiseis">26</button></td>
<td><button class="button" id="veintisiete">27</button></td>
</tr>
</table>
<script>
document.getElementById("uno").onclick = function(){
this.style.backgroundColor ="red";
};
</script>
-------------------------
v3 Approach
<style>
#div1 {margin:10px;font-size:1.25em;}
table {border-collapse:collapse;border:1px solid #7f7f7f;background-color: white}
td {border:1px solid #7f7f7f;width:50px;height:50px;text-align:center;}
button{width: 50px;height:50px;background-color: white;border: none;}
</style>
<div id="div1"></div>
<script>
function crearCarton() {
var div1 = document.getElementById('div1');
var carton = document.createElement("table");
var Array1=[1,2,3,4,5,6,7,8,9];
var Array2=[10,11,12,13,14,15,16,17,18,19];
var Array3=[20,21,22,23,24,25,26,27,28,29];
var Array4=[30,21,32,33,34,35,36,37,38,39];
var Array5=[40,41,42,43,44,45,46,47,48,49];
var Array6=[50,51,52,53,54,55,56,57,58,59];
var Array7=[60,61,62,63,64,65,66,67,68,69];
var Array8=[70,71,72,73,74,75,76,77,78,79];
var Array9=[80,81,82,83,84,85,86,87,88,89];
var Array10=[90,91,92,93,94,95,96,97,98,99];
for (var i = 1; i < 4; i++) {
var fila = document.createElement("tr");
for (var j = 0; j < 10; j++) {
var columna = document.createElement("td");
var boton=document.createElement("button");
columna.appendChild(boton);
fila.appendChild(columna);
}
carton.appendChild(fila);
}
div1.appendChild(carton);
creaOrdenaArray1(Array3);
}
function creaOrdenaArray1(Array){
Array.sort(function(a, b){return 0.5 - Math.random()});
}
window.onload=crearCarton;
As I told you in my comments, your idea seemed interesting to me and that motivated me to look for a solution.
I will try to explain step by step the process to get the solution. It will be quite long.
ISSUE
You want to create a lottery or bingo card, with the following characteristics:
With these specifications, we are going to create our lottery card. I hope I haven't left anything out, and that these are the OP's requirements.
SOLUTION
In your question you have 2 layouts, one where you create a table manually using HTML, and the other where you generate the table using JS. We will go in the second direction, since it is more efficient and less code is written.
First of all we are going to create our HTML template, it will be just that, a template on which we are going to dump our cardboard generated in Javascript.
The code for your HTML template is only going to include one element
div
with theid="carton"
.That's all in HTML, obviously if you want to add a title and other design elements then that's another thing.
Second, I'll add a style sheet, called
carton.css
that will give the cardboard a little style, nothing complicated, it can be improved but I'm not going to go into that now.Our style sheet will look like this:
Finally, I am going to create 2 JS files, one will have the logic to generate the card, and the other will have the logic of the game (change selected cell color, call bingo when completing a row).
The most complicated, in my opinion, is the logic to position 12 boxes randomly on the cardboard, respecting the specifications.
We will start with the problem of generating the cardboard, it will be generated when loading the page. With that we already have an idea, then it can be adapted to generate the cardboard using a button or another element. Our logic will be stored in a file called
generarCarton.js
We will create a function called
crearCarton(filas, columnas)
which will accept as parameters the number of rows and the number of columns. I do it like this to have a reusable code.Our function will simply have 5 statements, it is something like a stack of calls to different utility functions that will help us create the cardboard.
The code is the following:
As you can see, we create an instance of our element
div
since we are going to write our cardboard there.In addition, we call 4 functions:
generarValores(inicio, fin)
,llenarTabla(valores, filas, columnas)
,taparTabla(tabla, filas, columnas)
andescribirCarton(tabla, carton, filas, columnas)
. Each function will perform a specific task as its name indicates.The function
generarValores(inicio, fin)
returns aarray
number of ordered numbers in a range frominicio
tofin
. I haven't added error checking (cases likeinicio >= fin
) I'll leave that to homework, for this example I'll omit errors of that type.Our function is as follows:
Something quite simple if you will, and it is also reusable.
The second function we are going to create is called
llenarTabla(valores, filas, columnas)
. As its name indicates, it is in charge of filling a dimension tablefilas x columnas
with values that will be chosen randomly from the set ofvalores
.Our function will return a table filled with random values, and use a utility function to pick the value randomly, and avoid repetition. The function is as follows:
As you can see, we are going to fill a
array
multidimensional, which is nothing more than onearray
that contains otherarray
different ones, all of the same dimension. In this function we make a call to another function:escogerValor(valores)
, which will take care of choosing a value randomly from the set of values. This function returns aarray
that contains the chosen value and thearray
values from which the chosen value has been subtracted, thus guaranteeing the uniqueness of each value that we will assign to the cells of the table.The function
escogerValor(valores)
, as its name implies, picks a value at random from the set of values. This function is as follows:As can be seen in this function, we choose a random index
array
of the values. Remember that in JS the indices of aarray
go from0
toarray.length - 1
, that is why we multiplyMath.random()
byvalores.length - 1
. Since values contains (in this case) 99 elements, this will produce (float) numbers in the range 0.00000... to 98.00000..., and being floats, we simply useMath.round()
to capture the integer part of those numbers.Having the index chosen randomly, we store the value that corresponds to said index in our variable
valor
.We then remove the element corresponding to that index from our
array
of values, using thesplice()
object's methodArray
.Finally we return the selected value and the
array
one that contains the rest of the values and that does not include the already selected value. That is what guarantees uniqueness.An example of how our table looks:
Now we have our table with randomly chosen numbers, we have to "cover" 12 cells randomly. For this we use a function called
taparTabla(tabla, filas, columnas)
. This function is the most specific to this program, as it has been designed with the OP's specifications in mind. Therefore, although it can be adapted for other situations, it cannot be reused in case the number of rows, columns or number of elements to "cover" changes.Our function is as follows:
This function is quite elaborate, but best of all, I can reuse the functions already created before. It is always a good practice to be able to write functions, methods, classes that can be reused. It is the DRY principle, which personally, I learned by writing a lot of code, without any guidance, realizing that I should always think about reusing any method or object created, so as not to write such repetitive things. Over the years, I read a book on OOP, and I clearly understood the DRY principle, which I had been applying without knowing that it was a principle. (DRY is an acronym in the English language that means: Don't Repeat Yourself)
In our function, the first thing we have is the number of caps per row, which we store in a variable with a suggestive name.
Then we initialize a
array
so-called caps, which will contain in turn 3array
with the indices of the cells that will be capped.Then we generate the values of the indices. Since each row has
n
columns, and we know the number of columns, we use thegenerarValores()
. Note that the parameterinicio
is zero, and the parameterfinal
iscolumnas - 1
Now we will use a loop that will repeat (in this case) 3 times (from
0
tofilas -1
), and in each iteration we will create aarray
callfila
that will contain the indices of the cells that we are going to cover.To fulfill the conditions (4 cells covered per row and all columns must have at least 1 cell covered and maximum 2 cells covered) we will use a nested loop that will be executed 4 times (from
0
tocantTapasFila - 1
)Now we will use a bit of logic and mathematics to understand the process.
Let's remember that our
array
of values contains indices (from 0 to 8 in this case)In each iteration of our nested loop, we are going to choose a value (using our function
escogerValor()
) from the 9 possible values that we have previously generated.So, in the first iteration of row (
i = 0
), we pick 4 values, and extract them from ourarray
of values.Now for the second iteration (
i = 1
) ourarray
value only contains 5 elements. We again choose 4 elements, and extract them from ourarray
values.For the last iteration (
i = 2
) ourarray
of elements contains 1 single element. This must be assigned directly, to ensure that each column contains at least 1 blank cell. And since the previously chosen indices are not repeated, we can freely choose the 3 remaining values, since they will be unique for the row and it does not matter if they are repeated in the column, since it would only be repeated 2 times, which is the maximum allowed.An example of a run to better understand the process would be the following:
i = 0
),valores = [0, 1, 2, 3, 4, 5, 6, 7, 8]
.tapasFila = []
tapasFila
intapas
, the chosen values: [0, 3 , 8, 4]i = 1
),valores = [1, 2, 5, 6, 7]
.tapasFila = []
tapasFila
intapas
, the chosen values: [7, 2, 5, 6]i = 2
),valores = [1]
.tapasFila = []
tapasFila
array
with values (from 0 to 9)tapasFila
intapas
, the chosen values: [1, 4, 8, 2].At the end of this cycle, we have a
array
calltapas
that contains the indexes of the rows that we are going to "cover" in our table.To do this, we loop through our table and every time we go through the indicated index, we put the cell in
0
. Per the OP's spec. This will then allow us to color the cell black. With this we already have the table with the covered values.An example of how our table would look without coloring the cells:
Finally we have to write the table in HTML and color it as necessary.
To achieve this we will use the function
escribirCarton(tabla, carton, filas, columnas)
, to which we pass the necessary elements to perform the task. Our function is as follows:As we can see, our function goes through the table that we have passed as a parameter and generates the appropriate HTML code.
When a cell is zero ("covered"), the appropriate style (
background: black;
) is added, a construct is added to the rest of the cellsid
by means of the corresponding row and column number, therefore eachid
will be unique. The format ofid
is clear:filaNcolM
, where N and M correspond to the position indices of the cell.Additionally, to each uncovered cell, a class is added
active
and a cursor style is markedpointer
, so that the cell looks like a link or hyperlink when hovering over it with the mouse.In this way our table is ready to play.
Now we will write the logic of the game. We will do this in a different file, which we will call playBingo.js The content of our file is as follows:
Como podemos apreciar en nuestro código, lo primero que hacemos es instanciar un
array
que contiene las celdas de números activas. Para eso usamos el selectordocument.querySelectorAll('td.active')
. Luego inicializamos tresarray
llamadosfila0, fila1, fila2
que servirá para almacenar los valores escogidos en nuestro cartón según la fila a la que pertenezcan.Aqui hay una posibilidad para optimizar, pero para este ejemplo lo dejaré de esta forma. La optimización la dejo de tarea.
Usaremos un bloque condicional
switch ... case
para ir almacenando los valores seleccionados (clicados por el usuario) en el correpondientearray
.Cada vez que se hace clic en una celda, nuestro programa verifica si el elemento existe en el
array
correspondiente. Si el elemento existe entonces lo sacamos delarray
, en cambio si no existe lo agregamos. Esto tiene como objetivo permitir que un usuario deshaga la selección realizada, en caso de equivocación.Por útlimo, se verifica el tamaño de cada
array
, si alguno contiene 5 elementos entonces se ha completado una línea y se puede cantar 'BINGO'.Esta sería una manera de completar la tarea. No es nada muy elaborado, pero merece la pena revisar cada parte del código y entender el porqué de cada cosa.
Una muestra mínima de lo que se puede hacer con HTML, CSS y Javascript y un editor de texto.
Espero que sea la respuesta que buscabas.
Below I leave a complete implementation so you can see how it works: