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

Q&A

解決済

2回答

836閲覧

C言語とmingw64とgccによる将棋ゲームの作成

todasan

総合スコア98

C

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

Visual Studio Code

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

GCC

GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。

MinGW

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

0グッド

0クリップ

投稿2025/10/02 08:56

編集2025/10/02 11:52

0

0

実現したいこと

以下のソースで将棋盤の5の5に歩を表示して、カーソルに歩を合わせると、
色が変わるつもりで、プログラムを作成しました。
しかし画像のように歩が白くなり、カーソルをつけても、色が変わりません。
何か解決方法があれば、お聞きしたいです。

・Makefile

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

shougi_test.c

#include <pdcurses.h> #include <stdio.h> #include <locale.h> #include <string.h> #include <windows.h> // SetConsoleOutputCP #include "shougi_shisaku.h" extern void explode(const char*, char*, int); // 項目を取り出す person data[81]; // 駒のデータの読み込み person dataretu[81]; // 駒のデータのコピー先 motikoma sente[20]; //先手の持ち駒 motikoma gote[20]; //先手の持ち駒 #define BOARD_SIZE 9 // 将棋は9x9 #define CELL_W 4 #define CELL_H 2 int start_y = 2; // 盤面の開始位置(縦方向) int start_x = 4; // 盤面の開始位置(横方向) // 画面上の盤左上のオフセット #define ORIGIN_Y (start_y + 1) #define ORIGIN_X (start_x + 2) int cursor_x = 5; // 初期カーソル位置(ファイル) int cursor_y = 5; // 初期カーソル位置(段) // 盤面を管理する2次元配列 // NULLなら空マス、文字列なら駒 const char *board[BOARD_SIZE][BOARD_SIZE]; // 駒を選択中かどうか int is_selected = 0; int from_x, from_y; // 選択した位置 void csv_read(){ FILE* fp; char buf[512], * cp; int tatehoukou; fp = fopen("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); END:; } void place_piece(int file, int rank, const char *piece) { // file: 1..9 (左から1列目を1とする) // rank: 1..9 (上から1行目を1とする) if (file < 1 || file > BOARD_SIZE || rank < 1 || rank > BOARD_SIZE) return; int Screen_y = ORIGIN_Y + (rank - 1) * CELL_H; int Screen_x = ORIGIN_X + (file - 1) * CELL_W; // 少し中央寄せ mvaddstr(Screen_y, Screen_x, piece); } void draw_board() { // タイトル 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) { attron(COLOR_PAIR(2)); // カーソル位置反転 mvprintw(sy, sx, "%s", board[y][x] ? board[y][x] : " "); attroff(COLOR_PAIR(2)); } else { attron(COLOR_PAIR(1)); mvprintw(sy, sx, "%s", board[y][x] ? board[y][x] : " "); attroff(COLOR_PAIR(1)); } } } } int main(void) { setlocale(LC_ALL, ""); SetConsoleOutputCP(CP_UTF8); initscr(); start_color(); // 色機能を有効化 init_pair(1, COLOR_WHITE, COLOR_BLACK); // 白文字+黒背景 init_pair(2, COLOR_BLACK, COLOR_WHITE); // 黒文字+白背景(反転用) noecho(); cbreak(); keypad(stdscr, TRUE); csv_read(); // 盤面初期化(5五に歩を置く) memset(board, 0, sizeof(board)); board[4][4] = "歩"; while (1) { clear(); draw_board(); refresh(); int ch = getch(); if (ch == 'q') break; switch (ch) { case KEY_UP: if (cursor_y > 1) cursor_y--; break; case KEY_DOWN: if (cursor_y < BOARD_SIZE) cursor_y++; break; case KEY_LEFT: if (cursor_x > 1) cursor_x--; break; case KEY_RIGHT: if (cursor_x < BOARD_SIZE) cursor_x++; break; case '\n': // UNIX系 case '\r': // Windows系 case KEY_ENTER: // PDCurses用 { if (!is_selected) { // 駒を持ち上げる if (board[cursor_y-1][cursor_x-1] != NULL) { is_selected = 1; from_x = cursor_x; from_y = cursor_y; } } else { // 移動先に置く board[cursor_y-1][cursor_x-1] = board[from_y-1][from_x-1]; board[from_y-1][from_x-1] = NULL; is_selected = 0; } break; } } } endwin(); return 0; }

