串カツが食べたかった。
白石区役所で障害者手帳を更新した後、電話でテイクアウトの注文を入れて、受け取ってきました。



タレは別容器で付属されていました。
そのタレをかけて食べます。
サッポロクラシックも飲んで。
溜まった動画を見ながら。
午後6時に酔い潰れて寝ました。
12時間ぐらい寝たね。
また今日から頑張る。

前回までの状況はこちら。
最新ソースはこちら(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()で数値の重複が無いかを確認し、あれば選択中のマスと同じ値のマスを赤くします。もし重複が無ければ全て黒に戻します。
そして、重複があればボタンを無効化、無ければボタンを有効化します。
動作結果はこうなりました。
前回までの状況はこちら。
最新ソースはこちら(gitHub)
https://github.com/takishita2nd/sudokuGUI
やることの一つ目を解決します。
9×9の範囲が分かれば、対処は簡単です。
9×9は画像なので、幅、高さはプロパティを見ればわかります。
private const int width = 576;
private const int height = 576;
これが分かれば、isClick()を作成。
private bool isClick(asd.Vector2DF pos)
{
if (pos.X > offsetX && pos.X < offsetX + width &&
pos.Y > offsetY && pos.Y < offsetY + height)
{
return true;
}
else
{
return false;
}
}
これを使用します。
if (isButtonClisk == false)
{
if (isClick(pos) == true)
{
mouseHold = true;
palette.show(pos);
for (int row = 0; row < 9; row++)
{
for (int col = 0; col < 9; col++)
{
if (squareObjects[row, col].isClick(pos) == true)
{
clickedSquareObject = squareObjects[row, col];
}
}
}
}
}
こんな感じでどうでしょうか。
新情報まとめました。
【速報】今後追加されるカバー楽曲が決定🎶
— バンドリ! ガールズバンドパーティ! (@bang_dream_gbp) April 24, 2020
『UNION』
『秒針を噛む』
生放送で最新情報をお届け中📣
→https://t.co/WCWwkcY1ik#バンドリ #ガルパ #ガルパ生 pic.twitter.com/mgHMB2wBrx
UNIONはO×Tが2018年11月にリリースされた曲で、アニメ「SSSS.GRIDMAN」のOPでした。
Poppin’Partyのカバーで実装されます。
予想レベル25。
秒針を噛むはずっと真夜中で良いのに。が2018年6月にYouTubeで公開された曲です。
予想レベル26。
【速報】ガルパ初❗リアルライブをイメージしたアプリ内イベント開催💫
— バンドリ! ガールズバンドパーティ! (@bang_dream_gbp) April 24, 2020
5月3日に開催を予定していた、リアルライブ「GBP2020」をイメージしたイベントやガチャを4月30日より開催🎉
生放送で最新情報をお届け中📣
→https://t.co/WCWwkcY1ik#バンドリ #ガルパ #ガルパ生 pic.twitter.com/hOgVNDzm7s
5/3に開催予定だったガルパーティ2020に合わせてゲーム内でもイベントが実施されます。
【速報】リアルライブをイメージした、期間限定スキンの追加決定❣️
— バンドリ! ガールズバンドパーティ! (@bang_dream_gbp) April 24, 2020
5月3日15時より、リアルライブの会場をイメージした、ライブ背景・レーン・判定ラインを追加いたします✨#バンドリ #ガルパ #ガルパ生 pic.twitter.com/38DZzBaf6C
うーむ、仕方が無いとは言え、悔しい・・・。
追加バンドRASの情報も公開されました。
【速報】RAISE A SUILENのキービジュアル初公開🎉
— バンドリ! ガールズバンドパーティ! (@bang_dream_gbp) April 24, 2020
アプリ内でのRAISE A SUILENメンバーのキービジュアルを公開🎧
生放送で最新情報をお届け中📣
→https://t.co/WCWwkcY1ik#バンドリ #ガルパ #ガルパ生 pic.twitter.com/iTEBSVda3Z
【速報】RAISE A SUILENのバンドストーリー追加決定📚
— バンドリ! ガールズバンドパーティ! (@bang_dream_gbp) April 24, 2020
6月に前編、8月に後編をアプリ内イベントにて公開いたします🎶
生放送で最新情報をお届け中📣
→https://t.co/WCWwkcY1ik#バンドリ #ガルパ #ガルパ生 pic.twitter.com/xllexeifYf
6月のイベントにてバンドイベント公開ということは、それより前に実装が確実のようです。
5月実装説ありえるぞ。
【速報】『A DECLARATION OF ×××』が4月25日に追加決定🎧
— バンドリ! ガールズバンドパーティ! (@bang_dream_gbp) April 24, 2020
6月のRAISE A SUILENメンバー登場に先駆けて、RAISE A SUILENのオリジナル楽曲を4月25日に追加いたします💿✨
生放送で最新情報をお届け中📣
→https://t.co/WCWwkcY1ik#バンドリ #ガルパ #ガルパ生 pic.twitter.com/hLThFcFyST
RAS実装に先行して楽曲も25日に追加されます。
予想レベル25。
リモートで放送するというのも新鮮でありなのですが、
早くコロナ収まって欲しいですね。
前回までの状況はこちら。
とりあえず、解析処理を行い、結果を表示するところまで完成しましたが、これだけではまだツールとしては完成ではありません。
まだまだ手を加えなければならないところがあります。
それは以下の3つです。
こんなところですかね。
具体的にどう対応するかはおいおい考えるとして、
まずは簡単に対処できそうな所から対処していこうと思います。
前回までの状況はこちら。
最新ソースはこちら(gitHub)
https://github.com/takishita2nd/sudokuGUI
解析処理を実行する処理を作成します。
作り方は前回のクリアボタンと同じです。
Buttonクラスを継承して、AnalyzeButtonクラスを作成します。
class AnalyzeButton : Button
{
public AnalyzeButton() : base(600, 570, "解析開始")
{
}
public override void onClick(SquareObject[,] squareObjects)
{
Square[,] squares = new Square[9, 9];
for (int row = 0; row < 9; row++)
{
for (int col = 0; col < 9; col++)
{
squares[row, col] = new Square(squareObjects[row, col].getValue(), row, col);
}
}
Sudoku sudoku = new Sudoku(squares, null);
sudoku.run();
for (int row = 0; row < 9; row++)
{
for (int col = 0; col < 9; col++)
{
squareObjects[row, col].setValue(squareObjects[row, col].getValue());
}
}
}
}
これを実装します。
// ボタン
List<Button> buttons = new List<Button>();
Button clear = new ClearButton();
asd.Engine.AddObject2D(clear.getBackTexture());
asd.Engine.AddObject2D(clear.getTextObject());
buttons.Add(clear);
Button start = new AnalyzeButton();
asd.Engine.AddObject2D(start.getBackTexture());
asd.Engine.AddObject2D(start.getTextObject());
buttons.Add(start);
// パレット
palette = new Palette();
palette.setEngine();
// Altseedが進行可能かチェックする。
while (asd.Engine.DoEvents())
{
asd.Vector2DF pos = asd.Engine.Mouse.Position;
if (!mouseHold)
{
for (int row = 0; row < 9; row++)
{
for (int col = 0; col < 9; col++)
{
squareObjects[row, col].updateTexture(pos);
}
}
foreach(Button button in buttons)
{
button.updateTexture(pos);
}
}
else
{
palette.updateTexture(pos);
}
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;
}
}
}
else
{
bool isButtonClisk = false;
foreach (Button button in buttons)
{
if (button.isClick(pos))
{
button.onClick(squareObjects);
isButtonClisk = true;
}
}
if (isButtonClisk == false)
{
mouseHold = true;
palette.show(pos);
for (int row = 0; row < 9; row++)
{
for (int col = 0; col < 9; col++)
{
if (squareObjects[row, col].isClick(pos) == true)
{
clickedSquareObject = squareObjects[row, col];
}
}
}
}
}
}
// Altseedを更新する。
asd.Engine.Update();
}
各種ボタン系はButtonリストでまとめておき、updateTexture()、isClick()、onClick()処理をforeachでまとめて処理できるように修正しています。
これで解析までできるはず。
ん?
あああ!
今の解析処理、解析結果をテキストに吐き出す処理のままだった!
これは解析処理にも修正をいれなくては。。。
ここまで来たので、修正しました。
あああ、この瞬間がたまらない!
これこそがプログラマーの喜び!
最近リリースされたらしい。
今までは仮想環境にスマホをエミュレートしていた感じで動作していたのですが、
新しいクライアントソフトは完全にPC用に作られたものです。
まずホーム画面。
広い。
スマホの画面が横に二つ付いたような画面の広さ。
そして、待望の、ゲームパッド対応。
PC用のコントローラーで操作できます。
操作方法はこんな感じ。
キーバインドで配置を変更できます。
あと、左スティックで仮想カーソルを動かすこともできますが、マウスの方が早いので、戦闘以外はそちらの方が良いと思います。
それでは、白熱のバトルの様子をご覧ください。
これはもうスマホには戻れんわ。
ちょっと最近は放置気味だったけど頑張ってみるか。