想像以上にボリューミー。
こちらのレシピ動画を参考にしました。
使用するのはもやしとひき肉だけ。
それらを手でこねて焼くだけという、簡単に作れてしまいます。
しかも、半分はもやしなので、かなりのかさ増しハンバーグになりました。
ダイエットにも最適だと思います。
これだけ簡単で美味しいとなると、料理も楽しくなりますね。
さて、前回までで、マップ関連は完成しました。
次回からバトル関連を作成していこうと思うのですが、バトルのルールを決めておく必要があります。
まずは、コンピューターだけでバトルさせて、どの市町村が勝利するかを見てみたいと思います。
ということで以下の様にしていました。
こんな感じでどうだろうか?
まずは、作ってみて動かしてみましょうか。
前回までの状況はこちら。
最新ソースはこちら(gitHub)
https://github.com/takishita2nd/HokkaidoWar
さて、前回で隣接都市とのリンクを作成しましたが、
1つ問題がありまして、
それは離島とのリンクです。
今のままではマスの隣接関係でリンクを確認しているので、マスが離れている離島との隣接関係がありません。
具体的には、
この隣接関係を作成しなければ行けません。
※ちなみに、天売島、焼尻島は羽幌に属しています。

今回はUp(),Down(),Left(),Right()処理に例外を入れることで対応します。
マップそのものが変わってしまうと、ここの処理も修正しなければ鳴りませんが、他に有効な手段が思いつかないので、仕方がありません。
class Map
{
public Map Up {
get {
var field = Singleton.GetFieldMap();
if(_x == 18 && _y == 0)
{
return field.GetMap(23, 0);
}
else if(_x == 23 && _y == 0)
{
return field.GetMap(18, 0);
}
else if (_x == 20 && _y == 1)
{
return field.GetMap(18, 0);
}
else
{
return field.GetMap(_x, _y - 1);
}
}
}
public Map Down
{
get
{
var field = Singleton.GetFieldMap();
if(_x == 18 && _y == 0)
{
return field.GetMap(19, 1);
}
else
{
return field.GetMap(_x, _y + 1);
}
}
}
public Map Left
{
get
{
var field = Singleton.GetFieldMap();
if (_x == 2 && _y == 29)
{
return field.GetMap(0, 29);
}
else if(_x == 19 && _y == 1)
{
return field.GetMap(18, 0);
}
else if (_x == 23 && _y == 0)
{
return field.GetMap(20, 1);
}
else
{
return field.GetMap(_x - 1, _y);
}
}
}
public Map Right
{
get
{
var field = Singleton.GetFieldMap();
if (_x == 0 && _y == 29)
{
return field.GetMap(2, 29);
}
else if(_x == 18 && _y == 0)
{
return field.GetMap(20, 1);
}
else if (_x == 20 && _y == 1)
{
return field.GetMap(23, 0);
}
else
{
return field.GetMap(_x + 1, _y);
}
}
}
こんな感じで離島とのリンク関係を強引に作りました。
食べ過ぎちゃった(てへぺろ

こちらの記事で購入したジンギスカンセットでジンギスカンを食べました。
使用したお肉はこれ。

行者ニンニク入り味付けラムです。

うん、美味しそうである。
野菜は、もやし、玉ねぎ、ニラを用意しました。

そして忘れちゃいけないのはうどん。

準備完了。

焼くぞー。

味付けラムを焼くときは、火を強くしすぎないことです。
大体弱めの中火ぐらい。
強すぎると肉汁が蒸発してしまうので。
そうすると、肉汁が鍋の縁に貯まっていきます。

ここにうどんを投入。

肉汁でうどんを煮込みます。

このうどんが美味い。
いやー1kgペロッと食べちゃった。
美味かった。
そして後片付けである。
このジンギスカン鍋、キャプテンスタッグ製のものです。
これは鋳物なので、洗剤は使用しません。
たわしで表面の汚れを落とします。
しかし、ジンギスカンのタレが焦げて、たわしでも落とせない焦げ付きがあるんですよ。
その場合は、ガスコンロで空焚きします。
ガスボンベ一本使い切るぐらい。
空焚きしていると、次第に焦げつきが剥がれてくるんです。
あとは、この焦げをたわしで落として、
乾燥後にオリーブオイルを塗る。

これが出来るのは、品物が良いのと、お手入れがしっかりしているからですね。
さすがキャプテンスタッグ。
いやーしばらくジンギスカンはいいけど、また食べたいね。
良かった良かった。
ダイエット支援ツールは以下のリンク先で運用中です。
ダイエット支援ツールに食事管理機能を追加したいと思います。
ダッシュボードはこんな感じにしようと思います。

三栄要素をレーダーチャートで表示させます。
Chart.jsを調べたらこんな感じのチャートが表示出来るみたいです。

また、この画面からデータ入力も出来るようにしたいと思います。
詳細画面はこんな感じ。

日付毎に三栄要素とカロリーを一覧表示。
さらに編集画面へのリンクを用意します。
編集画面はこんな感じ。

朝昼晩毎に、食事と栄養素とカロリーを表示します。
入力、編集も可能にします。
その他、ちょっとFitBitアプリの機能っぽいものに仕上げたいと思います。
じゃあ、次回から取りかかりますか。
前回までの状況はこちら。
前回はスイッチをはんだ付けして、ブレッドボードに取り付けました。
今回はこのスイッチを動かしてみます。
import RPi.GPIO as GPIO
import time
X_p = 0
Y_p = 0
Z_p = 0
A_p = 0
B_p = 0
C_p = 0
D_p = 0
def PinsInit(x, y, z, a, b, c, d):
global X_p
global Y_p
global Z_p
global A_p
global B_p
global C_p
global D_p
X_p = x
Y_p = y
Z_p = z
A_p = a
B_p = b
C_p = c
D_p = d
GPIO.setup(X_p, GPIO.OUT)
GPIO.setup(Y_p, GPIO.OUT)
GPIO.setup(Z_p, GPIO.OUT)
GPIO.setup(A_p, GPIO.IN)
GPIO.setup(B_p, GPIO.IN)
GPIO.setup(C_p, GPIO.IN)
GPIO.setup(D_p, GPIO.IN)
GPIO.output(X_p, GPIO.HIGH)
GPIO.output(Y_p, GPIO.HIGH)
GPIO.output(Z_p, GPIO.HIGH)
def SW_Sample():
col = 1
swState = [0] * 12
while True:
if col == 1:
GPIO.output(X_p, GPIO.LOW)
GPIO.output(Y_p, GPIO.HIGH)
GPIO.output(Z_p, GPIO.HIGH)
elif col == 2:
GPIO.output(X_p, GPIO.HIGH)
GPIO.output(Y_p, GPIO.LOW)
GPIO.output(Z_p, GPIO.HIGH)
else:
GPIO.output(X_p, GPIO.HIGH)
GPIO.output(Y_p, GPIO.HIGH)
GPIO.output(Z_p, GPIO.LOW)
# 1押下
if swState[1] == 0 and col == 1 and GPIO.input(D_p) == 0:
# チャタリング回避
time.sleep(0.05)
if GPIO.input(D_p) == 0:
print("push 1")
swState[1] = 1
# 1押下戻し
elif swState[1] == 1 and col == 1 and GPIO.input(D_p) == 1:
print("release 1")
swState[1] = 0
# 2押下
if swState[2] == 0 and col == 2 and GPIO.input(D_p) == 0:
# チャタリング回避
time.sleep(0.05)
if GPIO.input(D_p) == 0:
print("push 2")
swState[2] = 1
# 2押下戻し
elif swState[2] == 1 and col == 2 and GPIO.input(D_p) == 1:
print("release 2")
swState[2] = 0
# 3押下
if swState[3] == 0 and col == 3 and GPIO.input(D_p) == 0:
# チャタリング回避
time.sleep(0.05)
if GPIO.input(D_p) == 0:
print("push 3")
swState[3] = 1
# 3押下戻し
elif swState[3] == 1 and col == 3 and GPIO.input(D_p) == 1:
print("release 3")
swState[3] = 0
# 4押下
if swState[4] == 0 and col == 1 and GPIO.input(C_p) == 0:
# チャタリング回避
time.sleep(0.05)
if GPIO.input(C_p) == 0:
print("push 4")
swState[4] = 1
# 4押下戻し
elif swState[4] == 1 and col == 1 and GPIO.input(C_p) == 1:
print("release 4")
swState[4] = 0
# 5押下
if swState[5] == 0 and col == 2 and GPIO.input(C_p) == 0:
# チャタリング回避
time.sleep(0.05)
if GPIO.input(C_p) == 0:
print("push 5")
swState[5] = 1
# 5押下戻し
elif swState[5] == 1 and col == 2 and GPIO.input(C_p) == 1:
print("release 5")
swState[5] = 0
# 6押下
if swState[6] == 0 and col == 3 and GPIO.input(C_p) == 0:
# チャタリング回避
time.sleep(0.05)
if GPIO.input(C_p) == 0:
print("push 6")
swState[6] = 1
# 6押下戻し
elif swState[6] == 1 and col == 3 and GPIO.input(C_p) == 1:
print("release 6")
swState[6] = 0
# 7押下
if swState[7] == 0 and col == 1 and GPIO.input(B_p) == 0:
# チャタリング回避
time.sleep(0.05)
if GPIO.input(B_p) == 0:
print("push 7")
swState[7] = 1
# 7押下戻し
elif swState[7] == 1 and col == 1 and GPIO.input(B_p) == 1:
print("release 7")
swState[7] = 0
# 8押下
if swState[8] == 0 and col == 2 and GPIO.input(B_p) == 0:
# チャタリング回避
time.sleep(0.05)
if GPIO.input(B_p) == 0:
print("push 8")
swState[8] = 1
# 8押下戻し
elif swState[8] == 1 and col == 2 and GPIO.input(B_p) == 1:
print("release 8")
swState[8] = 0
# 9押下
if swState[9] == 0 and col == 3 and GPIO.input(B_p) == 0:
# チャタリング回避
time.sleep(0.05)
if GPIO.input(B_p) == 0:
print("push 9")
swState[9] = 1
# 9押下戻し
elif swState[9] == 1 and col == 3 and GPIO.input(B_p) == 1:
print("release 9")
swState[9] = 0
# *押下
if swState[10] == 0 and col == 1 and GPIO.input(A_p) == 0:
# チャタリング回避
time.sleep(0.05)
if GPIO.input(A_p) == 0:
print("push *")
swState[10] = 1
# *押下戻し
elif swState[10] == 1 and col == 1 and GPIO.input(A_p) == 1:
print("release *")
swState[10] = 0
# 0押下
if swState[0] == 0 and col == 2 and GPIO.input(A_p) == 0:
# チャタリング回避
time.sleep(0.05)
if GPIO.input(A_p) == 0:
print("push 0")
swState[0] = 1
# 0押下戻し
elif swState[0] == 1 and col == 2 and GPIO.input(A_p) == 1:
print("release 0")
swState[0] = 0
# #押下
if swState[11] == 0 and col == 3 and GPIO.input(A_p) == 0:
# チャタリング回避
time.sleep(0.05)
if GPIO.input(A_p) == 0:
print("push #")
swState[11] = 1
# #押下戻し
elif swState[11] == 1 and col == 3 and GPIO.input(A_p) == 1:
print("release #")
swState[11] = 0
col += 1
if col > 3:
col = 1
def __main__():
GPIO.setmode(GPIO.BCM)
GLCD.PinsInit(20, 7, 8, 9, 18, 19, 10, 11, 12, 13, 14, 15, 16, 17)
GLCD.GLCDInit()
GLCD.GLCDDisplayClear()
roop = 10 * 60 * 60
try:
while True:
SW.PinsInit(21, 22, 23, 24, 25, 26, 27)
SW.SW_Sample()
time.sleep(0.1)
except KeyboardInterrupt:
GLCD.GLCDDisplayClear()
GPIO.cleanup()
__main__()
思った以上に長くなった。
まずピン設定ですが、X,Y,Zに繋がるピンが出力用、A,B,C,Dに繋がるピンが入力用になります。
そして、X,Y,ZはHIGHで初期化します。
サンプル処理では、whileの無限ループの中で、
X=LOW、Y=HIGH、Z=HIGH
X=HIGH、Y=LOW、Z=HIGH
X=HIGH、Y=HIGH、Z=LOW
を繰り返します。
その中で、A~Dの中にLOWの信号があれば、X,Y,ZのLOW出力の状態とA~DのLOW入力の状態を

この表に当てはめて、押下されたボタンを特定します。
ただ、無限ループで動いているので、普通に信号だけを見ていると、ものすごい数の入力をプログラムが検出してしまうので、スイッチの状態を保持し、その値と変化があるか、ということを確認する必要があります。
また、物理スイッチが入ったとき、信号が一瞬の短い間、HIGH/LOWを繰り返すような信号になります。
これをチャタリングといいます。
何も対策していないと、スイッチ1回しか押していなくても、プログラムは数回スイッチを押したと判断してしまうことがあります。
なので、それを回避するために、スイッチの検出を行った後、50ミリ秒後にもう一度信号を確認、信号に変化が無ければスイッチオンとする、という風にする必要があります。
実行結果はこうなりました。
pi@raspberrypi:~/RaspiDisplayMonitor $ python3 main.py
push 1
release 1
push 2
release 2
push 3
release 3
push 4
release 4
push 5
release 5
push 6
release 6
push 7
release 7
push 8
release 8
push 9
release 9
push *
release *
push 0
release 0
push #
release #
push 1
push #
release 1
release #
push 2
push 8
release 8
push 9
release 9
release 2
同時押しも動きましたね。
これで基本的な動きは出来ました。
次回は、これをモジュール化して今までのプログラムと組み合わせていましょう。

前回までの状況はこちら。
最新ソースはこちら。(gitHub)
https://github.com/takishita2nd/Picross
今回からは、デバッグ作業をよりやりやすくするために、過去問を一括して解いて正しく解析できているかを確認する仕組みを作っていきます。
そのためには、解析結果をファイルに出力して、照合対象となるデータを作成する必要があります。
なので、以下の様なコードを作成しました。
class FileAccess
{
private const string _outputfile = "output.dat";
public static void Output(BitmapData[,] bitmapDatas, int row, int col)
{
if (File.Exists(_outputfile) == true)
{
File.Delete(_outputfile);
}
using (var stream = new StreamWriter(_outputfile, true))
{
for(int r = 0; r < row; r++)
{
for(int c = 0; c < col; c++)
{
if(bitmapDatas[r, c].IsPainted())
{
stream.Write(1);
}
else
{
stream.Write(0);
}
}
stream.Write("\r\n");
}
}
}
解析済みのデータbitmapDatasを受け取り、それをファイルに出力します。
色塗りの部分は1、マスク部分は0となるイメージです。

このデータが、

こんな感じになります。
問題データを

こんな感じで用意して、
解析結果データを、

こんな感じで作成しました。
数字で問題と解答が結びついているイメージです。
さて、これで必要な準備が出来ました。
毎回、ピクロスネタをやるとコーディングに膨大な時間を使ってしまうので、今回はサックリやって、続きは次回やります。

次は、スイッチを繋げてみます。
購入したのはスイッチが12個付いている簡易的なキットです。

この基板に部品を設置して、はんだ付けします。

ダイオード。
向きに注意。
向きを間違えると動きません。
黒い印が付いている方がカソードになります。
基板に向きがきちんと書かれているので、それに従って配置します。

抵抗。

で、これがスイッチ。

はんだ付け完了。

ブレッドボードに設置。
さらに配線も接続します。

もうこれ以上部品を設置するのは不可能ですね。
ちなみに、配線は以下の様になっています。
12SWとあるのが、今回追加したスイッチモジュールです。

スイッチが押されたかの確認は、
X=LOW、Y=HIGH、Z=HIGH
X=HIGH、Y=LOW、Z=HIGH
X=HIGH、Y=HIGH、Z=LOW
の状態を繰り返し、そのときのA,B,C,Dの出力状態(押されたときにLOWになる)を確認します。
XYZとABCDの組み合わせはこんな感じです。

回路はこんな感じ。

これを見たところ、おそらく、スイッチを押していないときは、▼から入ってきた入力がそのままA~Dに流れていく(HIGH)のでしょう。
そして、X~YがLOWの時にスイッチを押すと、▼の入力がスイッチの方へ流れていくので、その結果、A~DがLOWとなるのでは、と思います。
まぁ、この回路を流用すれば、自分で部品を調達してスイッチ回路を組むことも可能でしょう。
次回はこれを動かすためのプログラムコードを作成します。
ほとんどドライブするだけの旅。

2日目は、1日目の問題点を踏まえまして、
長万部~豊浦間のルートを避けました。
また、黒松内までは高速料金そんなに高くなかったので、高速道路を使って一気に時間を稼ぐ作戦です。
なぜなら、この日の北海道、豪雨の予報だったので。
ということで、二日目は、蘭越~倶知安~小樽ルートです。
カーナビがはじき出しました。
朝8時前にホテルを出発。
そして、函館出る前にハセガワストアでやきとり弁当を購入して臨みました。
ただ、これでも問題点はありまして、
まず、大沼公園IC~八雲PAまで休憩できない。
これは、高速を使う以上仕方が無い。
そして、

この区間も休憩無し。
しかも、道の駅あかいがわを素通りしたため、実際は倶知安からノンストップでした。
なんだよ、このぐねぐねした道(毛無峠だよ)。
函館~札幌間、どういうルートが正解なんですかね?
誰か教えて。
でも、なんとか、事故も無く、午後4時までに札幌に到着し、レンタカーも時間内に返却できました。
次行く時は特急とかバスとか使うわ。

ニセコの道の駅で購入したおつまみで乾杯。
お疲れ様でした。