「技術」カテゴリーアーカイブ

【C#】【ピクロス】【ALTSEED】絵を描画するエリアを作成する

前回までの状況はこちら。

最新ソースはこちら。

https://github.com/takishita2nd/Picross

今回は、前回のソースコードを元に、クラス構成を変えて作り直していきます。

まずはリソースを管理するクラス。

class Resource
{
    private static asd.Texture2D _picrossTexture = null;
    public static asd.Texture2D GetPicrossTexture()
    {
        if (_picrossTexture == null)
        {
            _picrossTexture = asd.Engine.Graphics.CreateTexture2D("square.png");
        }
        return _picrossTexture;
    }
}

数独の時と同じです。

画像などの外部リソースは、読み込んだ一個のオブジェクトをみんなで使い回すような仕組みにしています。

こうすることで、外部リソース読み込み速度が向上し、使用メモリも少なくなります。

シングルトンに近いイメージですね。

絵を構成するオブジェクトのベース部分を作成します。

class ObjectBase
{
    protected int _x;
    protected int _y;
    protected asd.TextureObject2D _backTexture;
    protected asd.TextObject2D _valueText;
    protected int width;
    protected int height;

    public asd.TextureObject2D getBackTexture()
    {
        return _backTexture;
    }

    public asd.TextObject2D getTextObject()
    {
        return _valueText;
    }

