公制魔方

时间:2019-02-19 06:15:02

标签: javascript magic-square

任何人都可以帮助我为魔术平方度量创建逻辑。在给定的示例中,我创建了一个代码以生成3x3、5x5、7x7度量标准的奇数的Magic Square,但无法找到创建2x2、4x4、6x6、8x8、10x10等的偶数值魔术平方度量标准的正确解决方案。 / p>

在当前实现中,任何人都可以在输入中输入数字(n)并单击Generate按钮,这将创建一个nxn幻方度量。但是用偶数不能很好地工作。

$(function () {
    var n;
    var main = $('#main');

    $("#generate").click(function(){
      $("#main").text("");
      var val = $("#number").val();
      if(val){
        n = val;
        generateMetric(val); // Generate n x n metric
      }
    });

    function generateMetric(n){
      var magicSquare = [];

      // Set all metric values to 0
      for (var i = 0; i < n; i++) {
        magicSquare[i] = [];

        for (var j = 0; j < n; j++) {
          magicSquare[i].push(0);
          main.append('<input type="text" class="values" id="'+ i +'-'+ j +'" readonly />');
        }
        main.append('<div class="clear"></div>');
      }


      // Initialize position for 1 

      var i = parseInt(n/2);
      var j = n - 1;

      // Put all values in metric
      for(var k = 1; k <= n*n;){
        if(i == -1 && j == n){
          j = n - 2;
          i = 0;
        }else{
          // if value of j is going to higher than n
          if(j == n){
            j = 0;
          }

          // if value of i is going in minus
          if(i < 0){
            i = n - 1;
          }
        }

        if(magicSquare[i][j]){
          j -= 2; 
          i++;
          continue; 
        } else{		
          // set the value in metric
          magicSquare[i][j] = k++;
        }

        j++; i--; 
      }

      // Append values to all metric inputs
      for (var i = 0; i < n; i++){ 
        for (var j = 0; j < n; j++) {
          $("#"+i +"-"+ j).val(magicSquare[i][j]);
        }
      }
    }
  });
 body {
    margin: 30px;
  }
  .values {
    width: 30px;
    float: left;
    margin-right:1px;
  }
  .clear {
    clear: both;
  }
<script type="text/javascript" src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<input type="text" id="number" />
<input type="button" id="generate" value="Generate" />
<div id="main"></div>

1 个答案:

答案 0 :(得分:0)

您可以使用以下解决方案来创建所有魔法乡绅。

  

HTML

<body onload="constructMSquare();">
  <h1>Magic Square</h1>
  <form class="confbox" onsubmit="constructMSquare(); return false;" method="post">
    Size: <input id="size" type="number" min="3" max="32" value="5">
    <input type="submit" name="cd" value="Calculate!">
    <br>
    <input type="button" value="save" name="save" id="save">
  </form>
  <div class="square">
    <div id='quadrat'>
      <p class="row"></p>
    </div>
  </div>
</body>
  

CSS

body {
  background-color: rgb(97,189,255);

  text-align: center;
}

.square {
  margin: auto;

}

.confbox {
  margin: 15px;
}

#quadrat {
  display: table;
  border: solid;
  border-width: thick;
  border-radius: 5px;
  background-color: rgb(84,156,251);
  border-color: rgb(0,34,138);
  margin: 0 auto;
}

span {
  display: table-cell;
  width: 50px;
  height: 50px;
  margin: 0;
  border: solid;
  border-width: 5px;
  padding: 0;
  text-align: center;
  vertical-align: middle;
  border-color: rgb(0,34,138);
  font-weight: bold;
  color: rgb(0,34,138);

}

p {
  margin: 0;
  padding: 0;

}
  

JavaScript:

var size = 0
var square = []

var constructMSquare = function () {
  size = document.getElementById('size').value; // squaresize

  // choose generatinalgorithm depending on squaresize( odd, even or doubleeven(evener))
  if (size % 2 == 0) {
    if (size % 4 == 0) {
      square = evenerMSquare(size);
    } else {
      square = evenMSquare(size);
    }
  } else {
    square = oddMSquare(size);
  }

  if (check(square)) {
    displaySquare(square);
  }


  document.getElementById('save').addEventListener('click', save)

  return false;
}

