【问题标题】:Styling a sudoku grid设计数独网格
【发布时间】:2013-11-10 21:34:36
【问题描述】:

我创建了一个数独拼图创建器/求解器,需要一些 CSS 帮助来设置它的样式。

通常它们的样式如下:

.

我正在使用的一些命名。

单元格 - 每个单元格都包含一个数字。

盒子 - 9 个盒子之一,每个盒子包含 3 x 3 个单元格

网格 - 整个 9x9 游戏区域。

我的 html 部分由我的 ruby​​ / Sinatra 应用程序生成(至少重复的 DIV 是),并且结构如下:

#game {
  margin-left: auto;
  margin-right: auto;
  width: 360px;
}
.cell input {
  display: inline-block;
  float: left;
  width: 40px;
  height: 40px;
  border-style: solid;
  border-width: 1px;
  text-align: center;
  font-size: 15px;
}
<form action="/" method="post">
  <div id="game">
    <div class="cell">
      <input name="cell[0]" type="text" maxlength="1" value=<%=val%>>
    </div>

    <div class="cell">
      <input name="cell[1]" type="text" maxlength="1" value=<%=val%>>
    </div>

    <!-- ... -->

    <div class="cell">
      <input name="cell[79]" type="text" maxlength="1" value=<%=val%>>
    </div>

    <div class="cell">
      <input name="cell[80]" type="text" maxlength="1" value=<%=val%>>
    </div>
  </div>
</form>

这使我可以创建基本的 9x9 网格,我的第一个单元格 (0) 在左上角,然后从左向右移动,一次一行,到右下角的最后一个单元格 (80)。

困难在于设置每个单元格的样式,以便网格不仅可以拆分为行和列,还可以拆分为 9 个更大的框。再次参考this grid

目前我有几个选择:

  1. 完全重写我的数独代码,以便我以不同的顺序绘制 DIV。将每个框包装在分组 DIV 中。这将使 CSS 相对简单。这将是一个重大变化,我真的不想走这条路。

  2. 手动标识每个单元格并为所有 81 个单元格编写相应的 CSS。比上面好多了,但还是有点痛,而且不是特别光滑。

我确实可以选择动态生成 CSS 样式(性能不是问题)。我正在寻找的是设计一种算法的帮助,该算法将确定(基于它的线性索引 0..80)每个单元格的样式。

例如,顶行 (0..8) 中的所有单元格将具有粗的上边框 (3px) 和细的下边框 (1px)。第 3 行 (18..26) 中所有单元格的底部将有一个粗边框,但这些单元格的顶部将有一个细边框。第一列中所有单元格的左侧将有一个粗边框,但这些单元格的右侧将有一个细边框。以此类推。

