前回までの状況はこちら。
最新ソースはこちら(gitHub)
https://github.com/takishita2nd/sudokuGUI
やることの二つ目を解決します。
入力データに誤りがある場合は、誤りであると分かった時点でユーザーに知らせることが必要になります。
数独の場合、
オレンジの数字と同じ数字が黄色の範囲に合った場合、すでに数独のルールから逸脱しているため、それが判明した時点で誤りと判断します。
どうやってユーザーに知らせるのかというと、数字フォントの色を赤に変えることで知らせようと思います。
それと同時に解析ボタンも押せないようにガードをかけようと思います。
まずは、フォントの色を変える処理を実装。
リソースの追加。
static class Resource
{
private static asd.Font _fontRed = null;
public static asd.Font getFontRed()
{
if (_fontRed == null)
{
_fontRed = asd.Engine.Graphics.CreateFont("numberRed.aff");
}
return _fontRed;
}
フォントの色を変える処理。
class SquareObject : ObjectBase
{
public enum FontColor
{
Black,
Red
}
public bool isSetValue()
{
if(_value == 0)
{
return false;
}
else
{
return true;
}
}
public void setFontColor(FontColor color)
{
switch (color)
{
case FontColor.Black:
_valueText.Font = Resource.getFont();
break;
case FontColor.Red:
_valueText.Font = Resource.getFontRed();
break;
default:
break;
}
}
ボタンを有効・無効を切り替える処理。
class Button : ObjectBase
{
protected bool enable = true;
public void setEnable(bool enable)
{
this.enable = enable;
}
class AnalyzeButton : Button
{
public override void onClick(SquareObject[,] squareObjects)
{
if(enable == false)
{
return;
}
これを実装。
class SudokuUI
{
private bool checkInputParameter(SquareObject[,] squareObjects)
{
bool conflict = false;
for(int row = 0; row < 9; row++)
{
for(int col = 0; col < 9; col++)
{
if(squareObjects[row,col].isSetValue() == true)
{
int value = squareObjects[row,col].getValue();
bool ret = checkRowNumber(squareObjects, row, col, value);
ret |= checkColNumber(squareObjects, row, col, value);
ret |= check9AreaNumber(squareObjects, row, col, value);
if(ret == true)
{
squareObjects[row, col].setFontColor(SquareObject.FontColor.Red);
conflict = true;
}
}
}
}
return conflict;
}
private bool checkRowNumber(SquareObject[,] squareObjects, int row, int col, int value)
{
for(int c = 0; c < 9; c++)
{
if(c != col &&
squareObjects[row, c].getValue() == value)
{
squareObjects[row, c].setFontColor(SquareObject.FontColor.Red);
return true;
}
}
return false;
}
private bool checkColNumber(SquareObject[,] squareObjects, int row, int col, int value)
{
for (int r = 0; r < 9; r++)
{
if (r != row &&
squareObjects[r, col].getValue() == value)
{
squareObjects[r, col].setFontColor(SquareObject.FontColor.Red);
return true;
}
}
return false;
}
private bool check9AreaNumber(SquareObject[,] squareObjects, int row, int col, int value)
{
int rowStart;
int colStart;
getRowCol9Area(row, col, out rowStart, out colStart);
for (int r = rowStart; r < rowStart + 3; r++)
{
for (int c = colStart; c < colStart + 3; c++)
{
if (r != row && c != col &&
squareObjects[r, c].getValue() == value)
{
squareObjects[r, c].setFontColor(SquareObject.FontColor.Red);
return true;
}
}
}
return false;
}
private void getRowCol9Area(int row, int col, out int rowStart, out int colStart)
{
if (row >= 0 && row <= 2)
{
rowStart = 0;
}
else if (row >= 3 && row <= 5)
{
rowStart = 3;
}
else
{
rowStart = 6;
}
if (col >= 0 && col <= 2)
{
colStart = 0;
}
else if (col >= 3 && col <= 5)
{
colStart = 3;
}
else
{
colStart = 6;
}
}
if (asd.Engine.Mouse.LeftButton.ButtonState == asd.ButtonState.Push)
{
if (mouseHold)
{
if (!palette.isClick(pos))
{
palette.hide();
mouseHold = false;
}
else
{
int value = palette.getClickValue(pos);
if(clickedSquareObject != null)
{
clickedSquareObject.setValue(value);
palette.hide();
mouseHold = false;
}
bool conflict = checkInputParameter(squareObjects);
if(conflict == true)
{
start.setEnable(false);
}
else
{
for (int row = 0; row < 9; row++)
{
for (int col = 0; col < 9; col++)
{
squareObjects[row, col].setFontColor(SquareObject.FontColor.Black);
}
}
start.setEnable(true);
}
}
}
else
ちょっと動作が怪しい気がするけど、、、後で見直す。
checkInputParameter()で数値の重複が無いかを確認し、あれば選択中のマスと同じ値のマスを赤くします。もし重複が無ければ全て黒に戻します。
そして、重複があればボタンを無効化、無ければボタンを有効化します。
動作結果はこうなりました。