package test;
import java.util.Scanner;
public class MagicSquare {
/** 幻方总数 */
static int allNum = 0;
/** 幻方阶数 */
static int n = 0;
/** 幻方最大下角坐标 */
static int m = 0;
/** 幻方行列对角和 */
static int count = 0;
/**
* 初始化幻方以及相关参数
* @return
*/
public int[][] initMgSq(){
n = (int) Math.sqrt(allNum);
count = n*(n*n+1)/2;
m = n-1;
int[][] mgSq = new int[n][n];
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
mgSq[i][j] = 0;
}
}
System.out.println("阶数:"+n);
System.out.println("行列对角和:"+count);
return mgSq;
}
/**
* 解幻方,并打印结果
*/
public void solve(int[][] mgSq) {
if (this.solve(mgSq, 0, 0)) {
printArray(mgSq);
} else {
System.out.println("没有找到相应的解法");
}
}
/**
* 解幻方
*/
private boolean solve(int[][] mgSq, int row, int column) {
/**
* 结束条件
*/
if (row == m && column == n) {
return true;
}
/**
* 如果column == n, 那么需要换行,也就需要更新column和row的值.
*/
if (column == n) {
column = 0;
row++;
}
/**
* 如果当前位置上mgSq[row][column]的值为0, 尝试在1~allNum的数字中选择合适的数字
*/
for (int num = 1; num <= allNum; num++) {
if (isSafe(mgSq, row, column, num)) {
mgSq[row][column] = num;
if (solve(mgSq, row, column + 1)) {
return true;
}
mgSq[row][column] = 0;
}
}
/**
* 回溯重置
*/
mgSq[row][column] = 0;
return false;
}
/**
* 该数字是否已使用
*/
private boolean isNumSafe(int[][] mgSq, int value) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if(mgSq[i][j] == value){
return false;
}
}
}
return true;
}
/**
* 某一行放置数据是否可以
*/
private boolean isRowSafe(int[][] mgSq, int row, int value) {
int rowCount = value;
for(int i : mgSq[row]){
rowCount += i;
}
// 如果是行最后一个 ,判断这一行的和是否正确
if(mgSq[row][m-1] != 0){
if(rowCount != count){
return false;
}
}else{
if(rowCount >= count){
return false;
}
}
return true;
}
/**
* 某一列放置数据是否可以
*/
private boolean isColumnSafe(int[][] mgSq, int column, int value) {
int columnCount = value;
for(int i=0;i<n;i++){
columnCount += mgSq[i][column];
}
// 如果是行最后一个 ,判断这一列的和是否正确
if(mgSq[m-1][column] != 0){
if(columnCount != count){
return false;
}
}else{
if(columnCount >= count){
return false;
}
}
return true;
}
/**
* 对角是否可以放该数据
*/
private boolean isOppositeSafe(int[][] mgSq, int row, int column, int value) {
//左右对角线和
int aCount = 0;//左
int bCount = 0;//右
if(row == column || (row + column) == m){
//求对角线值
for(int i=0;i<n;i++){
aCount += mgSq[m-i][i];
bCount += mgSq[i][i];
}
//最后一行
if(row == m){
if(column == 0 && (aCount + value) != count){
return false;
}else if(column == m && (bCount + value) != count){
return false;
}
}else if(row == column && (row + column) == m){//中间点,偶数阶幻方无该坐标
if((aCount + value) >= count || (bCount + value) >= count){
return false;
}
}else{
if(row == column){
if((bCount + value) >= count){
return false;
}
}else{
if((aCount + value) >= count){
return false;
}
}
}
}
return true;
}
/**
* 在指定位置是否可以放置数据
*/
private boolean isSafe(int[][] mgSq, int row, int column, int value) {
if(this.isNumSafe(mgSq, value)){
if(this.isRowSafe(mgSq, row, value)){
if(this.isColumnSafe(mgSq, column, value)){
if(this.isOppositeSafe(mgSq, row, column, value)){
return true;
}
}
}
}
return false;
}
/**
* 打印二维数组到控制台
*/
private void printArray(int[][] mgSq) {
System.out.println("------------------------");
for (int i = 0; i < n; i++) {
System.out.print("|");
for (int j = 0; j < n; j++) {
System.out.print(" ");
System.out.print(mgSq[i][j]+" ");
if(mgSq[i][j]<10){
System.out.print(" ");
}
System.out.print("|");
}
System.out.println("");
}
System.out.println("------------------------");
}
/**
* 测试
* @param args
*/
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
allNum = sc.nextInt();
double d = Math.sqrt(allNum);
String dStr = String.valueOf(d);
dStr = dStr.substring(dStr.indexOf(".") +1);
if(allNum < 9 || !dStr.equals("0")){
System.out.println("请输入正确的幻方数字,例如:9,16...");
}else{
MagicSquare example = new MagicSquare();
int[][] mgSq = example.initMgSq();
example.solve(mgSq);
}
}
}