shougi_shisaku.h

#pragma once typedef struct koma_info { int tate; // 位置_縦 int yoko; // 位置_横 int sente; // 先手_後手 char koma[10]; // 駒の種類 } person; typedef struct koma_shurui { char koma[10]; // 駒の種類 } motikoma;

・shougi_banmen.csv

後香,後桂,後銀,後金,後王,後金,後銀,後桂,後香, ,後飛,,,,,,後角,, 後歩,後歩,後歩,後歩,後歩,後歩,後歩,後歩,後歩, ,,,,,,,,, ,,,,,,,,, ,,,,,,,,, 先歩,先歩,先歩,先歩,先歩,先歩,先歩,先歩,先歩, ,先角,,,,,,先飛,, 先香,先桂,先銀,先金,先王,先金,先銀,先桂,先香,

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; // 次の文字のアドレス } }

イメージ説明

イメージ説明

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

質問に詳細を記載した。

該当のソースコード

特になし

試したこと・調べたこと

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

質問に詳細を記載した。

補足

特になし

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

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

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

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

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

melian

2025/10/02 11:20

「駒を描画」の部分で、変数 sx と sy が使われていません。これらは描画位置を指定するための座標値でしょうから、以下の様にするのではないでしょうか。 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; mvprintw(sy, sx, "%s", board[y][x] ? board[y][x] : " ");
jimbe

2025/10/02 11:46

ソースコードに対しては、コードのマークダウンの最初の「```」に言語名(件ではc言語ですので 'c')を付けて「```c」とすると、キーワードに色が付いたり行番号が付いたりしますので、ご活用ください。
todasan

2025/10/02 11:53

jimbeさん 了解しました。
todasan

2025/10/02 11:56

melian さん ご指摘通りに直したら、歩は意図通りに直りました。ありがとうございます。 質問内容を編集して、再度、投稿しましたが、カーソルを歩につけても歩は白に囲まれて、 色が変わりません。何か分かればご指摘は可能でしょうか。
thkana

2025/10/02 23:03

> 質問内容を編集して、再度、投稿しました あとから読む人には、それまでおこなわれたやりとりの意味が不明になります。修正や追記はいいですけれど、改変はやめてください。 修正、追記の範囲を超えるなら、新しい質問にしてください。質問が消費ポイント制だったりとか質問回数に制限があったりするわけではないですから。それによって回答者からみたあなたの評価が「質問を乱発する人」になる危険はありますが、もう遅いかと思いますのでいまさら恐れることはないでしょう。
thkana

2025/10/02 23:46

ぱっと見る限り、 ``` if (cursor_y - 1 == y && cursor_x - 1 == x) { attron(COLOR_PAIR(2)); // カーソル位置反転 <略> } else { <略> } ``` の部分でカーソル位置の文字を反転表示しているので、 > 画像のように歩が白くなり はプログラムに書いてある動作かと思います。 これはこれでそれっぽい動作なので、そうなるとあなたの期待する動作とあなたの書いたプログラムの動作が異なっているのでは...という話になるわけですが「どうなればあなたの期待通りなのか」が実は書かれていません。ひとこと「色が変わるつもり」とあるだけ。 コマがカーソル位置のとき、カーソル位置でないとき、それぞれどうなるのが期待値なのか教えてください。 また、あなたの意図したように「色を変える」処理はソースコードのどの部分ですか?
todasan

2025/10/03 01:08 編集

thkana さん コマがカーソル位置の時が、白の背面に黒文字を期待していました。画像のように。 それはそのようになっています。 コマがカーソル位置でない時は、白文字と黒の背景であってほしいですが、 上記と同じままです。 ソースコードでは以下の部分です。 ------------------------------------------------------------------------------------ init_pair(1, COLOR_WHITE, COLOR_BLACK); // 白文字+黒背景 init_pair(2, COLOR_BLACK, COLOR_WHITE); // 黒文字+白背景(反転用) if (cursor_y - 1 == y && cursor_x - 1 == x) { attron(COLOR_PAIR(2)); // カーソル位置反転 mvprintw(sy, sx, "%s", board[y][x] ? board[y][x] : " "); attroff(COLOR_PAIR(2)); } else { attron(COLOR_PAIR(1)); mvprintw(sy, sx, "%s", board[y][x] ? board[y][x] : " "); attroff(COLOR_PAIR(1)); } ------------------------------------------------------------------------------------
thkana

