Java|数独に使われる魔方陣をプログラミングで作る

数独をJavaで作るプログラミング制作物
プログラミング制作物

この記事では数独に使われる9×9の魔方陣をプログラミングで作成してみます。

スポンサーリンク

数独の魔方陣の特徴

作成する9×9の魔方陣の特徴についてまとめます。

特徴
  • 縦と横の全ての列で1~9の数字が1つずつ使われる
  • 3×3のブロックに1~9の数字が1つずつ使われる

数独の魔方陣はこんな感じの数表です。

プログラミングで作ってみる

上の画像のような数表を出力するプログラムを作成します。

アルゴリズム

基本的な作り方は

アルゴリズム
  1. 出来上がった数表を格納するint型配列num[9][9]を宣言する
  2. 1~9の数字が入ったArrayListを作りシャッフルしnumに格納する(これが横の行の1つになる)
  3. 縦の列に重複しないようにArrayListをnumに格納していく 重複したら格納せずもう一度シャッフルしていくを繰り返す
  4. 同時に3×3のブロックも重複がないかチェックする 重複したらその都度やり直す

この様なアルゴリズムで作成することにします。重複のチェックはHashSetを使いました。

サンプルコード

サンプルコードを以下に示します。

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

public class Sudoku_make {

	public static void main(String[] args) {
		// num:数表 list:横の行
		// integerSet1:縦の重複の確認用
		// integerSet2:3×3ブロックの重複の確認用
		int[][] num = new int[9][9];
		ArrayList<Integer> list = new ArrayList<Integer>();
		Set<Integer> integerSet1 = new HashSet<>();
		Set<Integer> integerSet2 = new HashSet<>();
		int i, j, x;

		// listの作成とシャッフル
		for (i = 1; i <= 9; i++) {
			list.add(i);
		}
		Collections.shuffle(list);

		for (i = 0; i <= 8;) {
			int u = 2, v = 2;
			if (i == 5) {
				u = 5;
			}

			// integerSet1の重複チェック
			for (j = 0; j <= 8;) {
				num[i][j] = list.get(j);
				for (x = 0; x < i; x++) {
					integerSet1.add(num[x][j]);
				}
				if (integerSet1.contains(num[i][j])) {
					integerSet1.clear();
					break;
				}

				// integerSet2の重複チェック
				if (i == u && j == v) {
					integerSet2.add(num[u - 2][v - 2]);
					integerSet2.add(num[u - 2][v - 1]);
					integerSet2.add(num[u - 2][v]);
					integerSet2.add(num[u - 1][v - 2]);
					integerSet2.add(num[u - 1][v - 1]);
					integerSet2.add(num[u - 1][v]);
					integerSet2.add(num[u][v - 2]);
					integerSet2.add(num[u][v - 1]);
					integerSet2.add(num[u][v]);
					if (integerSet2.size() != 9) {
						integerSet2.clear();
						i -= 2;
						j = 0;
						break;
					}
					v = 5;

				}
				j++;

				integerSet1.clear();
				integerSet2.clear();
			}
			if (j == 9) {
				i++;
			}

			Collections.shuffle(list);

		}

		// 完成したnumの出力
		for (i = 0; i <= 8; i++) {
			for (j = 0; j <= 8; j++) {
				System.out.print(num[i][j] + " ");
			}
			System.out.println();
		}
	}

}

出力結果(一例)

サンプルコードの出力結果を以下に示します。出力結果は一例です。

3 9 6 7 1 5 2 4 8 
2 1 8 6 3 4 5 9 7 
7 5 4 8 9 2 1 3 6 
5 6 9 3 2 8 4 7 1 
1 8 7 4 6 9 3 5 2 
4 3 2 1 5 7 6 8 9 
8 7 1 5 4 6 9 2 3 
6 2 5 9 7 3 8 1 4 
9 4 3 2 8 1 7 6 5

条件を満たす数表が出力されました。条件を満たすまでシャッフルを繰り返すので、出力されるまでちょっと時間がかかります。

まとめ

今回は数独の数表を作るところまで完成しました。

完全にランダムで条件を満たすか当てはめていってるので、処理に時間がかかっているところが問題点ですね。その部分を処理を減らすことも考えていきたいです。

この記事では時間がなくてできませんでしたが、数独の問題を作る機能も実装したいと思います。

スポンサーリンク
Dim雑記
タイトルとURLをコピーしました