Java|魔方陣「ミニナンプレ」を解くプログラムを作る

javaでミニナンプレを作るプログラミング制作物
プログラミング制作物

Dimです。前回の『Java|魔方陣「ミニナンプレ」の完成表を出力するプログラム』の続きになります。

今回はミニナンプレを解くプログラムを作ろうと思います。

スポンサーリンク

ミニナンプレを解くプログラムを作る

前回の記事では、ミニナンプレの完成形を出力するプログラムを作りました。ミニナンプレを完成させる順序として、完成形にランダムに穴をあけることで実現させることにしました。

穴をあけた数表でミニナンプレができるか検証する必要があります。また、解答例が複数ある場合に備えるため、下の様にミニナンプレを完成させるプログラムを作りたいと思います。

1 0 0 0      1 2 3 4
3 0 1 2    →  3 4 1 2
4 3 0 1        4 3 2 1
0 0 0 0        2 1 4 3

上の数表のように、ミニナンプレの空白の部分を0とした数列が与えられたとき、そこからミニナンプレを完成させるプログラムを完成させます。

今回は上の数表をnum1[4][4]の数列に代入したものを使って、プログラムを書いていきます。

サンプルコードと出力結果

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

import java.util.HashSet;
import java.util.Random;
import java.util.Set;

public class Mahou4_test {
   // 重複しているかチェックするメソッド
	public static boolean mahou_check(int num1, int num2, int num3, int num4, int rnd) {
		Set<Integer> integerSet = new HashSet<>();
		integerSet.add(num1);
		integerSet.add(num2);
		integerSet.add(num3);
		integerSet.add(num4);
		if (integerSet.contains(rnd)) {
			integerSet.clear();
			return true;
		} else {
			integerSet.clear();
			return false;
		}
	}

	public static void main(String[] args) {

		// 問題例を配列に格納する
		int[][] num1 = { { 1, 0, 0, 0 }, { 3, 0, 1, 2 }, { 4, 3, 0, 1 }, { 0, 0, 0, 0 } };

		// 解答を格納する配列を作る
		int[][] num2 = new int[4][4];
		int i = 0, j = 0, rnd, x = 0, count = 0;
		Random rand = new Random();
		while (x < 1) {
			for (i = 0; i <= 3;) {

				// 横の行を検証する
				// 数字が重複しないように数字を選ぶ
				// ループが一定数以上になったら最初からやり直し
				for (j = 0; j <= 3;) {
					if (num1[i][j] != 0) {
						num2[i][j] = num1[i][j];
						j++;
					} else {
						rnd = rand.nextInt(4) + 1;
						if (mahou_check(num2[i][0], num2[i][1], num2[i][2], num2[i][3], rnd)) {
							count++;
							if (count > 100) {
								i = 0;
								j = 0;
								num2 = new int[4][4];
								count = 0;
								break;
							}
						} else {

							// 縦の列を検証する
							if (mahou_check(num2[0][j], num2[1][j], num2[2][j], num2[3][j], rnd)) {
								count++;
								if (count > 100) {
									i = 0;
									j = 0;
									num2 = new int[4][4];
									count = 0;
									break;
								}

								// 条件を満たしたので代入する
							} else {
								num2[i][j] = rnd;
								j++;
							}
						}
					}
				}
				if (j > 3) {
					i++;
				}
			}

			// ボックスの数字を検証する
			int box1 = num2[0][0] + num2[0][1] + num2[1][0] + num2[1][1];
			int box2 = num2[0][2] + num2[0][3] + num2[1][2] + num2[1][3];
			int box3 = num2[2][0] + num2[2][1] + num2[3][0] + num2[3][1];
			int box4 = num2[2][2] + num2[2][3] + num2[3][2] + num2[3][3];
			if (box1 == 10 && box2 == 10 && box3 == 10 && box4 == 10) {
				x++;
			} else {
				i = 0;
				j = 0;
				num2 = new int[4][4];
			}
		}

		// 完成表を出力する
		for (i = 0; i < 4; i++) {
			for (j = 0; j < 4; j++) {
				System.out.printf("%3d", num2[i][j]);
			}
			System.out.println();
		}
	}
}

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

  1  2  4  3
  3  4  1  2
  4  3  2  1
  2  1  3  4

ミニナンプレを完成させることができました。しかし、上の数表とは解答が違います。つまり、上の問題は解答例が複数あるということですね。

今日はこのプログラムを完成させるのに手間取り数時間掛ったので、今回はこれで終わりにして次回に続きます。

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