    public bool isClick(asd.Vector2DF pos)
    {
        if (pos.X > _x && pos.X < _x + width
            && pos.Y > _y && pos.Y < _y + height)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

これは、数独のObjectBaseクラスと全く同じです。

これをベースにして、絵を書く部分と、数字を入力する部分とで、クラスを派生させて行きます。

絵を書く部分は以下の様に派生させました。

class DrawSquare : ObjectBase
{
    protected int _row;
    protected int _col;
    protected const int setPositionX = 200;
    protected const int setPositionY = 200;

    public DrawSquare(int row, int col)
    {
        width = 32;
        height = 32;
        _row = row;
        _col = col;
        _x = col * width + setPositionX;
        _y = row * height + setPositionY;

        _backTexture = new asd.TextureObject2D();
        _backTexture.Texture = Resource.GetPicrossTexture();
        _backTexture.Position = new asd.Vector2DF(_x, _y);
    }
}

これを使用して実装します。

class PicrossUI
{
    private List<List<DrawSquare>> drawSquares = new List<List<DrawSquare>>();

    public PicrossUI()
    {

    }

    public void Run()
    {
        asd.Engine.Initialize("ピクロス解析ツール", 1000, 800, new asd.EngineOption());

        // 下地
        var background = new asd.GeometryObject2D();
        asd.Engine.AddObject2D(background);
        var bgRect = new asd.RectangleShape();
        bgRect.DrawingArea = new asd.RectF(0, 0, 1000, 800);
        background.Shape = bgRect;

        for(int row = 0; row <10; row++)
        {
            List<DrawSquare> rowList = new List<DrawSquare>();
            for(int col = 0; col <10; col++)
            {
                var square = new DrawSquare(row, col);
                asd.Engine.AddObject2D(square.getBackTexture());
                rowList.Add(square);
            }
            drawSquares.Add(rowList);
        }

        while (asd.Engine.DoEvents())
        {
            asd.Engine.Update();
        }
        asd.Engine.Terminate();
    }
}

今回色を書く部分のマスの数は可変になるので、二次元配列ではなく、Listを使います。

実行結果はこんな感じになりました。

当然、見た目は何も弄っていないので、前回と同じですね。

次回はサイズを変更するダイアログを作成していきます。

【ラズパイ】ディスプレイにいろいろ表示させてみる

こちらのサンプルプログラムを入力します。

https://github.com/raspberrypilearning/astro-pi-guide/blob/master/files/SenseHAT-Cheatsheet.pdf

8×8のLEDディスプレイにいろいろ表示させてみましょう。

ドット点灯

from sense_hat import SenseHat
sense = SenseHat()
sense.set_pixel(0, 0, 255, 0, 0)

インターフェースは(x, y, R, G, B)。

これは(0,0)に赤を点灯します。

色を変えてみます。

sense.set_pixel(0, 0, 155, 100, 10)

表示位置を変えてみます。

sense.set_pixel(1, 1, 155, 100, 10)

1文字表示

from sense_hat import SenseHat
sense = SenseHat()
sense.show_letter("J", text_colour=[155, 100, 10])

ピクチャ表示

このような絵を作成。

from sense_hat import SenseHat
sense = SenseHat()
sense.load_image("creeper.gif", redraw=True)

一応256階調に調整できるので、フルカラー表示できるはずなんですが、あまり細かい違いは分かりません。

回転

from sense_hat import SenseHat
sense = SenseHat()
sense.load_image("creeper.gif", redraw=True)
sense.set_rotation(r=90, redraw=True)

ピクセルマップ

from sense_hat import SenseHat
sense = SenseHat()

R = [255, 0, 0]
W = [255, 255, 255]

pixel_list = [W, W, W, R, R, W, W, W,
              W, W, R, W, W, R, W, W,
              W, W, W, W, W, R, W, W,
              W, W, W, W, R, W, W, W,
              W, W, W, R, W, W, W, W,
              W, W, W, R, W, W, W, W,
              W, W, W, W, W, W, W, W,
              W, W, W, R, W, W, W, W]

sense.set_pixels(pixel_list)

次はセンサーを弄ってみましょう。

【ラズパイ】サンプルプログラムを実行する。

こちらのサンプルプログラムを入力します。

https://github.com/raspberrypilearning/astro-pi-guide/blob/master/program.md

エディターは何でも良いらしい。

from sense_hat import SenseHat
sense = SenseHat()
sense.show_message("Hello my name is Tim Peake")

言語はpythonですな。

実行に必要な物はすでに入っていました。

実行するとこうなりました。

ただ、デフォのエディターだと使いづらいので、ラズパイ用のvscodeをインストールします。

インストール方法はこのやり方で行けた。

https://note.com/yoshiteru11/n/n6521e33ca456

$ wget -qO - https://packagecloud.io/headmelted/codebuilds/gpgkey | sudo apt-key add -

$ sudo su

# . <( wget -O - https://code.headmelted.com/installers/apt.sh )

# exit

【C#】【ピクロス】【Altseed】とりあえず画面を作ってみる。

最新ソースはこちら。

https://github.com/takishita2nd/Picross

とりあえず画面を作ってみます。

クラス構成とか考えずに、

この画像を作成し、これを10×10に並べてみました。

    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            PicrossUI picross = new PicrossUI();
            picross.Run();
        }
    }
    class PicrossUI
    {
        private const int setPositionX = 200;
        private const int setPositionY = 200;

        public PicrossUI()
        {

        }

        public void Run()
        {
            asd.Engine.Initialize("ピクロス解析ツール", 1000, 800, new asd.EngineOption());

            // 下地
            var background = new asd.GeometryObject2D();
            asd.Engine.AddObject2D(background);
            var bgRect = new asd.RectangleShape();
            bgRect.DrawingArea = new asd.RectF(0, 0, 1000, 800);
            background.Shape = bgRect;

            for(int row = 0; row <10; row++)
            {
                for(int col = 0; col <10; col++)
                {
                    var square = new asd.TextureObject2D();
                    square.Texture = asd.Engine.Graphics.CreateTexture2D("square.png");
                    square.Position = new asd.Vector2DF(row * 32 + setPositionX, col * 32 + setPositionY);
                    asd.Engine.AddObject2D(square);
                }
            }

            while (asd.Engine.DoEvents())
            {
                asd.Engine.Update();
            }
            asd.Engine.Terminate();
        }
    }

数独の時は9×9のマスの画像をあらかじめ作成し、表示させていましたが、

これは数独が9×9で固定だからできるためです。

今回はマスの数が可変になるため、1個のマスを並べて使用したいと思います。

中の線が太く見えますが、マスを小さくすればそんなに気にならないかと思います。

ただ、マスのサイズを小さくしすぎると、このマスの中に後々数字を入れることになるので、あまり小さくできません。

