我正在制作一张彩票卡,但我怀疑自己。
我附加了一些模型,v2 和 v3,我正在使用按钮,想法是每个按钮都有一个标识符和一个分配的值,在 v2 中,我认为当在鼠标上单击按钮时它会保持红色并且按钮对应于没有任何被禁用且具有黑色背景的空间。
在版本 3 中,我想到同时创建单元格和按钮,并分配一个标识符和一个值,该值将来自 9 个数组,其值从 1 到 9,从 10 到 19等等……它们会从上到下遍历,之前为了不连续,数组是无序的并赋值,只会取3个值,第一列的值被遍历,然后是第二个,依此类推。
现在我必须看看如何为它分配一个值和一个标识符,标识符将从 1 到 27,而该值将是从数组中获取它的值,我现在有点卡在这一点上。
要禁用按钮,我曾想过放置 4 个值为 0 的按钮,这些值是通过从左到右逐行遍历纸板并将值放在随机位置来分配的,事情是当按钮有值时0 颜色设置为黑色并且按钮被停用,这将在前两行完成,对于第三行,有必要检查相应框中的所有按钮都没有被停用,也就是说,上面两个框中的按钮没有值 0,如果发生这种情况,则必须为最后一行分配值 0 重复该过程,直到一切正常。
要检查一条线或宾果游戏,我认为您可以制作一个计数器,对于宾果游戏,每次单击它都会增加一个计数器,将其增加到 15 和对于线,同时启用所有按钮并具有它们的标识符,添加把它们加起来,如果第一行的按钮加起来,比如180,我把那一行的点击值加起来,当它们被点击的时候,那个按钮的值被加到一个数组中,当这个值达到行行的值将被给出(每次单击按钮时都应禁用,以便无法单击两次)。
无论如何,我们赞赏实现更好方法的想法。
Enfoque del v.2
.button {宽度: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 方法
<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;
正如我在评论中告诉你的那样,你的想法对我来说似乎很有趣,这促使我寻找解决方案。
我将尝试逐步解释获得解决方案的过程。会很长。
问题
您想要创建具有以下特征的彩票或宾果卡:
有了这些规范,我们将创建我们的彩票卡。我希望我没有遗漏任何东西,这些是 OP 的要求。
解决方案
在您的问题中,您有两种布局,一种是使用 HTML 手动创建表格,另一种是使用 JS 生成表格。我们将朝着第二个方向前进,因为它更高效并且编写的代码更少。
首先,我们将创建我们的 HTML 模板,它只是一个模板,我们将在其上转储用 Javascript 生成的纸板。
您的 HTML 模板的代码只会包含一个
div
带有id="carton"
.这就是 HTML 中的全部内容,显然,如果您想添加标题和其他设计元素,那就是另一回事了。
其次,我将添加一个样式表,名为
carton.css
这将使纸板有一点样式,没有什么复杂的,它可以改进,但我现在不打算深入。我们的样式表将如下所示:
最后,我要创建2个JS文件,一个有生成卡片的逻辑,另一个有游戏的逻辑(更改选中的单元格颜色,完成一行时调用宾果游戏)。
在我看来,最复杂的是在纸板上随机放置 12 个盒子的逻辑,遵守规范。
我们将从生成纸板的问题开始,它会在加载页面时生成。有了这个我们已经有了一个想法,然后它可以适应使用按钮或其他元素生成纸板。我们的逻辑将存储在一个名为
generarCarton.js
我们将创建一个名为的函数,该函数
crearCarton(filas, columnas)
将接受行数和列数作为参数。我这样做是为了有一个可重用的代码。我们的函数将只有 5 个语句,它类似于对不同实用函数的调用堆栈,可以帮助我们创建纸板。
代码如下:
正如你所看到的,我们创建了一个元素的实例,
div
因为我们将在那里写我们的纸板。此外,我们调用 4 个函数:
generarValores(inicio, fin)
、llenarTabla(valores, filas, columnas)
和。正如其名称所示,每个函数都将执行特定的任务。taparTabla(tabla, filas, columnas)
escribirCarton(tabla, carton, filas, columnas)
该函数
generarValores(inicio, fin)
返回范围从到的array
多个有序数字。我没有添加错误检查(例如),我将把它留给家庭作业,在本例中,我将省略该类型的错误。inicio
fin
inicio >= fin
我们的功能如下:
如果你愿意的话,这很简单,而且它也是可重复使用的。
我们将要创建的第二个函数称为
llenarTabla(valores, filas, columnas)
. 正如它的名字所表明的,它负责filas x columnas
用将从集合中随机选择的值填充维度表valores
。我们的函数将返回一个填充随机值的表,并使用实用函数随机选择值,并避免重复。功能如下:
正如你所看到的,我们将填充一个
array
多维,它只不过是一个array
包含其他array
不同维度的多维,所有这些都是相同的维度。在这个函数中,我们调用另一个函数:escogerValor(valores)
,它将负责从一组值中随机选择一个值。此函数返回一个array
包含所选值和array
已减去所选值的值,从而保证我们将分配给表格单元格的每个值的唯一性。escogerValor(valores)
顾名思义,函数从一组值中随机选取一个值。这个函数如下:从这个函数中可以看出,我们选择了一个随机索引
array
值。请记住,在 JS 中 a 的索引array
从0
到array.length - 1
,这就是我们乘以Math.random()
的原因valores.length - 1
。由于值包含(在这种情况下)99 个元素,这将产生 0.00000... 到 98.00000... 范围内的(浮点)数字,并且作为浮点数,我们只是Math.round()
用来捕获这些数字的整数部分。随机选择索引后,我们将与所述索引对应的值存储在变量中
valor
。然后,我们使用对象的方法从我们
array
的值中删除与该索引对应的元素。splice()
Array
最后,我们返回选择的值和
array
包含其余值且不包含已选择值的值。这就是保证唯一性的原因。我们的表格的外观示例:
现在我们有了随机选择数字的表格,我们必须随机“覆盖”12 个单元格。为此,我们使用了一个名为
taparTabla(tabla, filas, columnas)
. 此功能是该程序最具体的,因为它的设计考虑了 OP 的规范。因此,虽然它可以适应其他情况,但在“覆盖”的行数、列数或要“覆盖”的元素数发生变化的情况下,它不能重复使用。我们的功能如下:
这个函数非常精细,但最重要的是,我可以重用之前已经创建的函数。能够编写可重用的函数、方法和类始终是一个好习惯。就是 DRY 原则,我个人是在没有任何指导的情况下,通过编写大量代码学到的,意识到我应该始终考虑重用任何创建的方法或对象,以免编写这种重复的东西。多年来,我读了一本关于 OOP 的书,我清楚地理解了 DRY 原则,我一直在应用它,但并不知道它是一个原则。(DRY 是英语的首字母缩写词,意思是:不要重复自己)
在我们的函数中,我们拥有的第一件事是每行的大写字母数量,我们将其存储在一个带有暗示名称的变量中。
然后我们初始化一个
array
所谓的 caps,它将依次包含 3array
和将被封顶的单元格的索引。然后我们生成索引的值。由于每一行都有
n
列,并且我们知道列数,所以我们使用generarValores()
. 注意参数inicio
为零,参数final
为columnas - 1
现在我们将使用一个循环(在这种情况下)重复 3 次(从
0
到filas -1
),并且在每次迭代中,我们将创建一个array
调用,该调用fila
将包含我们将要覆盖的单元格的索引。为了满足条件(每行覆盖 4 个单元格,所有列必须至少覆盖 1 个单元格,最多覆盖 2 个单元格),我们将使用一个嵌套循环,该循环将执行 4 次(从
0
到cantTapasFila - 1
)现在我们将使用一些逻辑和数学来理解这个过程。
让我们记住,我们
array
的值包含索引(在这种情况下从 0 到 8)在嵌套循环的每次迭代中,我们
escogerValor()
将从之前生成的 9 个可能值中选择一个值(使用我们的函数)。因此,在第 ( ) 行的第一次迭代中
i = 0
,我们选择了 4 个值,并从我们的值中提取它们array
。现在对于第二次迭代 (
i = 1
),我们的array
值仅包含 5 个元素。array
我们再次选择 4 个元素,并从我们的值中提取它们。对于最后一次迭代 (
i = 2
),我们array
的元素包含 1 个单个元素。这必须直接分配,以确保每列至少包含 1 个空白单元格。并且由于之前选择的索引不重复,我们可以自由选择剩余的 3 个值,因为它们对于行是唯一的,并且它们是否在列中重复并不重要,因为它只会重复 2 次,这是允许的最大值。为了更好地理解该过程的运行示例如下:
i = 0
),valores = [0, 1, 2, 3, 4, 5, 6, 7, 8]
。tapasFila = []
tapasFila
entapas
, los valores escogidos: [0, 3 , 8, 4]i = 1
),valores = [1, 2, 5, 6, 7]
.tapasFila = []
tapasFila
entapas
, los valores escogidos: [7, 2, 5, 6]i = 2
),valores = [1]
.tapasFila = []
tapasFila
array
con valores (del 0 al 9)tapasFila
entapas
, los valores escogidos: [1, 4, 8, 2].Al finalizar este ciclo, tenemos un
array
llamadotapas
que contiene los índices de las filas que vamos a "tapar" en nuestra tabla.Para hacerlo, recorremos nuestra tabla y cada vez que pasemos por el índice indicado, ponemos la celda en
0
. Según la especificación del OP. Esto nos va a permitir luego colorear la celda de negro. Con esto ya tenemos la tabla con los valores tapados.Un ejemplo de cómo quedaría nuestra tabla sin colorear las celdas:
Por último nos queda escribir la tabla en HTML y colorear según sea necesario.
Para lograrlo usaremos la función
escribirCarton(tabla, carton, filas, columnas)
, a la cual le pasamos los elementos necesarios para realizar la tarea. Nuestra función queda de la siguiente manera:Como podemos observar, nuestra función recorre la tabla que hemos pasado como parámetro y genera el código HTML adecuado.
Cuando se consigue una celda en cero ("tapada") se agrega el estilo adecuado (
background: black;
), al resto de las celdas se le agrega unid
construido mediante el número de fila y columna correspondiente, por lo tanto cadaid
será único. El formato delid
es claro:filaNcolM
, donde N y M corresponden a los índices de posición de la celda.Adicionalmente, a cada celda no tapada, se le agrega una clase
active
y se marca un estilo de cursorpointer
, para que la celda parezca un enlace o hipervínculo al posicionar el ratón sobre ella.De esta forma nuestra tabla queda lista para jugar.
Ahora escribiremos la lógica del juego. Esto la haremos en un archivo diferente, al cual llamaremos jugarBingo.js El contenido de nuestro archivo es el siguiente:
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.
下面我留下一个完整的实现,这样你就可以看到它是如何工作的: