前提
ここに質問の内容を詳しく書いてください。
(例)
C言語で軽いゲームのようなものを作っています。
いわゆる迷路ゲームのようなものです。
■■な機能を実装中に以下のエラーメッセージが発生しました。
実現したいこと
ここに実現したいことを箇条書きで書いてください。
ステージの切り替えを行いたいです。
発生している問題・エラーメッセージ
’N’を押したら次のステージへ、’P’を押したら前のステージへ進めるようにしたいのですが、どうしたらよいのか分かりません。222行目に if ((ch == 'n') || (ch == 'N')) {} と書いて、ここに必要な処理を組み込みたいのですがよくわかりません。 ステージそのものはすでに作成済みで、ソースコードの中にあります。
該当のソースコード
C
1#include <stdio.h> 2 3#include <ncurses.h> // 今回の表示全般に必要 4 5#include <stdlib.h> // system()に必要 6 7#include <locale.h> // setlocale()による表示日本語化に必要 8 9 10 11// map[][]の要素やCOLOR_PAIR()を参照するときに使うあだ名 12 13#define HERO 1 14 15#define EXIT 2 16 17#define WALL 3 18 19#define ROAD 4 20 21#define HAKO 5 22 23#define KAGI 6 24 25#define MESG 10 26 27 28 29// ヒーローの上下左右のマスを参照するときのあだ名 30 31#define HERO_UPPER map[hero_y - 1][hero_x] // ヒーローの1個上のマス 32 33#define HERO_UPPER2 map[hero_y - 2][hero_x] // ヒーローの2個上のマス 34 35#define HERO_LOWER map[hero_y + 1][hero_x] // ヒーローの1個下のマス 36 37#define HERO_LOWER2 map[hero_y + 2][hero_x] // ヒーローの2個下のマス 38 39#define HERO_LEFT map[hero_y][hero_x - 1] // ヒーローの1個左のマス 40 41#define HERO_LEFT2 map[hero_y][hero_x - 2] // ヒーローの2個左のマス 42 43#define HERO_RIGHT map[hero_y][hero_x + 1] // ヒーローの1個右のマス 44 45#define HERO_RIGHT2 map[hero_y][hero_x + 2] // ヒーローの2個右のマス 46 47 48 49// ゲーム中の状態 50 51#define LOCKED 1 // 未回収の鍵があり出口が閉じている状態 52 53#define UNLOCKED 2 // 鍵を全部回収して出口が開いた状態 54 55#define FINISHED 3 // 出口から脱出してゲームをクリアした状態 56 57#define GAMEOVER 4 58 59 60 61// getch()でのキー入力の待ち時間(単位:ms) 62 63// 永久ループのインターバルを兼ねている 64 65#define GETCH_WAIT 100 66 67 68 69// このゲームの配色を設定する 70 71void setup_my_colors(void) 72 73{ 74 75 // 使える色名はCOLOR_{BLACK|RED|GREEN|YELLOW|BLUE|MAGENTA|CYAN|WHITE} 76 77 init_color(COLOR_BLACK, 0, 0, 0); //RGB成分を0〜1000で指定 78 79 init_color(COLOR_WHITE, 1000, 1000, 1000); 80 81 init_color(COLOR_CYAN, 200, 800, 1000); 82 83 init_color(COLOR_GREEN, 200, 1000, 300); 84 85 init_color(COLOR_BLUE, 200, 300, 450); 86 87 init_color(COLOR_YELLOW, 1000, 1000, 200); 88 89 90 91 init_pair(HERO, COLOR_CYAN, COLOR_BLACK); 92 93 init_pair(EXIT, COLOR_GREEN, COLOR_BLACK); 94 95 init_pair(WALL, COLOR_BLUE, COLOR_BLUE); 96 97 init_pair(ROAD, COLOR_BLACK, COLOR_BLACK); 98 99 init_pair(HAKO, COLOR_YELLOW, COLOR_BLACK); 100 101 init_pair(KAGI, COLOR_WHITE, COLOR_BLACK); 102 103 init_pair(MESG, COLOR_WHITE, COLOR_BLACK); 104 105} 106 107 108 109void put_mesg_count(int y, int x, int n) 110 111{ 112 113 attrset(COLOR_PAIR(MESG)); 114 115 mvprintw(y, x * 2, "残り歩数:%d", n); 116 117} 118 119// ヒーロー「大」を指定の座標に表示する関数(👻🐘🐧等で代替可) 120 121void put_hero(int y, int x) 122 123{ 124 125 attrset(COLOR_PAIR(HERO)); mvaddstr(y, x * 2, "大"); 126 127} 128 129 130 131// 出口「且」を指定の座標に表示する関数(🚪等で代替可) 132 133void put_exit(int y, int x) 134 135{ 136 137 attrset(COLOR_PAIR(EXIT)); mvaddstr(y, x * 2, "且"); 138 139} 140 141 142 143// 壁を指定の座標に表示する関数(全角空白、⛰等で代替可) 144 145void put_wall(int y, int x) 146 147{ 148 149 attrset(COLOR_PAIR(WALL)); mvaddstr(y, x * 2, " "); 150 151} 152 153 154 155// 道を指定の座標に表示する関数(全角空白) 156 157void put_road(int y, int x) 158 159{ 160 161 attrset(COLOR_PAIR(ROAD)); mvaddstr(y, x * 2, " "); 162 163} 164 165 166 167// 箱「田」を指定の座標に表示する関数(📦🗿💩等で代替可) 168 169void put_hako(int y, int x) 170 171{ 172 173 attrset(COLOR_PAIR(HAKO)); mvaddstr(y, x * 2, "田"); 174 175} 176 177 178 179// 鍵「¶」を指定の座標に表示する関数(🔑🗝💍等で代替可) 180 181void put_kagi(int y, int x) 182 183{ 184 185 attrset(COLOR_PAIR(KAGI)); mvaddstr(y, x * 2, "¶"); 186 187} 188 189 190 191// 一般的なメッセージを指定の座標に表示する関数 192 193void put_mesg_main(int y, int x, char s[]) 194 195{ 196 197 attrset(COLOR_PAIR(MESG)); mvaddstr(y, x * 2, s); 198 199} 200 201 202 203// 未回収の鍵の個数を指定の座標に表示する関数 204 205void put_mesg_kagi(int y, int x, int n) 206 207{ 208 209 attrset(COLOR_PAIR(MESG)); 210 211 mvprintw(y, x * 2, "Uncollected ¶ × %d", n); 212 213 // 🔑🗝💍等を使う場合はここの絵文字↑もそれに合わせること 214 215} 216 217 218 219int main(void) 220 221{ 222 223 // マップ1 ここから ------------------------------ 224 225 int map_size_y = 13; // マップの縦幅 226 227 int map_size_x = 16; // マップの横幅 228 229 int hero_y = 5; // ヒーローのy座標の初期値 230 231 int hero_x = 13; // ヒーローのx座標の初期値 232 233 int uncollected_keys = 4; // 拾わなくてはならない鍵の個数 234 235 int count = 70; 236 237 238 239 // 2:出口、3:壁、4:道、5:箱、6:鍵 240 241 int map[][100] = { // とりあえずガバッっと大きめに横100で確保してある 242 243 { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }, 244 245 { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }, 246 247 { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }, 248 249 { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }, 250 251 { 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4 }, 252 253 { 4, 3, 6, 4, 4, 3, 3, 4, 3, 4, 4, 6, 3, 4, 3, 4 }, 254 255 { 4, 3, 3, 5, 4, 4, 4, 4, 4, 5, 4, 4, 5, 5, 3, 4 }, 256 257 { 4, 3, 6, 4, 3, 5, 4, 5, 4, 3, 5, 4, 5, 4, 3, 4 }, 258 259 { 4, 3, 3, 4, 4, 5, 4, 5, 4, 3, 4, 5, 3, 4, 3, 4 }, 260 261 { 4, 3, 2, 5, 4, 4, 3, 4, 5, 4, 4, 5, 4, 4, 3, 4 }, 262 263 { 4, 3, 3, 4, 4, 4, 4, 5, 4, 6, 3, 3, 5, 4, 3, 4 }, 264 265 { 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4 }, 266 267 { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }, 268 269 }; 270 271 // マップ1 ここまで ------------------------------ 272 273 274 275/*** 276 277 // マップ2 ここから ------------------------------ 278 279 int map_size_y = 16; // マップの縦幅 280 281 int map_size_x = 19; // マップの横幅 282 283 int hero_y = 8; // ヒーローのy座標の初期値 284 285 int hero_x = 6; // ヒーローのx座標の初期値 286 287 int uncollected_keys = 9; // 拾わなくてはならない鍵の個数 288 289 290 291 // 2:出口、3:壁、4:道、5:箱、6:鍵 292 293 int map[][100] = { // とりあえずガバッっと大きめに横100で確保してある 294 295 { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }, 296 297 { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }, 298 299 { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }, 300 301 { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }, 302 303 { 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4 }, 304 305 { 4, 3, 4, 5, 4, 4, 4, 4, 3, 3, 3, 3, 4, 5, 4, 3, 4 }, 306 307 { 4, 3, 4, 5, 3, 3, 4, 4, 4, 4, 5, 4, 4, 4, 6, 3, 4 }, 308 309 { 4, 3, 6, 4, 3, 6, 5, 5, 5, 6, 3, 3, 4, 5, 4, 3, 4 }, 310 311 { 4, 3, 5, 3, 4, 3, 4, 2, 5, 3, 3, 6, 3, 3, 5, 3, 4 }, 312 313 { 4, 3, 4, 4, 4, 3, 5, 4, 4, 5, 4, 5, 4, 4, 6, 3, 4 }, 314 315 { 4, 3, 6, 3, 5, 5, 5, 3, 4, 3, 4, 3, 4, 3, 3, 3, 4 }, 316 317 { 4, 3, 3, 6, 4, 5, 4, 4, 4, 3, 4, 3, 6, 3, 3, 3, 4 }, 318 319 { 4, 3, 3, 4, 3, 4, 3, 3, 3, 3, 4, 4, 5, 4, 3, 3, 4 }, 320 321 { 4, 3, 4, 4, 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 4 }, 322 323 { 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4 }, 324 325 { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }, 326 327 }; 328 329 // マップ2 ここまで ------------------------------ 330 331***/ 332 333 334 335/*** 336 337 // マップ3 ここから ------------------------------ 338 339 int map_size_y = 18; // マップの縦幅 340 341 int map_size_x = 20; // マップの横幅 342 343 int hero_y = 15; // ヒーローのy座標の初期値 344 345 int hero_x = 2; // ヒーローのx座標の初期値 346 347 int uncollected_keys = 9; // 拾わなくてはならない鍵の個数 348 349 350 351 // 2:出口、3:壁、4:道、5:箱、6:鍵 352 353 int map[][100] = { // とりあえずガバッっと大きめに横100で確保してある 354 355 { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }, 356 357 { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }, 358 359 { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }, 360 361 { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }, 362 363 { 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4 }, 364 365 { 4, 3, 4, 4, 4, 4, 4, 3, 3, 3, 3, 6, 3, 4, 4, 4, 4, 4, 3, 4 }, 366 367 { 4, 3, 4, 3, 3, 3, 4, 3, 6, 4, 5, 4, 6, 4, 4, 3, 3, 4, 3, 4 }, 368 369 { 4, 3, 4, 3, 3, 3, 4, 3, 4, 3, 4, 3, 6, 3, 3, 3, 4, 4, 3, 4 }, 370 371 { 4, 3, 4, 3, 4, 4, 4, 3, 4, 3, 4, 3, 4, 4, 4, 4, 4, 4, 3, 4 }, 372 373 { 4, 3, 4, 3, 5, 5, 5, 4, 4, 3, 4, 3, 5, 3, 3, 5, 5, 5, 3, 4 }, 374 375 { 4, 3, 2, 3, 4, 6, 4, 3, 3, 3, 4, 4, 5, 6, 3, 4, 6, 4, 3, 4 }, 376 377 { 4, 3, 4, 3, 5, 5, 5, 4, 4, 3, 3, 4, 3, 4, 4, 5, 5, 5, 3, 4 }, 378 379 { 4, 3, 4, 3, 4, 4, 4, 3, 4, 3, 4, 4, 3, 3, 3, 4, 4, 4, 3, 4 }, 380 381 { 4, 3, 4, 3, 3, 3, 4, 3, 4, 3, 4, 3, 3, 3, 3, 3, 3, 4, 3, 4 }, 382 383 { 4, 3, 4, 3, 3, 3, 4, 3, 6, 4, 4, 5, 4, 4, 4, 3, 3, 4, 3, 4 }, 384 385 { 4, 3, 4, 4, 4, 4, 4, 3, 3, 3, 3, 6, 3, 4, 4, 4, 4, 4, 3, 4 }, 386 387 { 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4 }, 388 389 { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }, 390 391 }; 392 393 // マップ3 ここまで ------------------------------ 394 395***/ 396 397 398 399 int state = LOCKED; // 状態(LOCKED, UNLOCKED, FINISHEDのいずれか) 400 401 int ch, y, x; 402 403 404 405 setlocale(LC_ALL,""); // 非ASCII文字(日本語や絵文字)の表示に必要 406 407 initscr(); // ncursesを使用する際、最初におこなう初期化 408 409 start_color(); // カラー表示を開始する 410 411 setup_my_colors(); // このゲームの配色を設定 412 413 curs_set(0); // カーソルを非表示にする 414 415 noecho(); // キー入力を非表示にする 416 417 cbreak(); // Enterキー無しでキー入力を受け取る 418 419 keypad(stdscr, TRUE); // カーソルキーを有効にする 420 421 //(上・下・左・右: KEY_{UP|DOWN|LEFT|RIGHT}) 422 423 timeout(GETCH_WAIT); // getch()で読み取るキー入力の待ち時間(単位:ms) 424 425 426 427 // キーのオートリピートを止める(ゲーム終了時に元に戻すこと) 428 429 system("/usr/bin/xset r off"); 430 431 432 433 while (1) 434 435 { 436 437 ch = getch(); // キー入力を読み取る(Enter不要) 438 439 440 441 if ((ch == 'q') || (ch == 'Q')) { break; } // while(1)から抜ける 442 443 if ((ch == 'n') || (ch == 'N')) 444 445 { } 446 447 448
試したこと
事前に各ステージに番号を振り分けて、’N’を押したらカウントを1足してステージを切り替えようとしましたが、書いてる途中で訳が分からなくなってしまいました。
補足情報(FW/ツールのバージョンなど)
ここにより詳細な情報を記載してください。
if (state != FINISHED) // ゲームがまだクリアされていない状態ならば
{
if (ch == KEY_UP)
{
switch (HERO_UPPER)
{
case ROAD:
hero_y--;
count--;
break;
case EXIT:
hero_y--;
count--;
if (uncollected_keys == 0) { state = FINISHED; } // クリア
break;
case HAKO:
if (HERO_UPPER2 == ROAD)
{
HERO_UPPER2 = HAKO;
HERO_UPPER = ROAD;
hero_y--;
count--;
}
break;
case KAGI:
HERO_UPPER = ROAD;
hero_y--;
count--;
uncollected_keys--;
if (uncollected_keys == 0) { state = UNLOCKED; } // 出口開く
break;
} // switch (HERO_UPPER) ここまで
} // if (ch == KEY_UP) ここまで
else if (ch == KEY_DOWN)
{
switch (HERO_LOWER)
{
case ROAD:
hero_y++;
count--;
break;
case EXIT:
hero_y++;
count--;
if (uncollected_keys == 0) { state = FINISHED; } // クリア
break;
case HAKO:
if (HERO_LOWER2 == ROAD)
{
HERO_LOWER2 = HAKO;
HERO_LOWER = ROAD;
hero_y++;
count--;
}
break;
case KAGI:
HERO_LOWER = ROAD;
hero_y++;
count--;
uncollected_keys--;
if (uncollected_keys == 0) { state = UNLOCKED; } // 出口開く
break;
} // switch (HERO_LOWER) ここまで
} // else if (ch == KEY_DOWN) ここまで
else if (ch == KEY_LEFT)
{
switch (HERO_LEFT)
{
case ROAD:
hero_x--;
count--;
break;
case EXIT:
hero_x--;
count--;
if (uncollected_keys == 0) { state = FINISHED; } // クリア
break;
case HAKO:
if (HERO_LEFT2 == ROAD)
{
HERO_LEFT2 = HAKO;
HERO_LEFT = ROAD;
hero_x--;
count--;
}
break;
case KAGI:
HERO_LEFT = ROAD;
hero_x--;
count--;
uncollected_keys--;
if (uncollected_keys == 0) { state = UNLOCKED; } // 出口開く
break;
} // switch (HERO_LEFT) ここまで
} // else if (ch == KEY_LEFT) ここまで
else if (ch == KEY_RIGHT)
{
switch (HERO_RIGHT)
{
case ROAD:
hero_x++;
count--;
break;
case EXIT:
hero_x++;
count--;
if (uncollected_keys == 0) { state = FINISHED; } // クリア
break;
case HAKO:
if (HERO_RIGHT2 == ROAD)
{
HERO_RIGHT2 = HAKO;
HERO_RIGHT = ROAD;
hero_x++;
count--;
}
break;
case KAGI:
HERO_RIGHT = ROAD;
hero_x++;
count--;
uncollected_keys--;
if (uncollected_keys == 0) { state = UNLOCKED; } // 出口開く
break;
} // switch (HERO_RIGHT) ここまで
} // else if (ch == KEY_RIGHT) ここまで
} // if (state != FINISHED) ここまで
// 表示のための処理開始
clear(); // 画面を消去する
// 画面がちらつくようならerase();に変更してみる
for (y = 0; y < map_size_y; y++)
{
for (x = 0; x < map_size_x; x++)
{
switch (map[y][x])
{
case WALL:
put_wall(y, x);
break;
case ROAD:
put_road(y, x);
break;
case HAKO:
put_hako(y, x);
break;
case KAGI:
put_kagi(y, x);
break;
case EXIT:
put_exit(y, x);
break;
} // switch (map[y][x]) ここまで
} // for (x = 0;〜) ここまで
} // for (y = 0;〜) ここまで
put_hero(hero_y, hero_x);
if(count <= 0)
{
count = 0;
}
put_mesg_count(2, 1, count);
switch (state)
{
case LOCKED: // まだ未回収の鍵があって出口が閉じている状態
put_mesg_main(0, 1, "Pick up all key and go to the exit!");
break;
case UNLOCKED: // 鍵を全部回収して出口が開いた状態
put_mesg_main(0, 1, "Hurry to the exit!");
break;
case FINISHED: // 出口から脱出してゲームをクリアした状態
put_mesg_main(0, 1, "Finished!! Quit \"q\"");
break;
case GAMEOVER:
put_mesg_main(0, 1, "Gameover!! Quit \"q\"");
break;
} // switch (state) ここまで
if(count == 0)
{
state = GAMEOVER;
}
put_mesg_kagi(1, 1, uncollected_keys);
refresh(); // このrefresh()によって実際に画面が再表示される
// 表示のための処理終わり
} // while(1)の永久ループはここまで
// while(1)の永久ループから抜けた後のゲーム終了の処理
endwin(); // ncurserを使った時の後始末
system("/usr/bin/xset r rate 500 33"); // キーのオートリピートを初期値に戻す
return 0;
}
ソースコードが入りきらなかったためこちらに追加しておきます。
コメントに長いコードは書かないでください。コードだけ縮小表示されたりはしません。
入りきらなければ、ストレージサービス等を利用してください。
必ず行間に空行を挟む謎のコーディングスタイル(?)は,このような場所にそのまま投稿するには適さないと思う.
ステージとmapって同義に使っていますか? なら統一して欲しいですがそれはともかく。
ステージが切り替わるとはどうなることか、
あるいは、なにがどうなったらステージが切り替わったことになるのか、
考えられていますか?
ステージはありますって・・・コメントになってるデータ群のことですかね。
まさかステージが進む度にコメントを付け直してコンパイルしようってわけじゃないでしょうから全てのステージデータを定義状態に出来た上での切り替え処理であって、切り替えの前の準備がそもそも出来てません、といったところでしょうか。
ステージとマップは同じ意味で使っています。統一すべきでした。すみません。
ステージそのものはコメントになっているデータ群のことで、これを定義状態にするにはどうすればいいのでしょうか
構造のあるデータを複数持つのですから、構造体の配列が妥当でしょう。
> これを定義状態にするには
コメントを外せばよいのではないですか?
シンボルが衝突するなら名前を変えて、使う変数にコピーすればよいです。
先にこっちを聞いておけばよかったかな? このプログラムは自分で作ったのですか? それとも、他人の作ったもの(あるいはその寄せ集め)ですか?
何の前置きもなく「作った」といわれたなら、そこに書かれていることは全て理解しているものとして話をしますがそれでよろしいですか。
回答1件