今回は32×32ピクセルで作成しましたが、これが妥当なところでしょう。

考慮すべき所は、数字が入るところと色を塗るところが分かるように中の色を変えた方が良いかもしれません。

そこら辺を考慮した上で、クラス構成を考えてみたいと思います。

まずは、マスのサイズを可変に変更できるように作成していきましょう。

【ラズパイ】Sense HATを装着する

これをラズパイに装着します。

これのマニュアルはgitHubにアップされています。

https://github.com/raspberrypilearning/astro-pi-guide

英語です。

チュートリアルに従って装着します。

https://github.com/raspberrypilearning/astro-pi-guide/blob/master/assemble.md

1.GPIO pin extension headerをラズパイに取り付けます。

2.六角柱のやつをラズパイに取り付けてしたからネジ止めします。

3.SENSE HATを取り付けます。

4.最後に上からネジ止めします。

電源ON!

正しくできたかどうか、本当に動くかどうか、次回はサンプルプログラムを作成してみます。

ピクロス解析ツールを作成する!

数独解析ツールはほぼ出来上がってしまったので、

今度はピクロス解析ツールを作成してみようと思います。

自信は無いです。

でもできるところまでやってみます。

数独の時はロジック→UIの順に作成しましたが、今回はUI→ロジックの順に作成していこうと思います。

まず、どんなUIにしようかまとめてみます。

ピクロスは絵のサイズが同じとは限らないので、サイズをフレキシブルに変更できるようにしなければなりません。

あと、数字入力は数独の時に適用したパレット方式が意外と使い勝手が良かったので、今回もその方式を取り入れようと思います。

問題データをセーブ/ロードできるようにした方が良いかなぁ(デバッグが楽)

まぁ、とりあえずやってみます。

【ラズパイ】ラズパイのセットアップ

さぁ、ラズパイをセットアップするぞ。

まずはマイクロSDカードにラズパイOSをインストールします。

マイクロSDカードをPCに接続して、以下のサイトからインストールツールをダウンロードします。

https://www.raspberrypi.org/downloads/

実行するとこんな画面が表示されるので、一番左のリストボックスから使用するOSを選びます。

今回はデフォのRASBIANで。

真ん中のリストボックスでは、インストール先のメディアを選択します。

これは当然SDカードを選択。

この二つを選択すると、一番右のWRITEボタンが有効になります。

WRITEボタンを押すとSDカードにOSが書き込まれます。

終わりました。

マイクロSDカードをラズパイに装着し、電源以外のケーブルなどを接続。

最後に電源ケーブルを接続します。

そうすれば勝手にラズパイが立ち上がります。

立ち上がりました。

初回セットアップに言語設定、Wi-Fi設定、アップデートを行って設定完了。

これで自動的に日本語も使用できます。

あと、設定を変えることろは、VNCを有効にする。

Raspberry Piの設定からVNCの項を有効にすると、他PCからVNCで接続できます。

基本的にはVNC接続で使用していきたいと思います。

さて、次回はアタッチメントをつなげてみましょうか。

数独解析ツールをリリースしました。

まぁいろいろありましたが、数独解析ツールが完成しましたので、ご報告いたします。

ダウンロードはこちら(gitHub)

https://github.com/takishita2nd/sudokuGUI/releases/tag/1.02

zipファイルを解凍してsudokuGUI.exeを実行してください。

操作はマウスでクリックするだけなのでわかりやすくなっていると思います。

何かありましたらコメントください。

あと、ネタもください。

【C#】【ALTSEED】【数独】解析ができなかった場合の対処

前回までの状況はこちら。

最新ソースはこちら(gitHub)

https://github.com/takishita2nd/sudokuGUI

やることの三つ目を解決します。

今のままでは、入力データが不完全な状態で解析ボタンを押してしまうと、アプリが固まってしまいます。

原因は、仮置きロジックの再起処理が無限に実行されてしまっているようです。