var isCellempty = function (square, column, row, squaresize, startX,  startY) {
  // default arguments

  // yes inefficient, but otherwise it is not working :( why?
  if (squaresize == undefined) {
    squaresize = square.length;
  }

  if (startX == undefined) {
    startX = 0;
  }

  if (startY == undefined) {
    startY = 0;
  }

  // check if the cell is empty

  // if column is not in the square put it back in
  if (column >= squaresize) {
    var column = squaresize % column;
  } else if (column < 0) {
    if (column < 0) {
      column = 0 - column;
    }

    var column = squaresize - column;
  }
  // if row is not in the square put it back in
  if (row >= squaresize) {
    var row = squaresize % row;
  } else if (row < 0) {
    var row = 0 - row;
    var row = squaresize - row;
  }

  // add start position to column and row to find the position in the big square
  var column = column + startX;
  var row = row + startY;

  // check if this position is empty
  var cell = square[row];
  if (cell[column] != null) {
    return false;
  }

  return true;
}

function oddMSquare(size) {
  // constracts magic squares with an odd size (http://www.1728.org/magicsq1.htm)

  // create an empty Square
  var square = [];
  for (var i = 0; i < size; i++) {
    var newRow = [];
    for (var u = 0; u < size; u++) {
      newRow.push();
    }

    square.push(newRow);
  }

  // fill the magic square
  var row = 0;
  var column = Math.round(size / 2) - 1; //start in the middle

  // counts till the number of cells
  for (var i = 1; i <= size * size; i++) {
    // fill the count in the cell
    var c = square[row];
    c[column] = i;

    // if the cell top right is empty set current "cell" to that position
    // else set it to the position below
    if (isCellempty(square, column + 1, row - 1)) {
      column++;
      row--;
    } else {
      row++;
    }

    // if column is not in the square put it back in
    if (column >= size) {
      column = size % column;
    } else if (column < 0) {
      column = 0 - column;
      column = size - column;
    }

    // if row is not in the square put it back in
    if (row >= size) {
      row = size % row;
    } else if (row < 0) {
      row = 0 - row;
      row = size - row;
    }
  }

  return square;
}

function evenMSquare(size) {
  // constracts magic squares with an even size (http://www.1728.org/magicsq3.htm)

  // create an empty square
  var square = [];
  for (var i = 0; i < size; i++) {
    var newRow = [];
    for (var u = 0; u < size; u++) {
      newRow.push();
    }

    square.push(newRow);
  }

  var y = size / 2; // size of the "mini magic squares"
  var i = 1; // counter

  // counts the mini magic sqaures
  for (var b = 1; b <= 4; b++) {
    // choose "mini magic square"
    switch (b) {
      case 1:
        // upper left
        var startX = 0;
        var startY = 0;
        break;
      case 2:
        // lower right
        var startX = y;
        var startY = y;
        break;
      case 3:
        // upper right
        var startX = y;
        var startY = 0;
        break;
      case 4:
        // lower left
        var startX = 0;
        var startY = y;
        break;
    }

    var row = 0;
    var column = (Math.round(y / 2) - 1); //start in the middle

    // counts till the number of cells of the "mini magic square"
    for (var a = 1; a <= y * y; a++ && i++) {
      // fill the count in the cell
      var c = square[row + startY];
      c[column + startX] = i;

      // if the cell top right is empty set current "cell" to that position
      // else set it to the position below
      if (isCellempty(square, column + 1, row - 1, y, startX, startY)) {
        column++;
        row--;
      } else {
        row++;
      }

      // if column is not in the square put it back in
      if (column >= y) {
        column = y % column;
      } else if (column < 0) {
        if (column < 0) {
          column = 0 - column;
        }

        column = y - column;
      }

      // if column is not in the square put it back in
      if (row >= y) {
        row = y % row;
      } else if (row < 0) {
        if (row < 0) {
          row = 0 - row;
        }

        row = y - row;
      }
    }

  }

  function swapAandB(posX, posY) {
    // swap the cell(posX, posY) with the cell at the upper mini magic square
    var cRow = square[posX];
    var a = cRow[posY];
    cRow = square[posX + y];
    var b = cRow[posY];
    cRow[posY] = a;
    cRow = square[posX];
    cRow[posY] = b;

  }

  // swap the right corners
  for (var i = 0; i < Math.floor(y / 2); i++) {
    for (var row = 0; row < y / 2; row++) {
      swapAandB(row, i);
      swapAandB(y - row - 1, i);

    }
  }

  // swap in the middle row beginning from the second cell till the lenght of the corners
  for (var i = 1; i < y / 2; i++) {
    swapAandB(Math.floor(y / 2), i);
  }

  // swap the last ( (squaresize - 6(size of the first single even magic square))
  //                  / 4(distance to next single even magic square) ) columns
  for (var i = 1; i <= (size - 6) / 4; i++) {
    for (var row = 0; row < y; row++) {
      swapAandB(row, size - i);
    }
  }

  return square;
}

