前回までの状況はこちら。
前回の修正でほぼほぼ解析ロジックは完成したので、もうちょっと使い勝手が良いように、ファイル入出力とエラー処理に手を加えます。
まずは、いままで出力ファイル名が固定化されていたので、コマンドの第二パラメータに出力ファイルを入力するようにします。
具体的には、ファイル入出力が一つのstaticクラスで行っていたのを分割します。
入力ファイルの読み込みは、最初の1回しか実行しないので、staticクラスで、出力ファイルは何度も使用するので、通常のクラスで定義し直します。
出力クラスのコンストラクタで出力ファイル名を指定します。
class FileOutput
{
private string _filename;
public FileOutput(string filename)
{
_filename = filename;
if (File.Exists(_filename) == true)
{
File.Delete(_filename);
}
}
public void Output(Square[,] sq)
{
using (var stream = new StreamWriter(_filename, true))
{
for (int row = 0; row < 9; row++)
{
for (int col = 0; col < 9; col++)
{
stream.Write(sq[row, col].GetValue());
}
stream.Write("\r\n");
}
stream.Write("\r\n");
}
}
public void Output(bool[,] sq)
{
using (var stream = new StreamWriter(_filename, true))
{
for (int row = 0; row < 9; row++)
{
for (int col = 0; col < 9; col++)
{
if (sq[row, col] == true)
{
stream.Write(1);
}
else
{
stream.Write(0);
}
}
stream.Write("\r\n");
}
stream.Write("\r\n");
}
}
public void Output(int row, int col, int value)
{
using (var stream = new StreamWriter(_filename, true))
{
stream.Write("[{0},{1}] => {2}\r\n", row, col, value);
}
}
public void Output(string text)
{
using (var stream = new StreamWriter(_filename, true))
{
stream.Write("{0}\r\n", text);
}
}
public void Output(List<Square> list)
{
using (var stream = new StreamWriter(_filename, true))
{
stream.Write("候補 ");
foreach (Square s in list)
{
stream.Write("[{0},{1}]", s.Row, s.Col);
}
stream.Write("\r\n");
}
}
}
メイン関数で出力ファイル名を取得します。
第二パラメータが無かった場合は、自動的に入力ファイイル名.outputというファイル名で出力させます。
static void Main(string[] args)
{
// パラメータチェック
if (args.Length < 1)
{
Console.WriteLine("usage : sudoku.exe [input file] [output file]");
return;
}
// ファイルの存在を確認
string filePath = Environment.CurrentDirectory + "\\" + args[0];
if (File.Exists(filePath) == false)
{
Console.WriteLine("File not found.");
return;
}
// 出力ファイル名
string outfile = null;
if (args.Length == 2)
{
outfile = Environment.CurrentDirectory + "\\" + args[1];
}
else
{
outfile = filePath + ".output";
}
var sq = FileRead.OpenFile(filePath);
if(sq == null)
{
return;
}
Sudoku sudoku = new Sudoku(sq, outfile);
sudoku.run();
}
最後に、入力データのエラー処理を改善します。
具体的には、例えば、行と列が10以上あった場合、そして、数字以外の値が入っていた場合、数字が10以上入っていた場合はエラーで終了させます。
static class FileRead
{
/**
* ファイルからデータを取得する
*/
public static Square[,] OpenFile(string filePath)
{
int[,] matrix = new int[9, 9];
// ファイルを開く
bool error = false;
using (var stream = new StreamReader(filePath))
{
int row = 0;
while (stream.EndOfStream == false)
{
if (row >= 9)
{
error = true;
break;
}
string lineText = stream.ReadLine();
var val = lineText.Split(',');
if (val.Length > 9)
{
error = true;
break;
}
int col = 0;
foreach (var v in val)
{
int i;
if (int.TryParse(v, out i))
{
if(i >= 10)
{
error = true;
break;
}
matrix[row, col] = i;
}
else
{
error = true;
break;
}
col++;
}
if (error)
{
break;
}
row++;
}
}
if (error)
{
Console.WriteLine("Illegal format.");
return null;
}
Square[,] ret = new Square[9, 9];
for (int row = 0; row < 9; row++)
{
for (int col = 0; col < 9; col++)
{
Square sq = new Square(matrix[row, col], row, col);
ret[row, col] = sq;
}
}
return ret;
}
}
そして、最終的にgitHubのようなソースになりました。
https://github.com/takishita2nd/sudoku