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

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

Visual Studio Code

Visual Studio Codeとは、Microsoft社が開発したマルチプラットフォーム対応のテキストエディタです。Visual Studioファミリーの一員でもあります。拡張性とカスタマイズ性が高く、テキストエディタでありながら、IDEと遜色ない機能を備えることができます。

Q&A

解決済

1回答

319閲覧

C言語で将棋のゲームを作成

todasan

総合スコア87

C

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

Visual Studio Code

Visual Studio Codeとは、Microsoft社が開発したマルチプラットフォーム対応のテキストエディタです。Visual Studioファミリーの一員でもあります。拡張性とカスタマイズ性が高く、テキストエディタでありながら、IDEと遜色ない機能を備えることができます。

0グッド

0クリップ

投稿2025/09/26 21:57

0

0

実現したいこと

visualstdiocodeとgccの環境で、将棋のゲームを作成しています。ソースファイルは全て、utf-8になります。以下のソースでmakeをし、ソースの実行ファイルを動かすと、盤面表示の一~九が将棋盤のようになりません。画像がその結果です。盤面表示の一~九が将棋盤になるようにしたいですが、どこがおかしいか、教えていただいてもよろしいでしょうか。バグの探し方として、この環境でいい方法は、分かりますか。

shougi_banmen.csv

後香,後桂,後銀,後金,後王,後金,後銀,後桂,後香, ,後飛,,,,,,後角,, 後歩,後歩,後歩,後歩,後歩,後歩,後歩,後歩,後歩, ,,,,,,,,, ,,,,,,,,, ,,,,,,,,, 先歩,先歩,先歩,先歩,先歩,先歩,先歩,先歩,先歩, ,先角,,,,,,先飛,, 先香,先桂,先銀,先金,先王,先金,先銀,先桂,先香,
#pragma once typedef struct koma_info { int tate; // 位置_縦 int yoko; // 位置_横 int sente; // 先手_後手 char koma[10]; // 駒の種類 } person; shougi_shisaku.h typedef struct koma_shurui { char koma[10]; // 駒の種類 } motikoma;

shougi_shisaku.c