function evenerMSquare(size) {
  // create square
  var square = [];

  // calculate square
  for (var i = 0; i < (size * size); i++) {

    // if i is greater than the length of the square create a new row
    if ((i % size) == 0) {
      var newRow = [];
      square.push(newRow);
    }

    /* if i is in a corners(cornersize = squaresize/4)
    or in the middle write the count in the square
    else write the count backwards in the square */
    if (((i % size < size / 4) || i % size >= size - size / 4) && ((square.length <= size / 4) || square.length > size - size / 4)) {
      newRow[i % size] = i + 1;
    } else if (!((i % size < size / 4) || i % size >= size - size / 4) && !((square.length <= size / 4) || square.length > size - size / 4)) {
      newRow[i % size] = i + 1;
    } else {
      newRow[i % size] = (size * size) - i;
    }
  }

  return square;
}

function check(square) {
  // Check if the sum of the rows, columns and diagonals equals the magic number.

  // defines the magic number
  sum = square.length * (square.length * square.length + 1) / 2;
  console.log('magic number: ', sum);

  // Check the rows.
  for (row in square) {
    row = square[row];
    var x = 0;
    for (i in row) {
      i = row[i];
      x = x + i;
    }

    if (x != sum) {
      console.log('fehler!!!!!!!!!!');
      console.log(x);
      console.log(row);
      return false;
    }
  }

  // Check the columns.
  for (column in square) {
    var x = 0;
    for (row in square) {
      row = square[row];
      x = x + row[column];
    }

    if (x != sum) {
      console.log('fehler!!!!!!!!!!');
      console.log(x);
      console.log(column);
      return false;
    }
  }

  // Check the diagonal(from right top to left buttom).
  count = 0;
  x = 0;
  for (row in square) {
    row = square[row];
    x = x + row[count];
    count = count + 1;
  }

  if (x != sum) {
    console.log('fehler!!!!!!!!!!');
    return false;
  }

  // Check the diagonal(from left top to right buttom).
  count = 0;
  x = 0;
  for (row in square) {
    row = square[row];
    x = x + row[row.length - count - 1];
    count = count + 1;
  }

  if (x != sum) {
    console.log('fehler!!!!!!!!!!');
    return false;
  }

  return true;
}

function displaySquare(square) {
  // Displays the array square in html.
  var quadrat = document.getElementById('quadrat');

  // removing the old square
  childNodes = quadrat.childNodes;
  while (quadrat.childNodes.length != 0) {
    for (var i in quadrat.childNodes) {
      i = quadrat.childNodes[i];
      try {
        quadrat.removeChild(i);
      }
      catch (e) {
        console.log('catched');
      }
    }
  }

  function addRow(square) {
    // Adds rows in the quadrat (html).
    addedRow = document.createElement('p');
    quadrat.appendChild(addedRow);
    addedRow.class = 'row';
    addCells(addedRow);
  }

  function addCells(htmlRow) {
    // Adds cells in the added row and fills them with the numbers of square.

    // for every cell in the row
    for (cell in row) {
      cell = row[cell];
      addedCell = document.createElement('span');
      addedCell.innerHTML = cell;
      htmlRow.appendChild(addedCell);
      addedCell.class = 'cell';
    }
  }

  // for every row of the square
  for (row in square) {
    row = square[row];
    addRow(square);

  }
}

function save() {
  var a = document.createElement("a");
  document.body.appendChild(a);
  a.style = "display: none";
  var data = square.reduce((data, row) => data + '\n' + row.join(','), '')
  var blob = new Blob([data], {type: "text/csv"}),
      url = window.URL.createObjectURL(blob);
  a.href = url;
  a.download = `magic-square_${size}.csv`;
  a.click();
  window.URL.revokeObjectURL(url);
}

下载完整的源代码here