Member 14076805 Ответов: 1

Создайте решатель судоку на java .


Цель моего кода, аналогичного алгоритму обратного отслеживания для лабиринтов, состоит в том, чтобы вычислить решения для судоку 9 × 9.
а судоку и его решение хранятся подобно лабиринту в двумерном массиве int.
Я знаю это :алгоритм обратного отслеживания пытается ввести значение 1 ... 9 из ячейки [0.0], начиная со свободного поля (значение тогда равно 0), начиная с пункта 1. Проверка того, является ли это допустимым значением, немного сложнее, чем лабиринт, где нужно было только проверить, свободна ли ячейка. Я думаю, что это хорошая идея, чтобы использовать эти методы
isRowOk ,
исколок ,
isBlockOk
Чтобы воспользоваться проверкой, разрешено ли значение вообще, то есть еще не содержится в блоке.
и тогда все эти три функции должны дать свое согласие, прежде чем алгоритм обратного отслеживания попытается рекурсивно ввести значение 1 ... 9 в следующую свободную ячейку. В противном случае-если все цифры 1 ... 9 были опробованы-поиск будет отменен (возврат), и следующий возможный номер будет опробован в поиске вызова.
У кого-нибудь есть идея получше, потому что мой код работает неправильно?

Что я уже пробовал:

package test;

public class Sudoku {

	private final int BLOCK_SIZE = 3;

	private final int ROW_SIZE = BLOCK_SIZE * BLOCK_SIZE;

	private int nrOfSolutions, nrOfTests;

	private int[][] board;

	private int[][][] testBoard = {
			/* |---------|---------|---------| */
			{ { 5, 3, 0, 0, 7, 0, 0, 0, 0 }, { 6, 0, 0, 1, 9, 5, 0, 0, 0 }, { 0, 9, 8, 0, 0, 0, 0, 6, 0 },
					/* |---------|---------|---------| */
					{ 8, 0, 0, 0, 6, 0, 0, 0, 3 }, { 4, 0, 0, 8, 0, 3, 0, 0, 1 }, { 7, 0, 0, 0, 2, 0, 0, 0, 6 },
					/* |---------|---------|---------| */
					{ 0, 6, 0, 0, 0, 0, 2, 8, 0 }, { 0, 0, 0, 4, 1, 9, 0, 0, 5 }, { 0, 0, 0, 0, 8, 0, 0, 7, 9 } },
			/* |---------|---------|---------| */

			/* |---------|---------|---------| */
			{ { 5, 3, 4, 6, 7, 8, 9, 1, 2 }, { 6, 7, 2, 1, 9, 5, 3, 4, 8 }, { 1, 9, 8, 3, 4, 2, 5, 6, 7 },
					/* |---------|---------|---------| */
					{ 8, 5, 9, 7, 6, 1, 4, 2, 3 }, { 4, 2, 6, 8, 5, 3, 7, 9, 1 }, { 7, 1, 3, 9, 2, 4, 8, 5, 6 },
					/* |---------|---------|---------| */
					{ 9, 6, 1, 5, 3, 7, 2, 8, 4 }, { 2, 8, 7, 4, 1, 9, 6, 3, 5 }, { 3, 4, 5, 2, 8, 6, 1, 7, 0 } },
			/* |---------|---------|---------| */

			/* |---------|---------|---------| */
			{ { 0, 0, 0, 5, 4, 2, 0, 0, 0 }, { 9, 6, 7, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 3, 1, 8 },
					/* |---------|---------|---------| */
					{ 0, 0, 0, 0, 7, 0, 8, 6, 4 }, { 0, 2, 0, 6, 0, 4, 0, 9, 0 }, { 6, 4, 5, 0, 1, 0, 0, 0, 0 },
					/* |---------|---------|---------| */
					{ 8, 9, 1, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 5, 4, 7 }, { 0, 0, 0, 3, 2, 6, 0, 0, 0 } },
			/* |---------|---------|---------| */

	};

	public void testSudokuSolver() {
		for (int[][] s : this.testBoard) {
			this.board = s;
			this.print();

			nrOfSolutions = 0;
			nrOfTests = 0;
			this.solve(0, 0);
		}
	}