#include <stdio.h> #include <string.h> #include <stdlib.h> #include <time.h> #include "shougi_shisaku.h" extern void explode(const char*, char*, int); // 項目を取り出す person data[81]; // 駒のデータの読み込み person dataretu[81]; // 駒のデータのコピー先 motikoma sente[20]; //先手の持ち駒 motikoma gote[20]; //先手の持ち駒 char kuuhaku[] = "  ",motikoha_kuuhaku[] = " "; char tate_str[] = "一二三四五六七八九"; char koma_str_aite[10] = {},sente_motikoma_str[30] = {},gote_motikoma_str[30] = {}; int tate_mae = 0, yoko_mae = 0, tate_ato = 0, yoko_ato = 0, sente_cnt = 0,gote_cnt = 0 ; int banmen_hyouji(int sente_gote) { int readtate, readyoko, coma_cnt = 0,sente_motikoma; char sub_str[10] = {}; printf("将棋盤\n"); printf("|9    |8    |7    |6    |5    |4    |3    |2    |1     \n"); printf("--------------------------------------------------------------------------------------------\n"); for (readtate = 1; readtate < 10; readtate++) { for (readyoko = 9; readyoko > 0; readyoko--) { if (dataretu[coma_cnt].tate == readtate && dataretu[coma_cnt].yoko == readyoko && dataretu[coma_cnt].koma[0] != '\0') { // 駒の情報がある時 printf("|%s ", &dataretu[coma_cnt].koma[0]); coma_cnt++; } else { // 駒の情報がない時 printf("|%s ", kuuhaku); coma_cnt++; } if (readyoko == 1) { // 縦の駒番号を表示する。 // strから部分文字列を切り出す strncpy(sub_str, tate_str + (readtate - 1) * 2, 4); sub_str[5] = '\0'; // 切り出した部分の終端文字を追加 printf("|%s%s ", sub_str); } } printf("\n"); printf("--------------------------------------------------------------------------------------------\n"); } if (sente_gote == 1){ for (sente_motikoma = 0; sente_motikoma < 20; sente_motikoma++) { if (strlen(sente[sente_motikoma].koma) != 0) { strcat_s(sente_motikoma_str, sizeof(sente_motikoma_str), (const char*)sente[sente_motikoma].koma); strcat_s(sente_motikoma_str, sizeof(sente_motikoma_str), motikoha_kuuhaku); } } sente_gote = sente_gote + 1; } else{ for (sente_motikoma = 0; sente_motikoma < 20; sente_motikoma++) { if (strlen(sente[sente_motikoma].koma) != 0) { strcat_s(gote_motikoma_str, sizeof(gote_motikoma_str), (const char*)sente[sente_motikoma].koma); strcat_s(gote_motikoma_str, sizeof(gote_motikoma_str), motikoha_kuuhaku); } } sente_gote = sente_gote + 1; } printf("|先手の持ち駒 %s\n", sente_motikoma_str); printf("|後手の持ち駒 %s\n", gote_motikoma_str); return sente_gote; } int taikyoku_kaisi(int sente_gote) { int koma_data,idoumotosenteno,idousakisenteno,sente_no; char koma_str[10] = {}; size_t length = 0; if (sente_gote == 1){ printf("***先手の番です***\n"); }else{ printf("***後手の番です***\n"); } printf("***どの地点を動かしますか***\n"); scanf("%d%d", &tate_mae,&yoko_mae); printf("***どこにを動かしますか***\n"); scanf("%d%d", &tate_ato, &yoko_ato); for (koma_data = 0; koma_data < 81; koma_data++){ if (dataretu[koma_data].tate == tate_mae && dataretu[koma_data].yoko == yoko_mae) { // length = strlen(dataretu[koma_data].koma); idoumotosenteno = dataretu[koma_data].sente; } if (dataretu[koma_data].tate == tate_ato && dataretu[koma_data].yoko == yoko_ato){ length = strlen(dataretu[koma_data].koma); idousakisenteno = dataretu[koma_data].sente; printf("|%d \n", length); } } // 自分の駒があるので、移動できない。 if (length != 0 && idoumotosenteno == idousakisenteno) { goto skip; } if (sente_gote == 3){ sente_gote = 1; } // 移動する駒の文字列を保存する。 for (koma_data = 0; koma_data < 81; koma_data++){ if (dataretu[koma_data].tate == tate_mae && dataretu[koma_data].yoko == yoko_mae){ memcpy((void *)koma_str, dataretu[koma_data].koma, 10); sente_no = dataretu[koma_data].sente; memset((void *)dataretu[koma_data].koma, '\0', 10); } } // 駒を移動先の文字列に格納する。 for (koma_data = 0; koma_data < 81; koma_data++){ if (dataretu[koma_data].tate == tate_ato && dataretu[koma_data].yoko == yoko_ato){ if(sente_gote == 1){ memcpy((void*)sente[sente_cnt].koma, (const void*)dataretu[koma_data].koma, 10); sente_cnt = sente_cnt + 1; }else{ memcpy((void*)sente[gote_cnt].koma, (const void*)dataretu[koma_data].koma, 10); gote_cnt = gote_cnt + 1; } dataretu[koma_data].sente = sente_no; memcpy((void*)dataretu[koma_data].koma, (const void*)koma_str, 10); } } skip: return sente_gote; } int main() { FILE* fp; char buf[512], * cp; int tatehoukou,sente_gote = 0; printf("\n***将棋ゲーム***\n"); fopen_s(&fp,"shougi_banmen.csv", "r"); // 将棋のファイルを開く if (fp == NULL) goto END; // ファイルを開けない tatehoukou = 0; memset(&data[0], '\0', sizeof(data)); // データの全文字をNULLに memset(&sente[0], '\0', sizeof(sente)); // データの全文字をNULLに memset(&gote[0], '\0', sizeof(gote)); // データの全文字をNULLに while (1) { cp = fgets(buf, 256, fp); // 1レコードを読む if (cp == NULL) break; // EOF explode(",", buf, tatehoukou); // csvデータを1行ずつ、項目を取り出す tatehoukou = tatehoukou + 1; if (tatehoukou == 9) break; } fclose(fp); // 将棋のファイルを閉じる // memcpyを使ったコピー memcpy(&dataretu, &data, sizeof(person)*81); sente_gote = banmen_hyouji(0); sente_gote = 1; while (1) { sente_gote = taikyoku_kaisi(sente_gote); sente_gote = banmen_hyouji(sente_gote); } END:; }

