ナンプレプログラム途中経過。ひとまず最終回メニュー操作、メイン関数、makefileについて。 前回はセッティング、というかncursesの仕様について振り返った
メニュー
ヘッダファイル
なんでグローバル変数を置いたのか…………いる?要らなくない?
menu.c
int LS[9] = {0,1,2,4,5,6,8,9,10}; int RS[9] = {1,5,9,15,19,23,29,33,37};
なぜかここにもあるグローバル変数。せめてまとめろ。これは表示の時に使う。区切り線も勘案した表示上の座標。
後々わかったが、インクルードファイルの方に配列を初期化して書くとコンパイルできない。menu.cとmain.cの両方にmenu.hをインクルードしているので両方で展開されて衝突する。
- void menu()
ループを回して、
findAllOnlyOne(); //menu.c内、確定できるところを見つける showAllTest(); //calc.c内、表示処理 markNow(now); //menu.c内、現在地を表示 printmenu(); //メニュー画面を表示 ch = getch(); /* chにキーを入れ、それにより分岐 */ checkNumAll(); /calc.c内/全マスで確定するか判断 refresh(); //ncurses.h 表示。
findAllOnlyOne();はループの後ろで良かったのでは
void print menu() 冒頭の
printw("now(%d, %d, in %d): ", LINE(now), ROW(now), BLOCK(now));
要らん、ていうか上書きされるやん。デバッグの時に表示してたところだvoid udrl(int ch) 入力が方向キーだった時の動作
markNow(int n) 現在地のマス
n
を$ $
で強調表示するfindAllOnlyOne()
for(i: 全マス) for(j: 0~8) if(マスiの候補jが存在するなら) if(ifOnlyOne(i, j)) //jで確定できるなら inputNum(i, j+1) //マスiに数字jを確定
二重のifは
&&
でよかった
- void changeKouho() まだ自動化できてない分、手動で候補のフラグを変更する関数。これで候補を削ると確定するところがあったりする。
//changeに変更する候補を入れた後 masu[now].kouho[change] = masu[now].kouho[change] ? 0 : 1;
これは三項演算子。以下のif文と同値。
if(masu[now].kouho[change]){ masu[now].kouho[change] = 0; }else{ masu[now].kouho[change] = 1; }
要は0と1の反転なんだけど別の書き方ないかね
- -1して絶対値をとる(
0 -> |-1| = 1, 1 -> 0
)- 1とのXOR
^
をとる(1^1 = 0, 0^1 = 1
)こっちの方がスマートだ
メイン・makefile
main.c
メイン関数。
int main(void){ startGame(); //開始時設定 reset(); //盤面リセット getch(); //何かしらのキー入力まで待機 menu(); //これでゲームループが始まる showAllTest(); //終了前に全マス開示……いる? getch(); //キー操作待機 endGame(); //終了処理 return 0; }
特に言うことなし。
makefile
これを置いておけば簡単なコマンドでコンパイルができる。
基本的な構造
{ターゲット}: 素材を列挙 {tab}{コマンド} //{tab}はタブ文字。空白ではいけない
例えば
main: main.c {tab}gcc -o main main.c
と作っておけばターミナルでmake main
と打つとそれがgcc -o main main.c
に変換されて実行される。便利やね。実際にはもっと細かいが、まあ。
実際
- マクロ
MAKE_O = gcc -c $<
MAKE_O
がgcc -c $<
に置き換わる
- solveSudoku
solveSudoku: main.o setting.o calc.o menu.o gcc -lncurses -o $@ $^
$@
はターゲット名を示すマクロ。$^
はすべての素材を示すマクロ。つまり上記のコマンドは
gcc -lncurses -o solveSudoku main.o setting.o calc.o menu.o
と解釈される。ちなみに-lncurses
は、ncurses.h
を利用するために必要なオプション。
- main.oその他
calc.o: calc.c calc.h $(MAKE_O)
hogehoge.oをつくるためのコマンド。マクロを展開して
calc.o: calc.c calc.h gcc -c $<
さらに、$<
は素材の先頭のものを示すマクロ。素材の先頭に.c
のファイルを置くことで
calc.o: calc.c calc.h gcc -c calc.c
と解釈される。
clean 要らんファイルを消すのに
clean
を使ったりするらしいが適当にやっているので参考にはならんdo
./solveSudoku
を打つのがめんどいのでこのコマンドでmake do
で置き換える
まとめ
ビット演算を活用したい
ビット | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
unsigned short x | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 |
用途 | a | a | a | a | 0 | 0 | b | b | b | b | b | b | b | b | b | c |
- a : 確定した数字 0001 ~ 1001 x>>12で取り出せる
- b : i=1~9の候補フラグ x>>i & 1 で取り出せる
- c : 確定したか1/0 x&1で取り出せる
う〜む良さげ!
あとは、手動で潰している候補をある程度自動で潰せるようにしたい。 ま、とりあえず洗い出せた改善点を改良してver.2を作ってみようと思う。おしまい。
追記:改良版ができてます ↓
よろしくどうぞ!