	private boolean isBlockOk(int row, int col, int num) {
		
		int iRowStart = (row / BLOCK_SIZE) * BLOCK_SIZE;
		int iColStart = (col / BLOCK_SIZE) * BLOCK_SIZE;

		for ( int irow = iRowStart; irow < iRowStart + BLOCK_SIZE; irow++) {
			for ( int icol = iColStart; icol < iColStart + BLOCK_SIZE; icol++) {

				if (num == board[irow][icol]) {
					return false;
				}
			}
		}
		return true;
	}

	private boolean isRowOk(int row, int num) {
		for (int i = 0; i < ROW_SIZE; i++) {
			if (num == board[row][i]) {
				return false;
			}
		}
		return true;
	}

	private boolean isColOK(int col, int num) {
		for (int i = 0; i < ROW_SIZE; i++) {
			if (num == board[i][col]) {
				return false;
			}
		}
		return true;
	}

	public void print() {
		final String horizBorder = " ┼────────┼────────┼────────┼";

		System.out.println();

		for (int i = 0; i < ROW_SIZE; i++) {
			if (0 == i % 3) {
				System.out.println(horizBorder);
			}

			for (int j = 0; j < ROW_SIZE; j++) {
				if (0 == j % 3) {
					System.out.print(" │ ");
				}

				int num = board[i][j];
				if (num == 0) {
					System.out.print("_ ");
				} else {
					System.out.print(num + " ");
				}

			}
			System.out.println(" │");
		}
		System.out.println(horizBorder);
	}

	private boolean isValid(int num, int row, int col) {
		return (isBlockOk(row, col, num) && isColOK(col, num) && isRowOk(row, num));
	}

	public boolean solve(int row, int col) {

		for (int i = 1; i < BLOCK_SIZE; i++) {
			for (int j = 1; j < BLOCK_SIZE; j++) {
				if (board[i][j] == 0) {
					for (int k = 1; k <= 9; k++) {
						board[i][j] = k;
						if (isValid(i, j, k) && solve(i, col)) {
							return true;
						}
						board[i][j] = 0;
					}
					return false;
				}
			}
		}
		return true;
	}

	public static void main(String[] args) {
		new Sudoku().testSudokuSolver();
	}

}

1 Ответов

Рейтинг:
1

Patrice T

Цитата:
У кого-нибудь есть идея получше ?

принцип обратного хода работает, он просто неэффективен.
Человеческий метод более эффективен.
Цитата:
потому что мой код работает неправильно?

Тогда вам нужно отладить свой код !
Во-первых, измените свой код для отображения каждой платы каждый раз, когда вы устанавливаете ячейку, и дождитесь ввода пользователя перед следующим шагом. Когда вы видите неправильный ход, это означает, что ваш код не проверяет правильно этот ход, это дает вам подсказки о том, где нужно проверить код.

Отладчик также очень помогает:
Ваш код ведет себя не так, как вы ожидаете, или вы не понимаете, почему !

Существует почти универсальное решение: запускайте свой код на отладчике шаг за шагом, проверяйте переменные.
Отладчик здесь, чтобы показать вам, что делает ваш код, и ваша задача-сравнить с тем, что он должен делать.
В отладчике нет никакой магии, он не знает, что должен делать ваш код, он не находит ошибок, он просто помогает вам, показывая, что происходит. Когда код не делает того, что ожидается, вы близки к ошибке.
Чтобы увидеть, что делает ваш код: просто установите точку останова и посмотрите, как работает ваш код, отладчик позволит вам выполнять строки 1 на 1 и проверять переменные по мере их выполнения.
Отладчик - Википедия, свободная энциклопедия[^]

Освоение отладки в Visual Studio 2010 - руководство для начинающих[^]
Базовая отладка с помощью Visual Studio 2010 - YouTube[^]
http://docs.oracle.com/javase/7/docs/technotes/tools/windows/jdb.html[^]
https://www.jetbrains.com/idea/help/debugging-your-first-java-application.html[^]
Отладчик здесь только для того, чтобы показать вам, что делает ваш код, и ваша задача-сравнить его с тем, что он должен делать.

Взгляните на это:
Решатель судоку Эндрю Стюарт[^]
Простые судоку - бесплатные программы для создания головоломок и поиска решения[^]
Решение Судоку[^]