2025/10/03 03:52

ふ~ん、そうなんだ... こないだの質問/回答みたいに、そこで意図通りに切り替えの分岐をしているかどうか、printf()でも埋め込んで様子を覗いてみたらどうなっているかしら?9x9回繰り返すところなので改行しないとかの気遣いがないと画面が流れちゃうかもしれないけれど。 (前回の回答で、思い通りじゃありません->教えて、に直行しないで自分で調べる話をしたつもりだったのだけどなぁ)
thkana

2025/10/03 05:34 編集

[修正あり] あと、そこの2カ所のmvprintwを両方 mvprintw(sy, sx, "%s", "歩"); //修正 とでもしてその結果について考察してみてください。 (私だったら、同じのを2度書くのいやだから ```C int tmp_col = 1; if (cursor_y - 1 == y && cursor_x - 1 == x) { tmp_col=2;// カーソル位置表示色反転(なにを反転するのか明示する書き方を) } attron(COLOR_PAIR(tmp_col)); mvprintw(sy, sx, "%s", board[y][x] ? board[y][x] : " "); attroff(COLOR_PAIR(tmp_col)); ``` とか書きそうだけどそれはまた別の話)
jimbe

2025/10/03 16:03

ちなみに、反転なら A_REVERSE を(色も必要なら | で繋げて) attr に設定すれば(わざわざ反転した COLOR_PAIR を用意しなくても)いいんじゃないでしょうか。
jimbe

2025/10/04 14:35

編集履歴を見ましたら、melian さんのコメントのご指摘の後の編集で、 addstr → mvprintw の変更の他に attron/off に付いていた |A_REVERSE を取り除いていたんですね。 それによってカーソル位置の表示が(本来の想定通りに?)変わったはずなのですが、それを確認せずに書かれてしまったように見えます。
guest

回答2

0

ベストアンサー

コマがカーソル位置でない時は、白文字と黒の背景であってほしい

Windows11 に(MSYS2 で)インストールしている C コンパイラは gcc ではなく clang なので御参考です。

Makefile で CC=clang に設定し make すれば,特に問題なくコンパイルできました。
また,実行すると提示されている画面で起動できました。

PowerShell

1PS > clang --version 2clang version 21.1.1 3PS > make 4clang -c shougi_test.c -I. -Wall 5clang -c explode.c -I. -Wall 6clang -o myapp.exe shougi_test.o explode.o -lpdcurses 7PS > .\myapp.exe 8

次に,下向きの矢印キー(↓)を押すと下の画面となりますので意図(コマがカーソル位置でない時は白文字と黒の背景)どおりに動いていると思われます。

参考画面

なお,今回の質問内容とは関係ありませんが,文字の上で2回続けて Enter キーを押すと文字が消えてしまうので,下記の修正を加えた方が良いかもしれません。

C

1 // 移動先に置く 2 board[cursor_y-1][cursor_x-1] = board[from_y-1][from_x-1]; 3 board[from_y-1][from_x-1] = NULL; 4 is_selected = 0; 5 6 // カーソルが移動した場合のみ NULL に書き換えるように if 文を追加 7 8 // 移動先に置く 9 board[cursor_y-1][cursor_x-1] = board[from_y-1][from_x-1]; 10 if (cursor_y != from_y || cursor_x != from_x) 11 board[from_y-1][from_x-1] = NULL; 12 is_selected = 0;

投稿2025/10/04 09:18

編集2025/10/04 14:15
little_street

総合スコア543

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

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

todasan

2025/10/05 05:55

little_street さん ---------------------------------- 次に,下向きの矢印キー(↓)を押すと下の画面となりますので意図(コマがカーソル位置でない時は白文字と黒の背景)どおりに動いていると思われます。 ---------------------------------- カーソルは白地の正方形だったという事ですか。ありがとうございます。 駒の上に、エンター釦を2回押すと、消える事も解決しました。
thkana

2025/10/05 10:13

> コマがカーソル位置の時が、白の背面に黒文字を期待していました。 空白文字だから黒の部分がなくて背景が全部白。 > カーソルは白地の正方形だったという事ですか。 だから、「どうなることを期待しているのか」を言葉にしてみて欲しかったのだけれど。
todasan