explode.c

#include <stdio.h> #include <string.h> #include "shougi_shisaku.h" void explode(const char*, char*, int); // 項目を取り出す extern person data[81]; // 駒のデータの読み込み int koma_cnt = 0; void explode( /*----------------------------------*/ /* CSVデータから項目を取り出す */ /*----------------------------------*/ const char* kugiri, // 区切り文字 char* buf, // CSVの1レコード int tatehoukou) { char* cp0, * cp; int yokohoukou = 0, len; cp0 = buf; // CSVデータの先頭アドレス for (yokohoukou = 0; yokohoukou < 9; yokohoukou++) { if (*cp0 == 0x22) cp0++; // 最初の"(0x22)を除く cp = strstr(cp0, kugiri); // 区切り文字を検索 if (cp == NULL) break; // 区切り文字なし len = cp - cp0; // 項目の文字数 if (*(cp - 1) == 0x22) len--; // 最後の"(0x22)を除く if (len > 0) // 項目あり { memcpy(&data[koma_cnt].koma[0], cp0, len); // 項目の文字列をコピー data[koma_cnt].tate = tatehoukou + 1; data[koma_cnt].yoko = 9 - yokohoukou; if (strncmp(data[koma_cnt].koma, "先", 2) == 0){ data[koma_cnt].sente = 1; } else { data[koma_cnt].sente = 2; } koma_cnt = koma_cnt + 1; }else{ data[koma_cnt].tate = tatehoukou + 1; data[koma_cnt].yoko = 9 - yokohoukou; koma_cnt = koma_cnt + 1; } cp0 = cp + 1; // 次の文字のアドレス } }

Makefile

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

イメージ説明

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

質問に詳細を記載した。

該当のソースコード

特になし

試したこと・調べたこと

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

質問に詳細を記載した。

補足

特になし

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

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

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

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

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

thkana

2025/09/26 22:52

「将棋盤のようになりません」ではなく、あなたの思う将棋盤と何が違うのかを誰がみても同じ現象として捉えるように記載してみてください。まずは、ちゃんと観察することが最初です。それが常に直接に解決に繋がるとまではいいませんが、一般論として。
thkana

2025/09/27 00:06

タイトルですが、 「C言語による将棋のプログラムについて」 「C言語で将棋のゲームを作成」 が並んでいて、区別ができません。 ヘルプ https://teratail.com/help/question-tips のタイトルに関する項目を参考に、それぞれの質問を区別できるようなタイトルを心がけていただければと思います。 (そもそも質問連発というのが「身の丈に合っていないことをやろうとしている」とも言えるのですが、その挑戦の意気やよし、というところでしょうね。頑張ってください)
Ham-tail

2025/09/27 03:00

さんざん別スレッドで駄目だしされてたのに何も変えてないのな 聞く気が無いのに次々同じ質問する意味が聞きたいね
todasan

2025/09/29 00:33

thkana さん  すみません。タイトルはこれから詳細につけます。 Ham-tail さん すみません。同じ質問をしているつもりはないのですが、アドバイスが欲しくて、 同じ質問のように、なってしまいました。
guest

回答1

0

ベストアンサー

