这更多是一个逻辑问题。问题是:
我需要用数字(1-9)填充矩阵,这样:
我不擅长将我尝试过的逻辑放在下面:
public class RandMatrix {
static int max=8;
static ArrayList<Integer> numbers=new ArrayList<>();
static int[][] arr=new int[max][max];
public static void main(String[] a){
// To fill number
for (int i = 1; i <=9; i++) {
numbers.add(i);
}
// Shuffle number
Collections.shuffle(numbers);
call();
}
public static void call(){
for (int i = 0; i < max; i++) {
for (int j = 0; j <max ; j++) {
for (int k = 0; k <max ; k++) {
int num=numbers.get(k);
if(!isExist(num,i,j)){
arr[i][j]=num;
break;
}
}
}
Collections.shuffle(numbers);
}
}
private static boolean isExist(int num,int row, int col){
for (int i = row; i >=0; i--) {
if(arr[i][col]==num){
return true;
}
}
for (int j = col; j >=0; j--) {
if(arr[row][j]==num){
return true;
}
}
return false;
}
}
当我打印二维数组时,我在某些地方看到值仍然为0。好像我的代码中断了。在某些时候,没有剩余的随机数可以填充。输出类似于:
我知道我的算法是不对的,我只是找不到方法来完成它。 我可以在这方面寻求帮助吗?
答案 0 :(得分:3)
我已经保存并修改了一些代码,以便在需要其他时间时使用。我想这是给你的;)
import java.util.Arrays;
import java.util.Random;
class Test {
public static void main(String[] args){
int size = 9;
int[][] matrix= new int[size][];
matrix[0] = MatrixOps.createOrderedArray(size, 1);
for(int x=0; x < size; x++) {
matrix[x] = MatrixOps.createOrderedArray(size, 1);
do {
MatrixOps.shuffle(matrix[x]);
} while(! MatrixOps.compare2DArray(matrix[x], matrix, 0, x));
}
MatrixOps.print(matrix);
}
}
class MatrixOps {
public static void shuffle(int[] arr){
Random random = new Random();
for(int x = 0; x < arr.length; x++)
swap(arr, x, random.nextInt(arr.length));
}
public static int[] createOrderedArray(int size, int startValue) {
int[] num = new int[size];
for (int x = 0; x < num.length; x++)
num[x] = x + startValue;
return num;
}
public static boolean compare2DArray(int[] arr1, int[][] arr2, int begin, int end) {
for (int x = begin; x < end; x++)
if (!compareArray(arr1, arr2[x]))
return false;
return true;
}
// https://stackoverflow.com/questions/19648240/java-best-way-to-print-2d-array/41533179#41533179
public static void print(int[][] array) {
for (int[] x: array) {
for (int y: x) {
System.out.print(y + " ");
}
System.out.println();
}
}
private static boolean compareArray(int[] arr1, int[] arr2){
if(arr1.length != arr2.length)
return false;
for(int x=0; x<arr1.length; x++)
if(arr1[x] == arr2[x])
return false;
return true;
}
private static void swap(int[] arr, int a, int b){
int temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
}
示例输出:
5 1 7 2 3 8 9 4 6
4 3 1 5 7 9 2 6 8
9 7 3 8 6 2 4 5 1
6 8 4 3 5 7 1 9 2
1 5 8 9 2 6 7 3 4
7 9 2 6 4 1 5 8 3
8 6 9 4 1 5 3 2 7
3 2 6 7 9 4 8 1 5
2 4 5 1 8 3 6 7 9
答案 1 :(得分:1)
在启动过程中定义以下矩阵:
1 2 3 4 5 6 7 8 9
2 3 4 5 6 7 8 9 1
3 4 5 6 7 8 9 1 2
4 5 6 7 8 9 1 2 3
5 6 7 8 9 1 2 3 4
6 7 8 9 1 2 3 4 5
7 8 9 1 2 3 4 5 6
8 9 1 2 3 4 5 6 7
9 1 2 3 4 5 6 7 8
当您需要创建n X n矩阵时,请执行以下操作:
唯一的问题是结果仍然不是完全随机的。 (它不能生成所有可能的解决方案。)尽管仅在标题中提到了随机性,但在3个要求中没有提及...
答案 2 :(得分:1)
我认为最好的方法是使用随机回溯算法。
矩阵的元素一个接一个地填充。对于每个矩阵元素,我们首先枚举所有可以使用的剩余整数(基于前面的元素)。然后以随机顺序尝试其中的每一个,直到找到第一个解决方案为止。
public static void main(String[] args) {
int[][] matrix = getMatrix(7, 0L);
if (matrix != null) {
for (int row = 0; row < 7; ++row) {
for (int column = 0; column < 7; ++column) {
System.out.print(matrix[row][column]);
}
System.out.println();
}
}
}
public static int[][] getMatrix(int size, long seed) {
int[][] matrix = new int[size][size];
Random random = new Random(seed);
if (!backtrack(matrix, size, 0, random))
return null;
return matrix;
}
// returns true when the backtracking could succesfully fill the matrix
private static boolean backtrack(int[][] matrix, int size, int index, Random random) {
if (index == size * size) {
// all elements are filled without conflict
return true;
} else {
// find the row and column of the next element which need to be filled
int column = index % size;
int row = index / size;
// an array which indicates whether the numbers in range [1 - 9] can be used
// canUse[x] encodes whether number (x+1) can be used
boolean[] canUse = new boolean[9];
Arrays.fill(canUse, true);
// check the previous rows and column elements
for (int c = 0; c < column; ++c)
canUse[matrix[row][c] - 1] = false;
for (int r = 0; r < row; ++r)
canUse[matrix[r][column] - 1] = false;
// generate the list of possible entries
List<Integer> possibilities = new ArrayList<Integer>();
for (int i = 1; i <= 9; ++i)
if (canUse[i - 1])
possibilities.add(i);
// backtrack if there are no possible entries
if (possibilities.isEmpty())
return false;
// shuffle the list (to randomly fill the matrix)
Collections.shuffle(possibilities, random);
// enter the number
for (int possiblity : possibilities) {
matrix[row][column] = possiblity;
if (backtrack(matrix, size, index + 1, random))
return true;
}
return false;
}
}
输出:
4139562
1896375
2613857
9357124
6245931
3482619
8761493
答案 3 :(得分:0)
给它一个疯狂的镜头,而不是编写代码。但请仔细考虑:
如何开始逐列填充数字,例如
mat[0][0]=1
mat[1][0]=2
...
mat[8][0]=9
然后,当您开始填充下一列时,请执行以下操作:
mat[1][1]=1
mat[2][1]=2
...
mat[8][1]=8
mat[0][1]=9
以此类推。
所以它精确地按顺序和对角线填充数字。
答案 4 :(得分:0)
使用纯随机数来填充矩阵,如果到达死角,则需要重做结果的最后一部分。
public static void call(){
int repeats = 0;
for (int i = 0; i < max; i++) {
for (int j = 0; j <max ; j++) {
for (int k = 0; k <max ; k++) {
int num=numbers.get(k);
if(!isExist(num,i,j)){
arr[i][j]=num;
break;
}
}
}
if(containsZero(arr[i]){
i--;
repeats++;
if(repeats > 1000){
i = 0;
repeats = 0;
}
}
Collections.shuffle(numbers);
}
}
private static boolean containsZero(int[] array){
for(int i = 0; i < array.length; i++){
if(array[i] == 0){
return true;
}
}
return false;
}
在某些情况下,更改最后一行不足以保证矩阵将被填充。这就是为什么我添加了一个计数器,如果通过更改最后一行找不到解决方案,它将重置整个矩阵。