「ナンバープレイス/数独」

計算機実習 II 後期 課題2
「ナンバープレイス/数独」
課題:ナンプレの問題のうち「Normal」レベル(別紙参照)までの問題を解くプログラム
を作成する。
締切:11 月 10 日(月)授業開始時にソースコードを印刷して提出
11 月 10 日のレポート回収後に解答例を配布する。自分が作成したプログラムと解
答例を比較し、自分のプログラムが解答例より優れている点、劣っている点、考え方
の違い等をレポートにまとめ、翌週 17 日の授業開始時に提出すること。
問題読み込み・盤面表示プログラムのダウンロード:
計算機実習 II ホームページより、次ページに記載の「問題読み込み・盤面表示プ
ログラム」および「問題ファイル」をダウンロードすること。
開発の目安(最低限):
10 月 20 日:未確定マスの全候補数字を表示するプログラム作成
~10 月 28 日:レベル Easy の問題を解くプログラム完成
~11 月 10 日:レベル Normal の問題を解くプログラムを提出
採点の目安(プログラム内容により加減あり)
C: レベル Easy の問題がある程度解ける(解けない場合がある)。
B: レベル Easy の問題がすべて解ける。
A: レベル Normal の問題が解ける。
A+: レベル Hard 以上の問題が解ける。
制限事項:
・個々の関数が 100 行を超えてはならない。(不自然な改行をしないこと)
・すべての関数にコメントを付ける。
問題読み込み・盤面表示プログラム
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int board[9][9];
//盤面[y][x]
//テキストファイルから問題を読み込み
void loadBoard(char *filename)
{
int i, j;
char buff[20];
FILE *fp = fopen(filename,"r");
for(i=0; i<9; i++) {
fgets(buff, 20, fp);
//1行読み込み
for(j=0; j<9; j++) {
if(isdigit(buff[j])) {
//数字か否か
board[i][j] = buff[j]-'0';//数字のASCIIコードから数値へ変換
} else {
board[i][j] = 0; //数字でなければ0:未入力マス
}
}
}
fclose(fp);
}
//現在の盤面を画面に表示
void printBoard()
{
int i, j;
for(i=0;i<9;i++) {
if(i%3==0) printf("|---+---+---|\n");
for(j=0;j<9;j++) {
if(j%3==0) printf("|");
if(board[i][j]!=0) {
printf("%d",board[i][j]);
} else {
printf(" ");
}
}
printf("|\n");
}
printf("|---+---+---|\n");
}
//メイン関数
void main(int argc, char *argv[])
{
loadBoard("Easy_1.txt");
printBoard();
}
入力ファイル例
.8.627..4
..3....96
4.6......
6.8.....1
7.1....4.
.4.1.56..
96..1.435
...9..12.
.1.5...6.
276000080
300800015
500209700
082300400
000050000
001004360
004508007
160003004
030000521
31
8 6 9
2 7 3
97 3
4
5 86
6 2 1
7 9 3
54
ナンバープレイス / 数独*
ルール
1.
空いているマスに 1~9 のいずれかの数字を入れる。
2.
各行・列、および太線で囲まれた 3×3 のブロックに同じ数字が複数入ってはいけない。
解法
1.
解法(Easy):既に決まった数字について、同じ行・列・ブロックの可能性を消す。
(ア) 各行・列・ブロックについて、ある数字の候補マスが1つになれば確定(単独候補マス)
。
・左上のブロックでは、
「7」を入れられるマスは[c-2]しかない。
(イ) そのマスの候補が1つの数字だけになれば確定(単独候補数字)
。
・マス[c-2]に入れられる数字は「5」しかない。
1 2 3 4 5 6 7 8 9
a
7
b
7
a
b
c
c
d
d
e
7
1 4
3
9 2
8
e
f
f
g
g
h 7
h
i
i
(ア)単独候補マス
*
1 2 3 4 5 6 7 8 9
6
7
(イ)単独候補数字
海外では「SUDOKU」が一般的名称になっているが、日本では「数独」はニコリの登録商標であるた
め、一般に「ナンバープレイス」と呼ばれることが多い。
2.
解法(Normal)
:候補数字の配置による絞り込み
あるブロックにおいて、ある候補数字の位置が一つの行(列)のみにある場合、
「他のブロックの
同じ行(列)
」および「同じブロックの他の行(列)
」においてその候補数字の可能性がなくなる。
(ア) 下列中央ブロックにおける「9」の候補位置が列6にしかない場合、その上方のブロックでは
列6の「9」の可能性がなくなる。
(イ) 行 d における「9」の候補位置が中央ブロックにしかない場合、このブロックでは他の行 e,f の
「9」の可能性がなくなる。
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
a
a
b
b
c
c
d
d 3
e
e
f
f
g
h
i
1 7
9
5 7
1
9
i
(ア)
3.
6
g
h
5 6
9
(イ)
解法(Hard):「定員確定法」または「2国同盟、3国同盟」
ある行(または列・ブロック)に n 個の数字の組の候補が n マスしかない場合、そのマスの属する
全ての行・列・ブロックにおいて他のマスにそれらの数字を入れることはできない。
4.
解法(Very Hard):「X-Wing」
「XY-Wing」
「Sword-Fish」
「Jerry Fish」「浜田ロジック」など
ネットで検索のこと。
5.
解法(最後の手段):「全列挙法」
「背理法」
あるマスの数字を仮定し、その仮定のもとにパズルを解いてゆく。最後まで解けなければ(矛盾が
発生すれば)最初の仮定を破棄し、別の仮定を試す。
参考 URL:http://www.geocities.jp/dentyuuame/game/numple.html