「将棋盤のようでない」とは、一~九までの順に文字が表示されないということですか?
バグの探し方は、「意図しない状況になっている処理を行っている部分を精査する」です。一~九を表示しているのはどこでしょう。

C

1#include <stdio.h> 2#include <string.h> 3 4char tate_str[] = "一二三四五六七八九"; 5 6int main() { 7 char sub_str[10]; 8 for (int readtate = 1; readtate < 10; readtate++) { 9 // strから部分文字列を切り出す 10 strncpy(sub_str, tate_str + (readtate - 1) * 2, 4); 11 sub_str[5] = '\0'; // 切り出した部分の終端文字を追加 12 printf("|%s l\n", sub_str); 13 } 14 return 0; 15}

で問題点を切り出せると思います。
なぜかを考えるなら

C

1#include <stdio.h> 2#include <string.h> 3 4char tate_str[] = "一二三四五六七八九"; 5 6int main() { 7 printf("%ld\n",strlen(tate_str)); 8 return 0; 9}

の結果を見ると参考になるでしょう。

私だったら、UTF-8のアルファベットでない一文字は一般には可変長ですから、考えることを放棄して
char* tate_str[]={"一","二","三","四","五","六","七","八","九"};
とするでしょうね。こうしておけば、他のエンコードに移植しても影響が少なくできるはずですし。

それと、コンパイラが出す警告(warning)はバグ候補です。みかけたら完膚なきまでに潰しておきましょう。shougi_shisaku.c中の printf("|%s%s ", sub_str);はwarningになっているはずです。

バグとは直接には関係ありませんが、

C

1 for (readtate = 1; readtate < 10; readtate++) 2 { 3 for (readyoko = 9; readyoko > 0; readyoko--) 4 { 5 if (readyoko == 1) { // 縦の駒番号を表示する。 6 //表示処理 7 } 8 } 9 printf("\n"); 10 printf("--------------------------------------------------------------------------------------------\n"); 11 }

という構成は気持ち悪く思えます。readyoko == 1になるタイミングを考えるとreadyokoのループの抜ける間際でしかあり得ませんね。そういうものは横ループを抜けたところで処理されるのが一般的な期待ですから、一般的な期待に添ったコードを書くべきでしょう。

C

1 for (readtate = 1; readtate < 10; readtate++) 2 { 3 for (readyoko = 9; readyoko > 0; readyoko--) 4 { 5 } 6 // 縦の駒番号を表示する。 7 // 表示処理 8 printf("\n"); 9 printf("--------------------------------------------------------------------------------------------\n"); 10 }

あと、プログラムそのものには関係のないところで、まぁそれぞれの感覚の問題でしかないかも知れないけれど、私だったら表示はこんな風にするかなぁ。互いの駒が入り乱れてきたときに「先手後手」表示だと頭がついていかなそう。まぁ、あなたのお好きな方でどうぞ。(v^は駒と縦に並べたい気もするけれど、コンソールの縦はやっぱり25行?だとちょっとキツいですね)

Text

1| 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 2+---+---+---+---+---+---+---+---+---+--- 3|v香|v桂|v銀|v金|v王|v金|v銀|v桂|v香| 一 4+---+---+---+---+---+---+---+---+---+--- 5| (略) 6+---+---+---+---+---+---+---+---+---+--- 7|^香|^桂|^銀|^金|^王|^金|^銀|^桂|^香| 九 8+---+---+---+---+---+---+---+---+---+---

投稿2025/09/26 23:22

編集2025/09/26 23:56
thkana

総合スコア7769

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

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

todasan

2025/09/29 00:36

ありがとうございます。以下のように文字列を固定長にしました。 char *tate_str[] = {"一","二","三","四","五","六","七","八","九"}; 以下のようにsub_strに格納したら、意図通りになりました。 memcpy((void *)sub_str, tate_str[readtate - 1], 10); ご回答をありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.30%

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

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

質問する

関連した質問