【问题讨论】:

    标签: html css ruby sinatra


    【解决方案1】:

    以下是 HTML5 CR 中 table element 部分中的示例的轻微修改,说明使用 colgroup 对列进行分组,使用 tbody 对行进行分组。通过这种分组,您可以在组周围设置与单元格周围不同的边框。

    <style>
    table { border-collapse: collapse; font-family: Calibri, sans-serif; }
    colgroup, tbody { border: solid medium; }
    td { border: solid thin; height: 1.4em; width: 1.4em; text-align: center; padding: 0; }
    </style>
    <table>
      <caption>Sudoku of the day</caption>
      <colgroup><col><col><col></colgroup>
      <colgroup><col><col><col></colgroup>
      <colgroup><col><col><col></colgroup>
      <tbody>
       <tr> <td>1 <td>  <td>3 <td>6 <td>  <td>4 <td>7 <td>  <td>9
       <tr> <td>  <td>2 <td>  <td>  <td>9 <td>  <td>  <td>1 <td>
       <tr> <td>7 <td>  <td>  <td>  <td>  <td>  <td>  <td>  <td>6
      <tbody>
       <tr> <td>2 <td>  <td>4 <td>  <td>3 <td>  <td>9 <td>  <td>8
       <tr> <td>  <td>  <td>  <td>  <td>  <td>  <td>  <td>  <td>
       <tr> <td>5 <td>  <td>  <td>9 <td>  <td>7 <td>  <td>  <td>1
      <tbody>
       <tr> <td>6 <td>  <td>  <td>  <td>5 <td>  <td>  <td>  <td>2
       <tr> <td>  <td>  <td>  <td>  <td>7 <td>  <td>  <td>  <td>
       <tr> <td>9 <td>  <td>  <td>8 <td>  <td>2 <td>  <td>  <td>5
    </table>
    

    【讨论】:

    • 表格中的数据可能比 DIV 中的数据更好,因此这是一个很好的解决方案。请参阅下面的我的实现(带代码)。
    【解决方案2】:

    通过结合Jukka K. Korpela's answer Mike's answer 并添加一点jQuery 魔法,我创建了两个解决方案。

    $(document).ready(function () {
        var data = [
            1, 0, 3, 6, 0, 4, 7, 0, 9, // 0x0
            0, 2, 0, 0, 9, 0, 0, 1, 0, // 0x1
            7, 0, 0, 0, 0, 0, 0, 0, 6, // 0x2
            2, 0, 4, 0, 3, 0, 9, 0, 8, // 1x0
            0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x1
            5, 0, 0, 9, 0, 7, 0, 0, 1, // 1x2
            6, 0, 0, 0, 5, 0, 0, 0, 2, // 2x0
            0, 0, 0, 0, 7, 0, 0, 0, 0, // 2x1
            9, 0, 0, 8, 0, 2, 0, 0, 5  // 2x2
        ];
    
        // Build page content.
        $('body').append($('<div>').addClass('wrapper')
            .append($('<div>').addClass('col')
              .append($('<h1>').html('First Method'))
              .append(generateSudokuGrid()))
            .append($('<div>').addClass('col')
              .append($('<h1>').html('Second Method'))
              .append(generateSudokuGrid2())));
    
        // Populate grids with data.
        $('table[class^="sudoku"]').each(function (index, grid) {
            populateGrid($(grid), data);
        });
    });
    
    function populateGrid(grid, data) {
        grid.find('td').each(function (index, td) {
            $(td).text(data[index] || '');
        });
    }
    
    /* First Method */
    function generateSudokuGrid(data) {
        return $('<table>').append(multiPush(3, function () {
            return $('<colgroup>').append(multiPush(3, function () {
                return $('<col>');
            }));
        })).append(multiPush(3, function () {
            return $('<tbody>').append(multiPush(3, function () {
                return $('<tr>').append(multiPush(9, function () {
                    return $('<td>');
                }));
            }));
        })).addClass('sudoku');
    }
    
    /* Second Method */
    function generateSudokuGrid2(data) {
        return $('<table>').append(multiPush(9, function () {
            return $('<tr>').append(multiPush(9, function () {
                return $('<td>');
            }));
        })).addClass('sudoku2');
    }
    
    function multiPush(count, func, scope) {
        var arr = [];
        for (var i = 0; i < count; i++) {
            arr.push(func.call(scope, i));
        }
        return arr;
    }
    /* First Method */
    table.sudoku {
        border-collapse: collapse;
        font-family: Calibri, sans-serif;
    }
    .sudoku colgroup, tbody {
        border: solid medium;
    }
    .sudoku td {
        border: solid thin;
        height: 1.4em;
        width: 1.4em;
        text-align: center;
        padding: 0;
    }
    
    /* Second Method */
    table.sudoku2 {
        border-collapse: collapse;
        font-family: Calibri, sans-serif;
    }
    .sudoku2 tr:nth-of-type(3n) {
        border-bottom: solid medium;
    }
    .sudoku2 td:nth-of-type(3n) {
        border-right: solid medium;
    }
    .sudoku2 td {
        border: solid thin;
        height: 1.4em;
        width: 1.4em;
        text-align: center;
        padding: 0;
    }
    
    /* Presentation Formatting [Ignore] */
    table[class^="sudoku"] {
      margin: 0 auto;
    }
    .wrapper {
      width: 100%;
    }
    .col {
      display: inline-block;
      width: 50%;
      text-align: center;
      margin: 0 auto;
      padding: 0;
    }
    &lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"&gt;&lt;/script&gt;

    【讨论】:

      【解决方案3】:

      我会按如下方式创建数独板:

      <section class="sudoku">
             <div class="sudoku-row">
                 <div class="sudoku-square">
                    <div class="cell"><a class="cell-value"></a></div>
                    <div class="cell"><a class="cell-value"></a></div>
                    <div class="cell"><a class="cell-value"></a></div>
                    <div class="cell"><a class="cell-value"></a></div>
                    <div class="cell"><a class="cell-value"></a></div>
                    <div class="cell"><a class="cell-value"></a></div>
                    <div class="cell"><a class="cell-value"></a></div>
                    <div class="cell"><a class="cell-value"></a></div>
                    <div class="cell"><a class="cell-value "></a></div> 
                </div>
      

      LESS 会是这样的

      @cell-size: 50px;
      .sudoku {
        margin: 70px auto;  
        width: 478px;
        background: #777;    
        border: 2px solid #000;
        box-shadow: 15px 15px 20px #111;
      
        .sudoku-row {    
          .sudoku-square {      
            float: left;
            border: 1px solid #000;
      
            .cell:nth-child(3n+1) {
              clear: both;
            }
            .cell {
              float: left;        
              position: relative;
              height: @cell-size;
              width: @cell-size;
              background:#fff;        
              border: 1px solid #000;
              box-sizing: content-box;        
      
              a {
                margin: 0;
                padding: 0;
              }
              a.cell-value {
                display: block;
                font-size: 30px;            
                color: #000;
                width: @cell-size;
                height: @cell-size;
                text-align: center;          
              }
      
              a.cell-value:hover {
              text-decoration: none;
              }
            }      
          }
          clear: both;
        }
      }
      

      你可以找到现场演示here

      【讨论】:

        【解决方案4】:

        很好的解决方案Jukka。我结合使用了这个和下面的 .erb 代码来动态生成表格并弹出内容。

        @current_solution 是我保存每个单元格值的数组。

        <table>
          <colgroup><col><col><col>
          <colgroup><col><col><col>
          <colgroup><col><col><col>
        
          <% 3.times do |all_box_rows_value|%>
          <tbody>
            <% 3.times do |box_row_value| %> 
              <%  all_box_rows = all_box_rows_value * 27 %>
                <% all_rows = ((box_row_value +1 ) * 9)-9 %>
                <tr><%9.times do |row| %>
                  <% index = all_box_rows+all_rows+row %>
                  <% value = @current_solution[index] %><td>
                  <% colour_class = get_colour_class index %>
                  <input name="cell[]" type="text" maxlength="1" autocomplete="off" value=<%=value%> >
                <% end %>
              <% end %>      
          <% end %>    
        </table>
        

        【讨论】:

          【解决方案5】:

          如果是我,我会使用 9 行 9 列的表格。

          然后在 CSS 选择器中使用 :nth-of-type(3n) 来设置每三行和每列的边框。

          【讨论】:

          • 感谢 Mike,虽然这样可以快速解决 HTML / CSS 问题,但它使数独解决代码变得更加复杂。因此问题。
          猜你喜欢
          • 2022-01-08
          • 2016-06-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-04-28
          相关资源
          最近更新 更多