なので、仮置きロジックが一定回数呼ばれたら失敗として処理終了させてしまいましょう。

    class Sudoku
    {
        private Square[,] _square;
        private int kariokiCount = 0;

        private Square doKarioki(Square[,] squares)
        {
            Square ret = null;
            List<Square> kariokiList = searchKariokiSquare(squares);
            kariokiCount++;
            if(kariokiCount >= 100)
            {
                return null;
            }

続いて、エラーを表示させる処理を追加します。

エラーは新しいオブジェクトを画面に追加して表示させます。

なので、フォントデータも作り直しです。

    class Message : ObjectBase
    {
        private string _text;
        private const int fontOffsetX = 0;
        private const int fontOffsetY = 0;

        public Message(int x, int y, string text)
        {
            width = 256;
            height = 64;
            _x = x;
            _y = y;
            _text = text;

            _backTexture = new asd.TextureObject2D();
            _backTexture.Position = new asd.Vector2DF(_x, _y);

            _valueText = new asd.TextObject2D();
            _valueText.Text = _text;
            _valueText.Font = Resource.getTextFont();
            _valueText.Position = new asd.Vector2DF(_x + fontOffsetX, _y + fontOffsetY);
        }

        public void show()
        {
            _valueText.Text = _text;
        }

        public void hide()
        {
            _valueText.Text = "";
        }
    }

テクスチャーは使わないので、書かなくても良かったんですけどね。


            // メッセージ
            Message message = new Message(10, 640, "解析に失敗しました");
            asd.Engine.AddObject2D(message.getTextObject());
            message.hide();

こんな感じでAltseedエンジンにテキストを追加します。

最後に、このメッセージの表示をON/OFFする処理を追加します。

    class Button : ObjectBase
    {
        public virtual void onClick(SquareObject[,] squareObjects, Message message)
    class AnalyzeButton : Button
    {
        public override void onClick(SquareObject[,] squareObjects, Message message)
        {
            if(enable == false)
            {
                return;
            }

            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);
            var ret = sudoku.run();
            if(ret == null)
            {
                message.show();
                return;
            }

            for (int row = 0; row < 9; row++)
            {
                for (int col = 0; col < 9; col++)
                {
                    squareObjects[row, col].setValue(ret[row, col].GetValue());
                }
            }
        }
    }
    class ClearButton : Button
    {
        public override void onClick(SquareObject[,] squareObjects, Message message)
        {
            message.hide();
            for (int row = 0; row < 9; row++)
            {
                for (int col = 0; col < 9; col++)
                {
                    squareObjects[row, col].setValue(0);
                }
            }
        }
    }
                        bool isButtonClisk = false;
                        foreach (Button button in buttons)
                        {
                            if (button.isClick(pos))
                            {
                                button.onClick(squareObjects, message);
                                isButtonClisk = true;
                            }
                        }

実装に悩みましたが、onClickにmessageオブジェクトを渡すことで対応させました。

もっとスマートな方法があると思うんですが、次回の開発までの課題にします。

たぶん、ほぼほぼこれで完成だと思います。

【ラズパイ】Raspberry PI4が届いた!

買いました。

Raspberry Pi 4 Model B 2GB RAM。

これの一個前がRaspberry Pi 2 Model Bだったから、それより大幅なパワーアップです。

メモリもプロセッサーも強化されていますが、わかりやすいところで言うと、

HDMIポート1個から、Micro HDMIのポート2つになりました。

4K出力もできるみたいよぉ。

Micro HDMI対応のケーブルなんてほとんど出回っていないので、本体と一緒に注文しました。

Micro HDMI – HDMIのケーブルです。

これが無いと、ディスプレイに画面を表示できません。

そして、もう一つ、左側にあるのが電源です。

端子はUSB-Cなのですが、これを動かすのに3Aの出力が必要なので、一般に出回っているUSB-Cケーブルでは動きません。

これも本体と同時に対応電源を注文しました。

あとは、ストレージとなるMicro SDカード。

これだけでこのラズパイは動かせるのですが、ついでなので、もうちょっと遊べるパーツを買いました。

このボードに温度計、湿度計などなど、あと右下にジョイスティック、8×8のLEDディスプレイが付いているパーツです。

ラズパイ4でも動くはず。

さあ、セットアップするぞ。

この一式はこちらのサイトで購入しました。

https://raspberry-pi.ksyic.com