How to create a magic square in PHP?

2019-02-24 19:36发布

问题:

I'd like to try my hand at creating a Magic Square in PHP (i.e. a grid of numbers that all add up to the same value), but I really don't know where to start. I know of the many methods that create magic square, such as starting "1" at a fixed position, then moving in a specific direction with each iteration. But that doesn't create a truly randomized Magic Square, which is what I'm aiming for.

I want to be able to generate an N-by-N Magic Square of N² numbers where each row and column adds up to N(N²+1)/2 (e.g. a 5x5 square where all rows/columns add up to 65 — the diagonals don't matter).

Can anybody provide a starting point? I don't want anybody to do the work for me, I just need to know how to start such a project?

I know of one generator, written in Java (http://www.dr-mikes-math-games-for-kids.com/how-to-make-a-magic-square.html) but the last Java experience I had was over 10 years ago before I quickly abandoned it. Therefore, I don't really understand what the code is actually doing. I did notice, however, that when you generate a new square, it shows the numbers 1-25 (for a 5x5 square), in order, before quickly generating a fresh randomized square.

回答1:

Wikipedia has several algorithms for generating magic squares, such as the siamese, if you please. But as you say that's not a truly random magic square. It does reference a genetic algorithm, wonder whether you could find more details about that?

The method used by your referenced article is using some clever maths, simulated annealing. The actual algorithm isn't explained in the comments and I can't find any references to the details. I could imagine replicating the algorithm without understanding it, transcribing the existing Java - the core of the implementation is very few methods, arrays and arithmentic hardly any Java cleverness.



回答2:

A simple Java program to do this, can be easily rewritten in any language:

/*
* Magic Square
*/

int order = 5;

for (int row = 0; row < order; row++) {
    for (int col = 0; col < order; col++) {
        int rowMatrix = (((order + 1) / 2 + row + col) % order);
        int colMatrix = (((order + 1) / 2 + row + order - col - 1) %
order) + 1;
        System.out.print(((rowMatrix * order) + colMatrix) + "\t");
    }
    System.out.println(); 

Algorithm:

  1. Form a Square Matrix writing numbers 1 to nxn in sequence. Here n is the order of the Magic Square, say 5.
1        2       3       4       5  
6        7       8       9      10
11      12      13      14      15
16      17      18      19      20
21      22      23      24      25
  1. We are trying to identify the final Matrix from the above. Form two matrices, one for identifying the row and another to identify the column.
4       5       1       2       3               3       2       1       5       4
5       1       2       3       4               4       3       2       1       5
1       2       3       4       5               5       4       3       2       1
2       3       4       5       1               1       5       4       3       2
3       4       5       1       2               2       1       5       4       3

You will see the middle column of the first Matrix starts with 1 and are in sequence. Columns on either side can be filled by subtracting and adding 1. The second Matrix is a mirror image.

  1. Form the final Matrix by writing the number from initial Matrix in the corresponding row and column. For e.g 4, 3 (Step 2) = 18 (Step 1)
18      22       1       10      14
24       3       7       11      20
5        9      13       17      21
6       15      19       23       2
12      16      25        4       8

The above steps are applicable for any order of the Magic Square!



回答3:

Sounds like you could solve this with recursion?

In my opinion: Start somewhere with a random number e.g. down right corner, than you start a function solve row, which calls itself until all rows are solved and a function solveField which calls itself until all fields in a row are placed correctly. (fills an array)

solceField places 1. a random variable if there are no restrictions 2. the missing number to complete a row (you should have a check that it doesnt place to high too fast => sum may not be greater than the remaining fields in a row)

if you get somewhere stuck you return false and go back one row and redo the row with a new random variable at its start.

Until everything returns true and you have a maqic square.