質問するログイン新規登録
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

UTF-8

UTF-8は8ビット符号単位の文字符号化形式及び文字符号化スキームです。データ交換方式、ファイル形式としては、一般的にUTF-8が使われる傾向があります。

MinGW

MinGW(ミン・ジー・ダブリュー)は GNUツールチェーンのWindows移植版です。 ランタイムライブラリと開発ツールで構成されています。

Q&A

2回答

266閲覧

utf-8のファイルから将棋のプログラムの移動範囲を表示する。

todasan

総合スコア87

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

UTF-8

UTF-8は8ビット符号単位の文字符号化形式及び文字符号化スキームです。データ交換方式、ファイル形式としては、一般的にUTF-8が使われる傾向があります。

MinGW

MinGW(ミン・ジー・ダブリュー)は GNUツールチェーンのWindows移植版です。 ランタイムライブラリと開発ツールで構成されています。

0グッド

0クリップ

投稿2025/10/06 11:03

編集2025/10/07 00:52

0

0

実現したいこと

以下のソースから将棋のプログラムを作成しています。makeを実行後、画像のように、
実行ファイルを実行して、画像の黄色いところで、エンター釦を押すと、エラーになります。
画像のターミナルに書かれたエラーです。
shougi_highlight.cの以下の"歩"がutf-8のファイルのため、2バイト以上の文字データのために
エラーになりますが、ファイルを全てshift-jisにすれば、よろしいでしょうか。
if (strcmp(piece, "歩") == 0) {

PDCursesWをインストールすれば、utf-8のファイルでもいいと言われましたが、
なぜか/c/pdcursesw/wincon/pdcursesw.aが作れず、pdcurses.aしかできず、
まだその方法もうまくできません。
何か解決のアドバイスをいただいてもよろしいですか。

・Makefile

# コンパイラの指定 CC=gcc # コンパイル時のオプション CFLAGS=-I. -Wall # 最終的な実行ファイル名 TARGET=myapp.exe LIBS = -lpdcurses # 最終ターゲット $(TARGET): shougi_main.o shougi_input.o shougi_boad.o shougi_highlight.o $(CC) -o $(TARGET) shougi_main.o shougi_input.o shougi_boad.o shougi_highlight.o $(LIBS) # shougi_main.cからshougi_main.oを生成 shougi_main.o: shougi_main.c $(CC) -c shougi_main.c $(CFLAGS) # shougi_input.cからshougi_input.oを生成 shougi_input.o: shougi_input.c $(CC) -c shougi_input.c $(CFLAGS) # shougi_boad.cからshougi_boad.oを生成 shougi_boad.o: shougi_boad.c $(CC) -c shougi_boad.c $(CFLAGS) # shougi_highlight.cからshougi_highlight.oを生成 shougi_highlight.o: shougi_highlight.c $(CC) -c shougi_highlight.c $(CFLAGS) # 'make clean' を実行した時に実行ファイルとオブジェクトファイルを削除 clean: rm -f $(TARGET) shougi_main.o shougi_input.o shougi_boad.o shougi_highlight.o

shougi_shisaku.h

h

1#ifndef SHOUGI_SHISAKU_DEF_H 2#define SHOUGI_SHISAKU_DEF_H 3typedef struct koma_info { 4 int tate; // 位置_縦 5 int yoko; // 位置_横 6 char koma[10]; // 駒の種類 7} person; 8 9typedef struct koma_shurui { 10 char koma[10]; // 駒の種類 11} motikoma; 12 13#define BOARD_SIZE 9 // 将棋は9x9 14 15extern int start_x; 16extern int start_y; 17 18#define CELL_W 5 19#define CELL_H 2 20 21// 画面上の盤左上のオフセット 22#define ORIGIN_Y (start_y + 1) 23#define ORIGIN_X (start_x + 2) 24#endif
・shougi_boad.c ```c #include "shougi_shisaku.h" #include <string.h> #include <pdcurses.h> void draw_board(); void set_board_from_dataretu(); extern void highlight_moves(int y, int x, const char *piece, int is_gote); extern person dataretu[81]; // 駒のデータの読み込み extern int is_selected; // 駒を選択中かどうか extern int from_x; // 選択した位置x extern int from_y; // 選択した位置y // 盤面を管理する2次元配列 // NULLなら空マス、文字列なら駒 extern const char *board[BOARD_SIZE][BOARD_SIZE]; extern const char *selected_piece; // 動かす対象の駒の種類 int start_y = 2; // 盤面の開始位置(縦方向) int start_x = 4; // 盤面の開始位置(横方向) int cursor_x = 5; // 初期カーソル位置(ファイル) int cursor_y = 5; // 初期カーソル位置(段) void draw_board() { clear(); // タイトル const char *title = "将棋ゲーム"; mvprintw(0, (COLS - strlen(title)) / 2, "%s", title); const char *kansuji[] = {"一", "二", "三", "四", "五", "六", "七", "八", "九"}; // 枠を描画 for (int y = 0; y <= BOARD_SIZE; y++) { for (int x = 0; x <= BOARD_SIZE; x++) { int py = start_y + y * CELL_H; int px = start_x + x * CELL_W; mvaddch(py, px, '+'); // 交点 if (x < BOARD_SIZE) { // 横線 for (int i = 1; i < CELL_W; i++) { mvaddch(py, px + i, '-'); } } if (y < BOARD_SIZE) { // 縦線 for (int j = 1; j < CELL_H; j++) { mvaddch(py + j, px, '|'); } } } } // 筋(上) — 右から左に 9 〜 1 for (int x = 0; x < BOARD_SIZE; x++) { int px = start_x + x * CELL_W + CELL_W / 2; mvprintw(start_y - 1, px, "%d", 9 - x); } // 段(右) — 上から下に 一〜九 for (int y = 0; y < BOARD_SIZE; y++) { int py = start_y + y * CELL_H + CELL_H / 2; int px = start_x + BOARD_SIZE * CELL_W + 2; // 右側に表示 mvprintw(py, px, "%s", kansuji[y]); } // 駒描画 for (int y = 0; y < BOARD_SIZE; y++) { for (int x = 0; x < BOARD_SIZE; x++) { int sy = ORIGIN_Y + y * CELL_H; int sx = ORIGIN_X + x * CELL_W; if (cursor_y - 1 == y && cursor_x - 1 == x) { attrset(COLOR_PAIR(2)); // 黒字+白背景 } else { attrset(COLOR_PAIR(1)); // 白字+黒背景 } // もし選択中で、元のマスがここなら空白(持ち上げ済み) if (is_selected && (from_y - 1) == y && (from_x - 1) == x) { mvaddstr(sy, sx, " "); // 元マスは空に見せる } else { // 通常はボード上の文字を出す mvaddstr(sy, sx, board[y][x] ? board[y][x] : " "); } // 駒(または空マス)を描画 mvaddstr(sy, sx, board[y][x] ? board[y][x] : " "); } } // もし駒を選択中なら、カーソル位置に選択中の駒を描画して追従表示(選択の視認性向上) if (is_selected && selected_piece != NULL) { int sy = ORIGIN_Y + (cursor_y - 1) * CELL_H; int sx = ORIGIN_X + (cursor_x - 1) * CELL_W; // attrset(COLOR_PAIR(3)); // 選択中は別色で描く(例: 白文字+青背景) // mvaddstr(sy, sx, selected_piece); highlight_moves(from_y - 1, from_x - 1, selected_piece, /*is_gote=*/0); attrset(A_NORMAL); } attrset(A_NORMAL); // 属性をリセット refresh(); } void set_board_from_dataretu() { for (int y = 0; y < BOARD_SIZE; y++) { for (int x = 0; x < BOARD_SIZE; x++) { int index = y * BOARD_SIZE + x; // 0〜80の通し番号 if (strlen(dataretu[index].koma) > 0) { // dataretu[index].moji が駒文字(例:"歩")なら代入 board[y][x] = (const char *)&dataretu[index].koma; // malloc確保してコピー } else { board[y][x] = NULL; // 空マス } } } }

・shougi_highlight.c

c

1#include <string.h> 2#include <pdcurses.h> 3#include "shougi_shisaku.h" 4 5void highlight_moves(int y, int x, const char *piece, int is_gote); 6 7typedef struct { 8 int dx; 9 int dy; 10} Direction; 11 12const Direction HO[] = { {0, -1} }; // 歩 13const Direction KYO[] = { {0, -1} }; // 香 14const Direction KEI[] = { {-1, -2}, {1, -2} }; // 桂 15const Direction GIN[] = { {-1,-1}, {0,-1}, {1,-1}, {-1,1}, {1,1} }; 16const Direction KIN[] = { {-1,-1}, {0,-1}, {1,-1}, {-1,0}, {1,0}, {0,1} }; 17const Direction OU[] = { {-1,-1}, {0,-1}, {1,-1}, {-1,0}, {1,0}, {-1,1}, {0,1}, {1,1} }; 18const Direction KAKU[]= { {-1,-1}, {1,-1}, {-1,1}, {1,1} }; 19const Direction HI[] = { {0,-1}, {0,1}, {-1,0}, {1,0} }; 20 21int get_moves(const char *piece, int is_gote, Direction moves[], int *max_steps) { 22 if (strcmp(piece, "歩") == 0) { 23 *max_steps = 1; 24 memcpy(moves, HO, sizeof(HO)); 25 } else if (strcmp(piece, "香") == 0) { 26 *max_steps = 8; 27 memcpy(moves, KYO, sizeof(KYO)); 28 } else if (strcmp(piece, "桂") == 0) { 29 *max_steps = 1; 30 memcpy(moves, KEI, sizeof(KEI)); 31 } else if (strcmp(piece, "銀") == 0) { 32 *max_steps = 1; 33 memcpy(moves, GIN, sizeof(GIN)); 34 } else if (strcmp(piece, "金") == 0) { 35 *max_steps = 1; 36 memcpy(moves, KIN, sizeof(KIN)); 37 } else if (strcmp(piece, "王") == 0) { 38 *max_steps = 1; 39 memcpy(moves, OU, sizeof(OU)); 40 } else if (strcmp(piece, "角") == 0) { 41 *max_steps = 8; 42 memcpy(moves, KAKU, sizeof(KAKU)); 43 } else if (strcmp(piece, "飛") == 0) { 44 *max_steps = 8; 45 memcpy(moves, HI, sizeof(HI)); 46 } else { 47 return 0; 48 } 49 50 // 後手なら縦方向反転 51 if (is_gote) { 52 for (int i = 0; i < 8; i++) { 53 moves[i].dy = -moves[i].dy; 54 } 55 } 56 57 return 1; 58} 59 60void highlight_moves(int y, int x, const char *piece, int 61 is_gote) { 62 Direction dirs[8]; 63 int max_steps; 64 if (!get_moves(piece, is_gote, dirs, &max_steps)) return; 65 66 for (int i = 0; i < 8; i++) { 67 for (int step = 1; step <= max_steps; step++) { 68 int ny = y + dirs[i].dy * step; 69 int nx = x + dirs[i].dx * step; 70 if (ny < 0 || ny >= BOARD_SIZE || nx < 0 || nx >= BOARD_SIZE) 71 break; 72 73 // ここでハイライト表示(PDCursesなら背景色変更) 74 attron(COLOR_PAIR(4)); 75 mvaddstr(ORIGIN_Y + ny * CELL_H, ORIGIN_X + nx * CELL_W, "□"); 76 attroff(COLOR_PAIR(4)); 77 } 78 } 79} 80

イメージ説明

イメージ説明

・shougi_main.c
https://www.mycompiler.io/view/Ht5quTklMci

・shougi_input.c
https://www.mycompiler.io/view/8iKKHPXAs0W

発生している問題・分からないこと

質問に詳細を記載した。

該当のソースコード

特になし
特になし

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

質問に詳細を記載した。

補足

特になし

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

melian

2025/10/06 12:28

shougi_main.c と shougi_input.c を追加してください。また、shougi_boad.c はshougi_board.c のスペルミスでしょうか?
jimbe

2025/10/06 17:36

set_board_from_dataretu 関数には変な所(そしてそれを無理矢理している所)がありますが、この関数は使っていないんでしょうか?
todasan

2025/10/07 00:10

melianさん jimbeさん shougi_main.c、shougi_input.cは質問の文字数の9000文字を超えたため追加できません。どのように追加したらいいですか。 shougi_board.cはスペルミスです。 set_board_dataretuはその意味通り使っています。
melian

2025/10/07 00:27

それでは、 https://www.mycompiler.io/ja/new/c にコピー・アンド・ペーストして貰えますか。具体的には以下の通りにします。 * 左側のテキストボックスにコードを貼り付け * 「タイトルを入力...」と表示されているテキストボックスにファイル名を入力 * 右側の「コードを保存」ボタンをクリック * ロケーションボックスのURLが切り替わるので、それを質問に追記
todasan

2025/10/07 00:53

melianさん jimbeさん 質問欄にshougi_main.c、shougi_input.cを記載しました。
jimbe

2025/10/07 06:03 編集

文字数制限はなかなか苦労する部分ですね^^; もっと増やしてほしいと思う反面、なんでもかんでも載せられては資源を圧迫されかねないですし、もしかしたらサービス妨害されるかも知れませんから…。 外部のストレージとか、github のように開発に利用しながら公開も出来るようなサービスをご検討されると良いかと思います。 また、ソースコードも例えばインデントを今は4文字されてますが2文字にするとか、コメントを極力減らすとか、質問本文で不要な部分を削除するとか地道に文字を消すのも多少は意味があるかもしれません。 今の所、include の使用とか関数・変数の宣言とかで工夫の余地があるようにも見えます。
thkana

2025/10/07 23:17

内容の精査はしていません。とりあえず書いてある文章への反応ですが、 https://teratail.com/questions/len2zda4xi7cd6#reply-4k2frniko4xqg1 で書いたことを再掲します。 --- 「歩である」という本質だけが必要なところに"歩"の文字コードを影響させてしまったが故に発生する手間といっていいでしょう。ここを、抽象化して歩なら1、香車は2とかシンボル化しておけばそういう違いの影響を排除できます。文字コードなどの外部事情に影響されやすい画面表示処理やデータ入出力を処理本体とは分離する、というのはプログラミングにおけるテクニックのひとつです。 --- > ファイルを全てshift-jisにすれば、よろしいでしょうか。 とてもよろしくない「悪い」解決、と言わざるを得ないと思います。プログラミングの勉強のため、ということであれば、ことここに至ってはどんなに面倒に思ったとしても、即時書き換えて文字コードがそのレベルに与える影響を排除するべきでしょう。動けばヨシ、ではありません。
guest

回答2

0

../pdcurses/refresh.c でエラーが発生していることから

  • shougi_boad.c 102行目

refresh()

の手前で,コメントアウトするとエラーが発生しなくなる箇所を探すと

  • shougi_boad.c 97行目

highlight_moves(from_y - 1, from_x - 1, selected_piece, /*is_gote=*/0);

が見つかり,この関数の中で

  • shougi_highlight.c 75行目

mvaddstr(ORIGIN_Y + ny * CELL_H, ORIGIN_X + nx * CELL_W, "□");

を疑いました。試しに,文字列を全角スペースにしたところエラーは発生しなくなりました。また,位置を合わせるため nyny + 1 にしました。

mvaddstr(ORIGIN_Y + (ny + 1) * CELL_H, ORIGIN_X + nx * CELL_W, " ");

投稿2025/10/07 16:30

編集2025/10/07 16:38
little_street

総合スコア528

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

cygwin で動かした所、特にエラーには成りませんでしたがコードや動作が妙に見えた所がありましたのでソコだけ指摘させて頂きます。

set_board_from_dataretu 関数

c

1// dataretu[index].moji が駒文字(例:"歩")なら代入 2board[y][x] = (const char *)&dataretu[index].koma; // malloc確保してコピー

コメントが合っていません。
コメントに詳細を書くと、時にはコードの変更にコメントの修正が追い付かず、他人にはコードが正しいのかコメントが正しいのかが分かりません。このようなことは結構起きやすいので、いっそコメントは無いほうが良いです。
そして、(const char *)&dataretu[index].koma というのは '&' の所為でエラーかワーニングになったのを無理矢理キャストで抑え込んだように見えます。 dataretu[index].koma と書けばキャストも要らないのではないでしょうか。

highlight_moves 関数

c

1 Direction dirs[8]; 2 int max_steps; 3 if (!get_moves(piece, is_gote, dirs, &max_steps)) return; 4 5 for (int i = 0; i < 8; i++) { 6 for (int step = 1; step <= max_steps; step++) { 7 int ny = y + dirs[i].dy * step;

get_moves 内で dirs にデータをコピーしていますが、コピーされた件数が返されないため i のループが固定で回っています。
get_moves 内でコピーされなかった所にデタラメなデータが残っていた場合、動作が不明になりそうです。
get_moves の返り値が 1/0 でしか利用されていませんので、関数値としてコピーした件数を返すようにすれば不要なループをしなくて済むように出来ると思います。
ただ、 highlight_moves (と get_moves) の構造で、"角"・"飛"の成った"馬"・"龍"の動きが表現出来るかが疑問です。

c

1mvaddstr(ORIGIN_Y + ny * CELL_H, ORIGIN_X + nx * CELL_W, "□");

がフォントによっては半角サイズになり、表示が崩れます( PDcurses と cygwin で違うかもしれません)。さらに、敵の'v'が付いた駒の所はどのように移動(取得)可能と表示するのでしょうか。

どこに何を表示するのか纏まってない?

カーソルの下に(敵/味方)駒がある/無い場合、選択中で下に(敵/味方)駒がある/無い場合、選択中で選択した駒が移動可能な位置で下に敵駒がある/無い場合等で、それぞれどのような表示にするのかは纏まっていらっしゃるでしょうか。
現状、highlight_moves で表示された所ではカーソルが隠れてしまいます。

投稿2025/10/07 07:15

編集2025/10/07 12:13
jimbe

総合スコア13422

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問