#1
by C言語初心者のがくせい » 4年前
初質問です。4月からC言語を習い始めました。
あらかじめ作られたゲームの穴埋めと追加の機能を加えて提出する課題が出されました。
一部取り組んでみましたが、上下左右の移動用の関数の部分が空白になっていて苦戦しています。
ヒントとしてキャラクタの現在の座標を増減させ、成功と失敗とでそれぞれ1と0を返すと示されていました。
また、追加の機能として、斜めの移動等を考えていますがよりよいものがあれば教えていただきたいです。
協力お願いします。
コード:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// 敵の数の指定
#define ENEMYS 10
// 可視領域 ( 範囲 )
#define VISIBLE_AREA 20
// 表示に使用する文字色の宣言
#define BLACK "\x1b[30m"
#define RED "\x1b[31m"
#define GREEN "\x1b[32m"
#define YELLOW "\x1b[33m"
#define BLUE "\x1b[34m"
#define MAGENTA "\x1b[35m"
#define CYAN "\x1b[36m"
#define WHITE "\x1b[37m"
// 表示に使用する文字の背景色の宣言
#define BACKGROUNDGRAY "\x1b[47m"
#define BACKGROUNDBLACK "\x1b[40m"
// 表示に使用する文字の太さを宣言
#define BOLD "\x1b[1m"
#define DEFAULT "\x1b[0m"
// キャラクタ用の構造体
typedef struct CHARACTER {
int x; // キャラクタのx座標→右に移動するほど増える
int y; // キャラクタのy座標→下に移動するほど増える
}CHARACTER;
// 迷路の生成
char field[20][20] = { {'+', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '+'},
{'|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|'},
{'|', ' ', '+', '-', '-', '-', '-', '-', '-', ' ', ' ', '-', '-', '-', '-', '-', '-', '+', ' ', '|'},
{'|', ' ', '|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|', ' ', '|'},
{'|', ' ', '|', ' ', '+', '-', ' ', ' ', '-', '-', '-', '-', ' ', ' ', '-', '+', ' ', '|', ' ', '|'},
{'|', ' ', ' ', ' ', '|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|', ' ', '|', ' ', '|'},
{'|', '-', '|', ' ', '|', ' ', '+', '-', '-', ' ', ' ', '-', '-', '+', ' ', '|', ' ', '|', ' ', '|'},
{'|', ' ', ' ', ' ', '|', ' ', '|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|', ' ', '|', ' ', '|'},
{'|', ' ', '|', ' ', '|', ' ', '|', ' ', '+', '-', '-', '+', ' ', '|', ' ', '|', ' ', ' ', ' ', '|'},
{'|', ' ', '|', ' ', '|', ' ', '|', ' ', ' ', ' ', ' ', '|', ' ', '|', ' ', '|', '-', '|', ' ', '|'},
{'|', ' ', '|', ' ', ' ', ' ', '|', ' ', '|', ' ', ' ', ' ', ' ', '|', ' ', '|', ' ', '|', ' ', '|'},
{'|', ' ', '|', ' ', '|', '-', '|', ' ', '+', '-', '-', '+', ' ', '|', ' ', ' ', ' ', '|', '-', '|'},
{'|', ' ', '|', ' ', '|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|', ' ', '|', ' ', '|', ' ', '|'},
{'|', ' ', '|', ' ', '|', ' ', '+', '-', '-', ' ', ' ', '-', '-', '+', ' ', '|', ' ', '|', ' ', '|'},
{'|', '-', '|', ' ', '|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|', ' ', ' ', ' ', '|'},
{'|', ' ', '|', ' ', '+', '-', ' ', ' ', '-', '-', '-', '-', ' ', ' ', '-', '+', ' ', '|', ' ', '|'},
{'|', ' ', '|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|', ' ', '|'},
{'|', ' ', '+', '-', '-', '-', '-', '-', '-', '-', ' ', ' ', '-', '-', '-', '-', '-', '+', ' ', '|'},
{'|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|'},
{'+', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '+'} };
// 上移動用関数
int Up( CHARACTER *object ) {
return 1;
}
// 下移動用関数
int Down( CHARACTER *object ) {
if(field[][]=' '){
object y +=1;
return 1;
}else{
return 0;
}
}
// 左移動用関数
int Left( CHARACTER *object ) {
return 1;
}
// 右移動用関数
int Right( CHARACTER *object ) {
return 1;
}//上移動用関数からここまでを取り組む
// ユーザに指定された方向へキャラクタを移動させる関数
int Move(int num, CHARACTER *character) {
int res;
switch(num) {
case 2:
res = Down(character);
break;
case 4:
res = Left(character);
break;
case 6:
res = Right(character);
break;
case 8:
res = Up(character);
break;
}
return res;
}
// 敵をランダムに移動させると共に,プレーヤと敵が重なったかどうか(ゲーム終了)を判定する関数
int Enemy(CHARACTER player, CHARACTER enemys[]) {
int rnum, res;
int i;
for( i=0; i<ENEMYS; i++ ) {
do{
rnum = 1 + rand()%4; // 移動方向を指定する数値を乱数で決定 ( 1:下,2:左,3:右,4:上 )
res = Move(rnum*2, &enemys[i]); // 移動方向を示す数値を2倍することで値を2:下,4:左,6:右,8:上に変換
}while( res == 0 );
if( player.x == enemys[i].x && player.y == enemys[i].y ) {
printf("敵に見つかりました... 残念...\n");
return 1;
}
}
return 0;
}
// 現在の状況を表示する関数
void ShowField(CHARACTER player, CHARACTER enemys[], int res) {
int i, j, k;
int flag_e;
// 表示領域 ( 端末の内容 ) をクリア
system("clear");
if( res == 0 ) printf("\n移動できない方向が指定されました.\n");
printf("%s", BOLD);
for( j=0; j<20; j++ ) {
for( i=0; i<20; i++ ) {
flag_e = 0;
for( k=0; k<ENEMYS; k++ ) {
if( j == enemys[k].y && i == enemys[k].x
&& player.y-VISIBLE_AREA <= j && j <= player.y+VISIBLE_AREA // 敵が可視領域にいるかどうかのチェック
&& player.x-VISIBLE_AREA <= i && i <= player.x+VISIBLE_AREA ) { // 敵が可視領域にいるかどうかのチェック
flag_e = 1;
break;
}
}
if( j == player.y && i == player.x ) { // プレーヤを黄色で表示する
printf("%s", YELLOW);
printf("P");
printf("%s", WHITE);
} else if( flag_e == 1 ) { // 敵を赤色で表示する
printf("%s", RED);
printf("E");
printf("%s", WHITE);
} else if (field[j][i] == 'G' ) { // ゴールを緑色で表示する
printf("%s", GREEN);
printf("%c", field[j][i]);
printf("%s", WHITE);
} else if( field[j][i] != ' ' ) { // 壁の背景色を灰色にする
printf("%s", BACKGROUNDGRAY);
printf("%c", field[j][i]);
printf("%s", BACKGROUNDBLACK);
} else {
printf("%c", field[j][i]);
}
}
printf("\n");
}
printf("%s", DEFAULT);
}
int main(void) {
int num, i, res, end = 0;
CHARACTER player = {1, 1}; // プレーヤーの位置(x座標,y座標)を保存する変数 ( 初期位置はx:1, y:1 )
CHARACTER enemys[ENEMYS]; // 敵の位置(x座標,y座標)を保存する配列
CHARACTER goal; // ゴールの位置(x座標,y座標)を保存する変数
// 乱数の初期化 ( 毎回異なる乱数を発生するために必要 )
srand(time(NULL));
// 敵の位置をランダムに決定する
for( i=0; i<ENEMYS; i++ ) {
do{
enemys[i].x = 1 + rand() % 19; // 1〜18までの乱数を発生させる ( 0と19は壁)
enemys[i].y = 1 + rand() % 19; // 1〜18までの乱数を発生させる ( 0と19は壁 )
}while( field[enemys[i].y][enemys[i].x] == '|' || field[enemys[i].y][enemys[i].x] == '-' || field[enemys[i].y][enemys[i].y] == '+' );
}
// ゴールの位置をランダムに決定する
do{
goal.x = 10 + rand() % 9; // 10〜18までの乱数を発生させる ( 19は壁)
goal.y = 10 + rand() % 9; // 10〜18までの乱数を発生させる ( 19は壁)
}while( field[goal.y][goal.x] == '|' || field[goal.y][goal.x] == '-' || field[goal.y][goal.x] == '+' );
field[goal.y][goal.x] = 'G';
// 初期状態を表示
ShowField(player, enemys, 1);
// ゴールに到達するか敵と接触するまで繰り返す
do{
printf("移動する方向の数字を入力してください. (下:2, 左:4, 右:6, 上: 8)\n");
scanf("%d", &num);
// プレーヤを指定された方向へ移動させる
res = Move(num, &player);
// 敵をランダムに移動させ,敵に見つかったかどうかを調べる
end = Enemy(player, enemys);
// 敵に見つかった場合 → ゲーム終了
if( end == 1 ) return 1;
ShowField(player, enemys, res);
}while( player.x != goal.x || player.y != goal.y );
printf("ゴールしました!! おめでとう!!\n");
return 0;
}
初質問です。4月からC言語を習い始めました。
あらかじめ作られたゲームの穴埋めと追加の機能を加えて提出する課題が出されました。
一部取り組んでみましたが、上下左右の移動用の関数の部分が空白になっていて苦戦しています。
ヒントとしてキャラクタの現在の座標を増減させ、成功と失敗とでそれぞれ1と0を返すと示されていました。
また、追加の機能として、斜めの移動等を考えていますがよりよいものがあれば教えていただきたいです。
協力お願いします。
[code]
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// 敵の数の指定
#define ENEMYS 10
// 可視領域 ( 範囲 )
#define VISIBLE_AREA 20
// 表示に使用する文字色の宣言
#define BLACK "\x1b[30m"
#define RED "\x1b[31m"
#define GREEN "\x1b[32m"
#define YELLOW "\x1b[33m"
#define BLUE "\x1b[34m"
#define MAGENTA "\x1b[35m"
#define CYAN "\x1b[36m"
#define WHITE "\x1b[37m"
// 表示に使用する文字の背景色の宣言
#define BACKGROUNDGRAY "\x1b[47m"
#define BACKGROUNDBLACK "\x1b[40m"
// 表示に使用する文字の太さを宣言
#define BOLD "\x1b[1m"
#define DEFAULT "\x1b[0m"
// キャラクタ用の構造体
typedef struct CHARACTER {
int x; // キャラクタのx座標→右に移動するほど増える
int y; // キャラクタのy座標→下に移動するほど増える
}CHARACTER;
// 迷路の生成
char field[20][20] = { {'+', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '+'},
{'|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|'},
{'|', ' ', '+', '-', '-', '-', '-', '-', '-', ' ', ' ', '-', '-', '-', '-', '-', '-', '+', ' ', '|'},
{'|', ' ', '|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|', ' ', '|'},
{'|', ' ', '|', ' ', '+', '-', ' ', ' ', '-', '-', '-', '-', ' ', ' ', '-', '+', ' ', '|', ' ', '|'},
{'|', ' ', ' ', ' ', '|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|', ' ', '|', ' ', '|'},
{'|', '-', '|', ' ', '|', ' ', '+', '-', '-', ' ', ' ', '-', '-', '+', ' ', '|', ' ', '|', ' ', '|'},
{'|', ' ', ' ', ' ', '|', ' ', '|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|', ' ', '|', ' ', '|'},
{'|', ' ', '|', ' ', '|', ' ', '|', ' ', '+', '-', '-', '+', ' ', '|', ' ', '|', ' ', ' ', ' ', '|'},
{'|', ' ', '|', ' ', '|', ' ', '|', ' ', ' ', ' ', ' ', '|', ' ', '|', ' ', '|', '-', '|', ' ', '|'},
{'|', ' ', '|', ' ', ' ', ' ', '|', ' ', '|', ' ', ' ', ' ', ' ', '|', ' ', '|', ' ', '|', ' ', '|'},
{'|', ' ', '|', ' ', '|', '-', '|', ' ', '+', '-', '-', '+', ' ', '|', ' ', ' ', ' ', '|', '-', '|'},
{'|', ' ', '|', ' ', '|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|', ' ', '|', ' ', '|', ' ', '|'},
{'|', ' ', '|', ' ', '|', ' ', '+', '-', '-', ' ', ' ', '-', '-', '+', ' ', '|', ' ', '|', ' ', '|'},
{'|', '-', '|', ' ', '|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|', ' ', ' ', ' ', '|'},
{'|', ' ', '|', ' ', '+', '-', ' ', ' ', '-', '-', '-', '-', ' ', ' ', '-', '+', ' ', '|', ' ', '|'},
{'|', ' ', '|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|', ' ', '|'},
{'|', ' ', '+', '-', '-', '-', '-', '-', '-', '-', ' ', ' ', '-', '-', '-', '-', '-', '+', ' ', '|'},
{'|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|'},
{'+', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '+'} };
// 上移動用関数
int Up( CHARACTER *object ) {
return 1;
}
// 下移動用関数
int Down( CHARACTER *object ) {
if(field[][]=' '){
object y +=1;
return 1;
}else{
return 0;
}
}
// 左移動用関数
int Left( CHARACTER *object ) {
return 1;
}
// 右移動用関数
int Right( CHARACTER *object ) {
return 1;
}//上移動用関数からここまでを取り組む
// ユーザに指定された方向へキャラクタを移動させる関数
int Move(int num, CHARACTER *character) {
int res;
switch(num) {
case 2:
res = Down(character);
break;
case 4:
res = Left(character);
break;
case 6:
res = Right(character);
break;
case 8:
res = Up(character);
break;
}
return res;
}
// 敵をランダムに移動させると共に,プレーヤと敵が重なったかどうか(ゲーム終了)を判定する関数
int Enemy(CHARACTER player, CHARACTER enemys[]) {
int rnum, res;
int i;
for( i=0; i<ENEMYS; i++ ) {
do{
rnum = 1 + rand()%4; // 移動方向を指定する数値を乱数で決定 ( 1:下,2:左,3:右,4:上 )
res = Move(rnum*2, &enemys[i]); // 移動方向を示す数値を2倍することで値を2:下,4:左,6:右,8:上に変換
}while( res == 0 );
if( player.x == enemys[i].x && player.y == enemys[i].y ) {
printf("敵に見つかりました... 残念...\n");
return 1;
}
}
return 0;
}
// 現在の状況を表示する関数
void ShowField(CHARACTER player, CHARACTER enemys[], int res) {
int i, j, k;
int flag_e;
// 表示領域 ( 端末の内容 ) をクリア
system("clear");
if( res == 0 ) printf("\n移動できない方向が指定されました.\n");
printf("%s", BOLD);
for( j=0; j<20; j++ ) {
for( i=0; i<20; i++ ) {
flag_e = 0;
for( k=0; k<ENEMYS; k++ ) {
if( j == enemys[k].y && i == enemys[k].x
&& player.y-VISIBLE_AREA <= j && j <= player.y+VISIBLE_AREA // 敵が可視領域にいるかどうかのチェック
&& player.x-VISIBLE_AREA <= i && i <= player.x+VISIBLE_AREA ) { // 敵が可視領域にいるかどうかのチェック
flag_e = 1;
break;
}
}
if( j == player.y && i == player.x ) { // プレーヤを黄色で表示する
printf("%s", YELLOW);
printf("P");
printf("%s", WHITE);
} else if( flag_e == 1 ) { // 敵を赤色で表示する
printf("%s", RED);
printf("E");
printf("%s", WHITE);
} else if (field[j][i] == 'G' ) { // ゴールを緑色で表示する
printf("%s", GREEN);
printf("%c", field[j][i]);
printf("%s", WHITE);
} else if( field[j][i] != ' ' ) { // 壁の背景色を灰色にする
printf("%s", BACKGROUNDGRAY);
printf("%c", field[j][i]);
printf("%s", BACKGROUNDBLACK);
} else {
printf("%c", field[j][i]);
}
}
printf("\n");
}
printf("%s", DEFAULT);
}
int main(void) {
int num, i, res, end = 0;
CHARACTER player = {1, 1}; // プレーヤーの位置(x座標,y座標)を保存する変数 ( 初期位置はx:1, y:1 )
CHARACTER enemys[ENEMYS]; // 敵の位置(x座標,y座標)を保存する配列
CHARACTER goal; // ゴールの位置(x座標,y座標)を保存する変数
// 乱数の初期化 ( 毎回異なる乱数を発生するために必要 )
srand(time(NULL));
// 敵の位置をランダムに決定する
for( i=0; i<ENEMYS; i++ ) {
do{
enemys[i].x = 1 + rand() % 19; // 1〜18までの乱数を発生させる ( 0と19は壁)
enemys[i].y = 1 + rand() % 19; // 1〜18までの乱数を発生させる ( 0と19は壁 )
}while( field[enemys[i].y][enemys[i].x] == '|' || field[enemys[i].y][enemys[i].x] == '-' || field[enemys[i].y][enemys[i].y] == '+' );
}
// ゴールの位置をランダムに決定する
do{
goal.x = 10 + rand() % 9; // 10〜18までの乱数を発生させる ( 19は壁)
goal.y = 10 + rand() % 9; // 10〜18までの乱数を発生させる ( 19は壁)
}while( field[goal.y][goal.x] == '|' || field[goal.y][goal.x] == '-' || field[goal.y][goal.x] == '+' );
field[goal.y][goal.x] = 'G';
// 初期状態を表示
ShowField(player, enemys, 1);
// ゴールに到達するか敵と接触するまで繰り返す
do{
printf("移動する方向の数字を入力してください. (下:2, 左:4, 右:6, 上: 8)\n");
scanf("%d", &num);
// プレーヤを指定された方向へ移動させる
res = Move(num, &player);
// 敵をランダムに移動させ,敵に見つかったかどうかを調べる
end = Enemy(player, enemys);
// 敵に見つかった場合 → ゲーム終了
if( end == 1 ) return 1;
ShowField(player, enemys, res);
}while( player.x != goal.x || player.y != goal.y );
printf("ゴールしました!! おめでとう!!\n");
return 0;
}
[/code]