C言語で、将棋のゲームを作成しています。VSCODEとucrt64のgcc、makeの
環境で作成しています。
先手、後手を上、下釦で、選択して、エンター釦を押し、先手か後手かを
画面に表示するまで、以下のソースで再現しました。先手なのに、後手の
駒を動かすと、動かないところまでも再現しました。
これから勉強のためシェルスクリプト、bashなどを取り入れていきたいです。
開発環境、どのような実装で、シェルスクリプト、bashを使うのかを
お聞きしてもいいですか。この既存のソースで、シェルスクリプト、bashの
使いどころもお聞きしたいです。理由として、シェルスクリプト、bashは、
C言語を使う時の常識と思っているため、使いどころが分からず
お聞きしたいです。これから棋譜の保存、棋譜の表示の機能も追加しようと思い、
そこらへんでもシェルスクリプト、bashの使いどころがあるかをお聞きしたいです。
・Makefile
https://www.mycompiler.io/view/Ag90sG2vfY2
・shougi_data.h
https://www.mycompiler.io/view/BHObuhYhjvS
・shougi_main.c
https://www.mycompiler.io/view/A7LTZUU4htK
・shougi_input.c
https://www.mycompiler.io/view/7ZSQIgfPioK
・shougi_boad.c
https://www.mycompiler.io/view/K0moOdsQ3y6
・shougi_highlight.c
https://www.mycompiler.io/view/EzCWLrLfWkT
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答23件
#1
総合スコア146822
投稿2025/10/17 01:32
まず、シェルスクリプトというのは、シェルで実行するコマンドを書き連ねて、まとめて実行するためのものです。
C言語で作ったプログラムでも、「フィルタ」と呼ばれるような、標準入力・標準出力で動作するようなプログラムであれば、シェルスクリプトの1要素として組み込むこむことも珍しくありません。
ただ、今回のようなcursesでインタラクティブにユーザーが操作することを前提としたコンソールプログラムでは、シェルスクリプトと合わせてもうまみはあまりありません。
これから棋譜の保存、棋譜の表示の機能も追加しようと思い、
そこらへんでもシェルスクリプト、bashの使いどころがあるかをお聞きしたいです。
棋譜を読み込んでユーザーの操作なしに評価値を出力するような機能があれば別ですが、読み込んだ後にユーザー操作で使うような状況では特にないです。
#2
総合スコア146822
投稿2025/10/17 01:33
なお、作るプログラムそのものを動かす話とは別問題として、ビルドプロセスが複雑化してきた場合に、ビルドをシェルスクリプトで自動化するということは考えられます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
#4
総合スコア21502
投稿2025/10/17 02:39
本題とは無関係ですが、気が付いた事があります。
先手、後手を上、下釦で、選択して、エンター釦を押し、先手か後手かを画面に表示するまで、以下のソースで再現しました。先手なのに、後手の駒を動かすと、動かないところまでも再現しました。
掲示されているソースコードをビルドして実行してみましたが、
- 先手・後手を選択すると、再度先手・後手の選択場面が表示される
- 2度目の選択画面で先手・後手を選ぶと盤面が表示されるが、キー入力を行うと先手・後手の選択画面へ戻る
という動作になっています。これはdraw_board()
関数(shougi_boad.c
)にdraw_selection()
関数(shougi_main.c
)と同じ処理(先手・後手の選択する処理)があるためですが、ソースコードを確認するとdraw_board()
のプロトタイプ宣言が一致していません。
shougi_main.c
c
1extern void draw_board(int is_turn);
shougi_boad.c
c
1void draw_board();
もしかして、掲示されているshougi_boad.c
が以前のバージョンのままなのではないでしょうか?
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
#6
総合スコア14644
投稿2025/10/17 02:57
理由として、シェルスクリプト、bashは、C言語を使う時の常識と思っている
これをどういうニュアンスで書いているのかわかりませんが、「シェルスクリプト・bashは、UNIX上で作業する時の基礎スキル」なので、作業を効率化するために、sedやawkを始めとするいろいろなコマンドを使えるようにするとか、ファイルやディレクトリの操作のためにの提携業務をスクリプト化するなどは習得しておくといいでしょう。
そうでなく、「C言語のプログラムの中にBashのスクリプトを混ぜて1つのものを作る」ということを指しているのであればそれは一般的ではありませんが、連携させて使うというのはよくやることです。
Bashはディレクトリやファイルを操作するのが得意ですから、将棋プログラムの実行にあたって必要な処理をBashで書くというのはありでしょう。たとえば、現在のプログラムを実行するときに、いつもやっていること(ログファイル更新とか必要ファイルの確認とか)があれば、それをBashスクリプトで自動化し、準備できたらそのスクリプトから本体を呼ぶなどでしょうか。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
#10
総合スコア13429
投稿2025/10/17 03:45
現状のプログラムでシェルスクリプトを使う必要は全く無いと思います。
興味があるからやってみたいというのは分かりますが、シェルは OS とユーザの仲を取り持つプログラムであって(bash はその中の一つに過ぎません)、OS と(直接もしくはライブラリを通して間接的に)やり取りしている c プログラムとは直接関係ありません。
どうしても何かやってみたいということなら、c や将棋は一旦置いておいて、他の人はシェルスクリプトで何をしているかから調べられては如何でしょう。
もっとも、今はシェルよりも将棋プログラムを( c だけで)完成させる方に力を注いだ方が良いと思います。
元々は『c を苦手に思うから』と苦手を克服?するために作り始められたと記憶しています。
もう苦手意識は無くなったのでしょうか。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
#11
総合スコア146822
投稿2025/10/17 04:09
編集2025/10/17 04:11例えば棋譜の保存で、シェルとbashを使い、csvファイルなどに保存する時などは、
使えそうでしょうか。
現状のプログラムのような、cursesを使ったユーザーが画面変化に応じて操作するプログラムでは、シェルスクリプトと合わせても仕方ないです。
今のプログラムをシェルスクリプトから呼び出したところで、「タイミングに合わせたキー操作」を送信するという、シェルスクリプトに全く向かない操作が必要となって、ただ煩雑になるだけです。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
#14
総合スコア21502
投稿2025/10/17 05:37
これから棋譜の保存、棋譜の表示の機能も追加しようと思い、そこらへんでもシェルスクリプト、bashの使いどころがあるかをお聞きしたいです。
PDCursesではputwin()
という関数が提供されています。(他のcursesライブラリにもあります) これは画面への表示内容をバイナリ形式でファイルに保存します。そして、getwin()
関数を使用して画面の表示状態をダンプ時に戻すことができます。
以下はs
を入力することでスクリーンダンプを行い、r
でリストアする処理の例です。ですが、ファイル名を決め打ちにしていますので保存するファイル名を入力させる処理と、内部で使用しているboard
配列とdataretu
配列へ表示内容を反映させる処理が必要になるでしょう。
c
1void screen_dump() { 2 FILE *file = fopen("screen.dump", "w"); 3 if (file != NULL) { 4 putwin(stdscr, file); 5 fclose(file); 6 } 7} 8 9void restore_data() { 10 FILE *fp; 11 if ((fp = fopen("screen.dump", "r")) == NULL) { 12 endwin(); 13 perror("Can't restore dump file"); 14 exit(EXIT_FAILURE); 15 } 16 17 WINDOW *win = getwin(fp); 18 fclose(fp); 19 touchwin(win); 20 wrefresh(win); 21} 22 23int main(void) { 24 : 25 while (1) { 26 : 27 switch (ch) { 28 : 29 case 's': screen_dump(); break; 30 case 'r': restore_data(); break; 31
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
#18
総合スコア13429
投稿2025/10/18 02:07
編集2025/10/18 02:22棋譜いうと↓ですかね。
日本将棋連盟>よくある質問>棋譜の表記方法
https://www.shogi.or.jp/faq/kihuhyouki.html
省略とか、思ったより複雑でした。
これをログとしてセーブや、ロードしてゆっくり再生出来るようになれば、プレイの記録にも新聞・雑誌の対局再現にも良さそうですが、シェルの出番は無さそうです…。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
#19
総合スコア12299
投稿2025/10/20 04:50
編集2025/10/20 05:08対局中の棋譜は対局中に、横に画面で表示しようと思います。
一度の対局が何手かかるかは一般的には不明なのでは…?
すなわち,棋譜の全てを画面内に一度に表示しきれるとは想定できないと思うのです.
画面表示内容の保存と復元なる機能を用いて本当にやれる話なのでしょうか?
(そりゃまぁ,「各時刻において表示されている棋譜の一部」みたいなのを都度保存していけばそれらから「棋譜全体」を構成できるぞ…とかなんとか,「やる方法」はあるのかもしれませんが……なんというか,こう,もっと「普通に」やらない理由がわからないというか?)
なんだろう? 想像している物が違うのかな?
まず「棋譜というデータ」があって→そのデータに基づいて何かしらの「今現在の表示」というのが成される…のだと思うんだけど,
結果たる「今現在の表示」というのが「棋譜というデータ」 の全て を含んでいるとは限らないよね.
(すなわち,ある時点における表示内容だけからその時点におけるデータというのを完全復元できるとは限らないのでは? っていう)
仮に,「表示内容は常にデータを完全に表現しきっている」という物を作っているのだとしても,
表示からデータを復元する処理というのは,表示方法をちょっと変える度にそれに合わせた修正が必要になるだろうし,とても面倒なんじゃないかなと思う.
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
#21
総合スコア12299
投稿2025/10/21 04:10
編集2025/10/21 04:29「何か特別なライブラリ(?)を使えばできるかも」という話だと,それをやってみることの意味合いというのは「その特定のライブラリの使い方 の学び」みたいなのになるように思う.
(そのこと自体が 良い とか 悪い とかいうことではないけども)
C言語の学習が目的
という話であれば,自分ならまずは「 C言語で データをファイルに保存したりそのファイルを読み込んでデータを復元したりするには?」という話を調べたら普通に出てくるようなこと(: C言語でやるとしたらまぁこうだよねっていうような一般的な話)からチャレンジするかなぁ,と.
まぁそういう話とは全く別のところで
「便利なことがあるか否か とか 一般的なやりかたか否か とか 目的に合ってるか 等々いう話は度外視して,とにかく一度 やってみる んだよ!」っていう勢いというかそういうのはアリだと思います.
本題の「シェルがどうの~」いう話について言えば,
(私はそういうことをあまりやったことは無いのですが)C言語だと system()
なる関数を使えばシェルのコマンドやらを実行できるのではないかと思います.
例えば何か「C言語で実装するよりもシェルスクリプトで実装したほうが楽」みたいな処理が存在している場合,その処理を実装したシェルスクリプトをC言語で作ったプログラム側から利用する的な話になるんでしょうかね.
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
#22
総合スコア21502
投稿2025/10/21 09:16
編集2025/10/21 09:33表示からデータを復元する処理というのは,表示方法をちょっと変える度にそれに合わせた修正が必要になるだろうし,とても面倒なんじゃないかなと思う.
mvwinnwstr()
で画面上の表示内容(ワイド文字列)を取得して、wcstombs()
でマルチバイト文字列に変換します。現状、駒データ(名前と盤上の位置)をboard
配列(char *
)とdataretu
配列(person
構造体)で二重管理してしまっているので、それらのつじつまを合わせることが少し面倒です。
c
1void restore_data() { 2 int result = scr_restore("screen.dump"); 3 if (result == ERR) { 4 perror("Can't restore dump file"); 5 return; 6 } 7 touchwin(curscr); 8 wrefresh(curscr); 9 10 extern person dataretu[]; 11 int disp_size = CELL_W - 2; 12 int nbytes, index; 13 wchar_t wcs[disp_size + 1]; 14 char mbcs[MB_CUR_MAX * disp_size + 1]; 15 for (int y = 0; y < BOARD_SIZE; ++y) { 16 for (int x = 0; x < BOARD_SIZE; ++x) { 17 mvwinnwstr(curscr, ORIGIN_Y + y * CELL_H, ORIGIN_X + x * CELL_W, wcs, disp_size); 18 nbytes = wcstombs(mbcs, wcs, sizeof(mbcs)); 19 mbcs[nbytes] = '\0'; 20 index = y * BOARD_SIZE + x; 21 if (wcsncmp(wcs, L" ", 1)) 22 strcpy(dataretu[index].koma, mbcs); 23 else 24 dataretu[index].koma[0] = '\0'; 25 } 26 } 27 set_board_from_dataretu(); 28}
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。