2025/10/05 12:54

little_street さん 以下の線の部分で、白文字に黒背景という事で、カーソルに駒がない部分は、その部分が全て黒になると、 思っていました。でも白の正方形が残っていたのでそれがカーソルなのかと思いました。 しかし、この部分はまた改良して、問題はなくなりました。 ---------------------------------- 次に,下向きの矢印キー(↓)を押すと下の画面となりますので意図(コマがカーソル位置でない時は白文字と黒の背景)どおりに動いていると思われます。 ---------------------------------- 指摘を受けて改良して、問題もなくなりましたので、助かりました。
guest

0

※回答ではありません
Cygwin なので MinGW とは一部違うと思いますが、自分側の駒選択・移動先候補表示・移動が出来るものを作ってみました。
あまり整理されていませんし curses を良く知っている訳でもありませんが、色とか反転・点滅を使ってみましたので1つサンプル的に見て頂ければ。

test.c

c

1//#define PDCURSES //PDCursesを使う場合はコレを有効に 2 3#include <stdio.h> 4#include <string.h> 5#include <time.h> 6#include <locale.h> 7 8#ifdef PDCURSES 9#include <windows.h> 10#include <pdcurses.h> 11#else 12#include <unistd.h> 13#include <ncurses.h> 14#endif 15 16#define BOARD_XOFF 2 17#define BOARD_YOFF 1 18 19#define lengthof(array) (sizeof(array)/sizeof((array)[0])) 20#define dirsign(side) ((side)==1?-1:(side)==2?1:0) 21 22void init() { 23 setlocale(LC_ALL, ""); //日本語の化け対策 24#ifdef PDCURSES 25 SetConsoleOutputCP(CP_UTF8); 26#endif 27 initscr(); 28 noecho(); 29 cbreak(); 30 timeout(0); 31 curs_set(0); 32 keypad(stdscr, TRUE); 33 34 start_color(); 35 init_pair(1, COLOR_BLUE, COLOR_BLACK); 36 //init_pair(2, COLOR_RED, COLOR_BLACK); 37 init_pair(3, COLOR_MAGENTA, COLOR_BLACK); 38 //init_pair(4, COLOR_GREEN, COLOR_BLACK); 39 init_pair(5, COLOR_CYAN, COLOR_BLACK); 40 //init_pair(6, COLOR_YELLOW, COLOR_BLACK); 41 init_pair(7, COLOR_WHITE, COLOR_BLACK); 42 bkgd(COLOR_PAIR(7)); 43} 44 45void term() { 46 echo(); 47 timeout(-1); 48 endwin(); 49} 50 51void print_surface() { 52 const char *r[] = {"一","二","三","四","五","六","七","八","九"}; 53 54 attrset(COLOR_PAIR(1)); 55 int y = BOARD_YOFF; 56 mvaddstr(y++, BOARD_XOFF+1, "9 8 7 6 5 4 3 2 1"); 57 for(int i=0; ; ++i) { 58 mvaddstr(y++, BOARD_XOFF, "+"); 59 for(int j=0; j<9; ++j) addstr("--+"); 60 if(i >= 9) break; 61 mvaddstr(y++, BOARD_XOFF, "|"); 62 for(int j=0; j<9; ++j) addstr(" |"); 63 addstr(r[i]); 64 } 65} 66 67struct _game; 68 69typedef struct { 70 char *face; 71 int (*mm_func)(struct _game*,int,int); 72 int promoted; 73 int original; 74} PIECE; 75 76typedef struct _game { 77 const PIECE *piece[9][9]; 78 int side[9][9]; 79 int movable[9][9]; 80 int cx, cy; //カーソル位置 81 int sx, sy; //選択中駒位置 82} GAME; 83 84const char *get_face(GAME *game, int y, int x) { 85 if(game->piece[y][x]) return game->piece[y][x]->face; 86 return game->movable[y][x] ? "〇" : " "; 87} 88 89const int COLOR[] = { 7, 5, 3 }; 90 91int get_attr(GAME *game, int y, int x) { 92 return (game->movable[y][x] ? A_BLINK : 0) | //移動可 93 (game->sx==x&&game->sy==y ? A_BOLD : 0) | //選択駒 94 (game->cx==x&&game->cy==y ? A_REVERSE : 0) | //カーソル 95 COLOR_PAIR(COLOR[game->side[y][x]]); //陣営別色 96} 97 98void print_game(GAME *game) { 99 for(int y=0, yy=BOARD_YOFF+2; y<9; ++y, yy+=2) { 100 for(int x=0, xx=BOARD_XOFF+1; x<9; ++x, xx+=3) { 101 attrset(get_attr(game,y,x)); 102 mvaddstr(yy, xx, get_face(game,y,x)); 103 } 104 } 105} 106 107int on_board(int y, int x) { 108 return (0 <= y && y <= 8) && (0 <= x && x <= 8); 109} 110 111int mm_pattern(GAME *game, int y, int x, const int *d, int size) { 112 int side = game->side[y][x]; 113 int ds = dirsign(side); 114 int count = 0; 115 for(int i=0; i<size; i+=2) { 116 int yy = y + d[i] * ds; 117 int xx = x + d[i+1] * ds; 118 if(!on_board(yy,xx) || game->side[yy][xx]==side) continue; 119 game->movable[yy][xx] = 1; 120 ++count; 121 } 122 return count; 123} 124 125int mm_line(GAME *game, int y, int x, int dy, int dx) { 126 int side = game->side[y][x]; 127 int ds = dirsign(side); 128 int count = 0; 129 do { 130 y += dy * ds; 131 x += dx * ds; 132 if(!on_board(y,x) || game->side[y][x]==side) break; 133 game->movable[y][x] = 1; 134 ++count; 135 } while(!game->side[y][x]); 136 return count; 137} 138 139//marking_movable functions 140//王/玉 141int mm_0(GAME *game, int y, int x) { 142 const int d[] = { 0,1, 1,1, 1,0, 1,-1, 0,-1, -1,-1, -1,0, -1,1 }; //8方向 143 return mm_pattern(game, y, x, d, lengthof(d)); 144} 145//金 146int mm_1(GAME *game, int y, int x) { 147 const int d[] = { 0,1, 1,1, 1,0, 1,-1, 0,-1, -1,0 }; //斜め後ろ以外 148 return mm_pattern(game, y, x, d, lengthof(d)); 149} 150//銀 151int mm_2(GAME *game, int y, int x) { 152 const int d[] = { 1,1, 1,0, 1,-1, -1,-1, -1,1 }; //横後ろ以外 153 return mm_pattern(game, y, x, d, lengthof(d)); 154} 155//桂 156int mm_3(GAME *game, int y, int x) { 157 const int d[] = { 2,1, 2,-1 }; //二つ前の左右 158 return mm_pattern(game, y, x, d, lengthof(d)); 159} 160//香 161int mm_4(GAME *game, int y, int x) { 162 return mm_line(game, y, x, 1, 0); 163} 164const int DIR_STRAIGHT[] = { 0,1, 1,0, 0,-1, -1,0 }; //前後左右 165const int DIR_DIAGONAL[] = { 1,1, 1,-1, -1,-1, -1,1 }; //斜め 166//角 167int mm_5(GAME *game, int y, int x) { 168 int count = 0; 169 for(int i=0; i<lengthof(DIR_DIAGONAL); i+=2) { 170 count += mm_line(game, y, x, DIR_DIAGONAL[i], DIR_DIAGONAL[i+1]); 171 } 172 return count; 173} 174//飛 175int mm_6(GAME *game, int y, int x) { 176 int count = 0; 177 for(int i=0; i<lengthof(DIR_STRAIGHT); i+=2) { 178 count += mm_line(game, y, x, DIR_STRAIGHT[i], DIR_STRAIGHT[i+1]); 179 } 180 return count; 181} 182//歩 183int mm_7(GAME *game, int y, int x) { 184 int side = game->side[y][x]; 185 y += dirsign(side); 186 if(!on_board(y, x) || game->side[y][x]==side) return 0; 187 game->movable[y][x] = 1; 188 return 1; 189} 190//馬 191int mm_8(GAME *game, int y, int x) { 192 return mm_5(game, y, x) + 193 mm_pattern(game, y, x, DIR_STRAIGHT, lengthof(DIR_STRAIGHT)); 194} 195//龍 196int mm_9(GAME *game, int y, int x) { 197 return mm_6(game, y, x) + 198 mm_pattern(game, y, x, DIR_DIAGONAL, lengthof(DIR_DIAGONAL)); 199} 200 201const PIECE PIECES[] = { 202 { "王", mm_0, -1, -1 }, 203 { "玉", mm_0, -1, -1 }, 204 { "金", mm_1, -1, 2 }, 205 { "銀", mm_2, 9, 3 }, 206 { "桂", mm_3, 10, 4 }, 207 { "香", mm_4, 11, 5 }, 208 { "角", mm_5, 12, 6 }, 209 { "飛", mm_6, 13, 7 }, 210 { "歩", mm_7, 14, 8 }, 211 { "ぎ", mm_1, -1, 3 }, 212 { "き", mm_1, -1, 4 }, 213 { "キ", mm_1, -1, 5 }, 214 { "馬", mm_8, -1, 6 }, 215 { "龍", mm_9, -1, 7 }, 216 { "と", mm_1, -1, 8 }, 217}; 218 219const int INIT_PIECES[] = { 220 //y,x,PIECES_index 221 0,0,5, 0,1,4, 0,2,3, 0,3,2, 0,4,1, 0,5,2, 0,6,3, 0,7,4, 0,8,5, 222 1,1,7, 1,7,6, 223 2,0,8, 2,1,8, 2,2,8, 2,3,8, 2,4,8, 2,5,8, 2,6,8, 2,7,8, 2,8,8, 224 6,0,8, 6,1,8, 6,2,8, 6,3,8, 6,4,8, 6,5,8, 6,6,8, 6,7,8, 6,8,8, 225 7,1,6, 7,7,7, 226 8,0,5, 8,1,4, 8,2,3, 8,3,2, 8,4,0, 8,5,2, 8,6,3, 8,7,4, 8,8,5, 227}; 228 229void clear_select(GAME *game) { 230 memset(game->movable, 0, sizeof(game->movable)); 231 game->sy = game->sx = -1; 232} 233 234void init_game(GAME *game) { 235 memset(game, 0, sizeof(GAME)); 236 for(int i=0; i<lengthof(INIT_PIECES); ) { 237 int y = INIT_PIECES[i++]; 238 int x = INIT_PIECES[i++]; 239 int j = INIT_PIECES[i++]; 240 game->piece[y][x] = &PIECES[j]; 241 game->side[y][x] = y<=2 ? 2 : 1; 242 } 243 clear_select(game); 244 game->cx = 4; 245 game->cy = 8; 246} 247 248void select_piece(GAME *game) { 249 int cancel = game->cy==game->sy && game->cx==game->sx; 250 clear_select(game); 251 if(!cancel) { 252 int y = game->cy, x = game->cx; 253 if((*game->piece[y][x]->mm_func)(game,y,x) > 0) { 254 game->sy = y; 255 game->sx = x; 256 } 257 } 258} 259 260void move_piece(GAME *game) { 261 int cy = game->cy, cx = game->cx; 262 int sy = game->sy, sx = game->sx; 263 game->piece[cy][cx] = game->piece[sy][sx]; 264 game->piece[sy][sx] = NULL; 265 game->side[cy][cx] = game->side[sy][sx]; 266 game->side[sy][sx] = 0; 267 clear_select(game); 268} 269 270int main(int argc, char *argv[]) { 271 init(); 272 273 GAME game; 274 init_game(&game); 275 276 print_surface(); 277 print_game(&game); 278 refresh(); 279 280 int turn = 1; 281 for(int key; (key=getch())!='q'; usleep(200)) { 282 int y = game.cy, x = game.cx; 283 switch(key) { 284 case KEY_UP: if(y > 0) --game.cy; break; 285 case KEY_DOWN: if(y < 8) ++game.cy; break; 286 case KEY_LEFT: if(x > 0) --game.cx; break; 287 case KEY_RIGHT: if(x < 8) ++game.cx; break; 288 case ' ': if(game.side[y][x] == turn) select_piece(&game); 289 else if(game.movable[y][x]) move_piece(&game); 290 break; 291 } 292 print_game(&game); 293 } 294 295 term(); 296 297 return 0; 298}

投稿2025/10/04 07:45

編集2025/10/07 09:15
jimbe

総合スコア13429

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

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

todasan

2025/10/05 05:47

jimbe さん ありがとうございます。参考にしてみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.29%

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

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

質問する

関連した質問