前提・実現したいこと
1対1の通信追跡ゲーム(鬼ごっこ)を作成しているのですが
鬼ごっこ自体は実装できているのですが、ふたつの位置データがかぶった時、鬼ごっこで言うとタッチした時にゲームを終了させる機能の実装がうまくできてないです。
以下のソースコードをどう編集すればいいか教えて下さい。
該当のソースコード
C++
1#include <stdlib.h> 2#include <string.h> 3#include <signal.h> 4 5#include "tagGame.h" // 鬼ごっこモジュールヘッダファイル 6 7#define MAINWIN_LINES 20 // メインウィンドウの高さ(行数) 8#define MAINWIN_COLUMS 40 // メインウィンドウの横幅(桁数) 9#define MAINWIN_SX 2 // メインウィンドウの左上座標 10#define MAINWIN_SY 1 // メインウィンドウの左上座標 11 12#define MOVE_UP 'i' // 上に移動するキー 13#define MOVE_LEFT 'j' // 左に移動するキー 14#define MOVE_DOWN 'k' // 下に移動するキー 15#define MOVE_RIGHT 'l' // 右に移動するキー 16 17// サーバーが送信するメッセージの最大長さ 18// 自分の座標情報(8byte) + 相手の座標情報(8byte) + '\0' 19#define SERVER_MSG_LEN (8 + 8 + 1) 20 21// クライアントが送信するメッセージの最大長さ 22// 押しているキー情報 + '\0' 23#define CLIENT_MSG_LEN (4 + 1) 24 25//-------------------------------------------------------------------- 26// 鬼ごっこゲームモジュール内部で使用する構造体の定義 27//-------------------------------------------------------------------- 28 29// サーバーに届く入力データ 30typedef struct { 31 int myKey; // ユーザが押しているキー 32 int itKey; // 相手の押しているキー(クライアントから届く) 33 int quit; // ゲームを終了させるメッセージが届いた場合に TRUE 34} ServerInputData; 35 36// クライアントに届く入力データ 37typedef struct { 38 int myKey; // ユーザが押しているキー 39 int myX; // 自分の X 座標(サーバーから届く) 40 int myY; // 自分の Y 座標(サーバーから届く) 41 int itX; // 相手の X 座標(サーバーから届く) 42 int itY; // 相手の Y 座標(サーバーから届く) 43 int quit; // ゲームを終了させるメッセージが届いた場合に TRUE 44} ClientInputData; 45 46//-------------------------------------------------------------------- 47// 鬼ごっこゲームモジュール内部で使用する関数のプロトタイプ宣言 48//-------------------------------------------------------------------- 49static void getServerInputData(TagGame *game, ServerInputData *serverData); 50static void getClientInputData(TagGame *game, ClientInputData *clientData); 51static void updatePlayerStatus(TagGame *game, ServerInputData *serverData); 52static void copyGameState(TagGame *game, ClientInputData *clientData); 53static void printGame(TagGame *game); 54static void sendGameInfo(TagGame *game); 55static void sendMyPressedKey(TagGame *game, ClientInputData *clietData); 56static void die(); 57 58 59//-------------------------------------------------------------------- 60// 外部に公開する関数の定義 61//-------------------------------------------------------------------- 62 63/* 64 * 鬼ごっこゲームの初期化 65 * 引数 : 66 * myChara - 自分を表すキャラクタ 67 * mySX - 自分の開始 X 座標 68 * mySY - 自分の開始 Y 座標 69 * itChara - 相手を表すキャラクタ 70 * itSX - 相手の開始 X 座標 71 * itSY - 相手の開始 Y 座標 72 * 戻値 : 73 * 鬼ごっこゲームオブジェクトへのポインタ 74 */ 75TagGame* initTagGame(char myChara, int mySX, int mySY, 76 char itChara, int itSX, int itSY) 77{ 78 TagGame* game = (TagGame *)malloc(sizeof(TagGame)); 79 80 // すべてのメンバを 0 で初期化 81 bzero(game, sizeof(TagGame)); 82 83 // 84 // ゲームの論理的データの初期化 85 // 86 game->my.chara = myChara; 87 game->my.x = mySX; 88 game->my.y = mySY; 89 game->it.chara = itChara; 90 game->it.x = itSX; 91 game->it.y = itSY; 92 93 // 前回のプレイヤー情報を初期化(現在のプレイヤー情報と同じにする) 94 memcpy(&game->preMy, &game->my, sizeof(Player)); 95 memcpy(&game->preIt, &game->it, sizeof(Player)); 96 97 // 98 // 画面の初期化 99 // 100 initscr(); // curses ライブラリの初期化 101 signal(SIGINT, die); // Ctrl-C 時に端末を復旧する関数 die を登録 102 signal(SIGTERM, die); // kill 時に端末を復旧する関数 die を登録 103 noecho(); // エコーバックの中止 104 cbreak(); // キーボードバッファリングの中止 105 106 // ゲーム画面の作成 107 game->mainWin = newwin(MAINWIN_LINES, MAINWIN_COLUMS, MAINWIN_SY, MAINWIN_SX); 108 109 // 画面が小さい場合 110 if (game->mainWin == NULL) { 111 endwin(); 112 fprintf(stderr, "Error: terminal size is too small\n"); 113 exit(1); 114 } 115 116 // 各制御キーはエスケープシーケンスで表現されている 117 // それを論理キーコードに変換する 118 keypad(game->mainWin, TRUE); 119 120 return game; 121} 122 123/* 124 * 鬼ごっこゲームの準備 125 * 引数 : 126 * game - 鬼ごっこゲームオブジェクトへのポインタ 127 * s - 相手との会話用ファイルデスクリプタ 128 */ 129void setupTagGame(TagGame *game, int s) 130{ 131 // 132 // データ入力のための準備 133 // 134 game->s = s; // 相手との会話用ファイルデスクリプタを登録 135 FD_ZERO(&(game->fdset)); // 入力を監視するファイルデスクリプタマスクを初期化 136 FD_SET(0, &(game->fdset)); // 標準入力(キーボード)を監視する 137 FD_SET(s, &(game->fdset)); // 相手との会話用デスクリプタを監視する 138 game->fdsetWidth = s + 1; // fdset のビット幅(=最大デスクリプタ番号+1) 139 game->watchTime.tv_sec = 0; // 監視時間を 100 msec にセット 140 game->watchTime.tv_usec = 100 * 1000; 141 142 // 143 // 画面の準備 144 // 145 146 // 画面の静的要素の描画 147 box(game->mainWin, ACS_VLINE, ACS_HLINE); 148 149 // 物理画面に描画 150 wrefresh(game->mainWin); 151} 152 153/* 154 * サーバー側鬼ごっこゲームの開始 155 * 引数 : 156 * game - 鬼ごっこゲームオブジェクトへのポインタ 157 */ 158void playServerTagGame(TagGame *game) 159{ 160 ServerInputData serverData; 161 162 while (1) { 163 164 // ユーザのキー入力と相手から届いたキー入力データを読む 165 getServerInputData(game, &serverData); 166 167 // ユーザもしくは相手から終了のメッセージが届いた場合,終了する 168 if (serverData.quit) 169 break; 170 171 // プレイヤーの状態を更新する 172 updatePlayerStatus(game, &serverData); 173 174 // 表示する 175 printGame(game); 176 177 // ゲームの状態を相手に知らせる 178 sendGameInfo(game); 179 } 180 181 // 相手も終了するようメッセージを送る 182 write(game->s, "quit", 5); 183} 184 185 186/* 187 * クライアント側鬼ごっこゲームの開始 188 * 引数 : 189 * game - 鬼ごっこゲームオブジェクトへのポインタ 190 */ 191void playClientTagGame(TagGame *game) 192{ 193 ClientInputData clientData; 194 195 while (1) { 196 197 // ユーザのキー入力と, 相手から届いたゲームの状態を読む 198 getClientInputData(game, &clientData); 199 200 // ユーザもしくは相手から終了のメッセージが届いた場合,終了する 201 if (clientData.quit) 202 break; 203 204 // ゲームの状態を更新する 205 copyGameState(game, &clientData); 206 207 // 表示する 208 printGame(game); 209 210 // 自分の押しているキーを相手に送る 211 sendMyPressedKey(game, &clientData); 212 } 213 214 // 相手も終了するようメッセージを送る 215 write(game->s, "quit", 5); 216} 217 218/* 219 * 鬼ごっこゲームの後始末 220 * 引数 : 221 * game - 鬼ごっこゲームオブジェクトへのポインタ 222 */ 223void destroyTagGame(TagGame *game) 224{ 225 // ウィンドウを廃棄 226 delwin(game->mainWin); 227 // ファイルデスクリプタを閉じる 228 close(game->s); 229 // オブジェクトを解放する 230 free(game); 231 // 端末を元に戻して終了 232 die(); 233} 234 235 236//-------------------------------------------------------------------- 237// 外部に公開しない関数の定義 238//-------------------------------------------------------------------- 239 240 241### 試したこと 242 243ここに問題に対して試したことを記載してください。 244 245### 補足情報(FW/ツールのバージョンなど) 246 247ここにより詳細な情報を記載してください。
「うまくできない」というのは質問者さんご自身がどういう結果になるよう設計していて、実際の動作が設計とどう違うか明記しないと伝わりません。そのあたりを具体的に追記していただいた方が回答が付きやすいと思います。
あなたの回答
tips
プレビュー