簡単なゲームを作っています。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ルイ

簡単なゲームを作っています。

#1

投稿記事 by ルイ » 2年前

現在、学校で以下のような課題が出ています。

課題3 関数3
未完成の プログラム shooting-kadai3.c を元に、敵が複数になる shooting プログラム を完成させよ。

//*** 要修正 もしくは //*** 要追加 の部分を修正すればよい。
ただし以下の条件を満たすこと。

(1)敵の数は #define された ENEMY_NUM で 簡単に変えられる
(2)関数 int isReplay() 内で static な整数 over10points を追加し、得点が10点以上になったプレイ回数を数えて表示する

それ以外に、ゲームを面白くする要素を追加するのは構わない。

未完成のプログラムshooting-kadai3.c です。

コード:

//////////////////////////////////////////////////////////////////////
//
// シューティングゲームのプログラム shooting.c
//
//  ●がキーボードに合わせて上下左右に移動
//  						
//////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h> // system()
#include <windows.h> // Sleep()
#include <conio.h> // kbhit()

#define SIZE 10 // ステージの大きさ
#define WAIT_TIME 100//画面表示のスピードを決める
#define ENEMY_NUM 10

// グローバル変数
int cx, cy;//自機 ●(circle)の場所 
int ex[ENEMY_NUM], ey[ENEMY_NUM];//敵 ▲(enemy)の場所
int point = 0;//得点

			  // 各種初期化
void init()
{
	int i;
	point = 0;
	cx = 0;
	cy = 0;
	for (i = 0; i < ENEMY_NUM; i++)
	{
		ex[i] = rand() % SIZE;
		ey[i] = rand() % SIZE;
	}
}

// ワープの計算
int getWarpPos(int pos)
{
	int w;
	w = (pos + SIZE) % SIZE;
	return w;
}

// 自機の移動
// キーボードに合わせて移動
// 4なら左、6なら右、2なら下、8なら上
void moveRocket()
{
	int key;
	// キーが押されていたら、キーコードを取得する
	if (!kbhit()) // キーが入力されていれば真
		return;
	key = getch();//一文字入力、エコーバックなし
	switch (key)
	{
	case '4':
		cx--;
		break;
	case '6':
		cx++;
		break;
	case '8':
		cy--;
		break;
	case '2':
		cy++;
		break;
	}
	cx = getWarpPos(cx); //ワープ
	cy = getWarpPos(cy);
}

// 敵機の移動
// 引数を i にし、配列ex、eyのi番目の値を更新させる
//*** 要修正
void moveEnemy()
{
	int	r = rand() % 4;
	switch (r)
	{
	case 0:
		ex--;
		break;
	case 1:
		ex++;
		break;
	case 2:
		ey--;
		break;
	case 3:
		ey++;
		break;
	}
	ex = getWarpPos(ex); //ワープ
	ey = getWarpPos(ey);
}

// 座標(x,y)に敵がいるかチェック
// 敵がいたら 1 を返す いなければ 0 を返す
int isOnEnemy(int x, int y)
{
	int i;
	//*** 要追加 授業を良く聞くこと
	for (i = 0; i < ENEMY_NUM; i++)
	{
		if (x == ex[i] && y == ey[i])
			return 1;
	}
	return 0;
}

//表示
void show()
{
	int x, y;
	for (y = 0; y < SIZE; y++)
	{
		for (x = 0; x < SIZE; x++)
		{
			if (x == cx && y == cy)
				printf("●");
			else if (x == ex && y == ey)//*** 要修正 isOnEnemyを使う
				printf("▲");
			else
				printf(" ");
		}
		printf("\n");
	}
	printf("\n");
	printf(" (cx,cy) = (%d, %d)\n", cx, cy);
	//printf(" (ex,ey) = (%d, %d)\n", ex, ey);
}

//時間つぶしと画面更新
void renew(int wait_time)
{
	printf(" point: %d\n", point);
	Sleep(wait_time);// 1秒間(wait_timeミリ秒)何もしない
	system("cls");// 画面消去
}

//衝突時の表示など
void hit()
{
	point++;
	printf("┏ ┳  ┳ ┳ ━┳━ ┓\n");
	printf("┃ ┣━┫  ┃  ┃  ┃\n");
	printf("┗ ┻  ┻ ┻  ┻  ┛\n");
}

//ゲームオーバー
void gameOver()
{
	show();
	printf("┏ ┏━┓┏━┓┏┳┓┳━┓ ┏━┓┳  ┳┳━┓┳━┓ ┓\n");
	printf("┃ ┃  ┓┣━┫┃┃┃┣┫   ┃  ┃┃  ┃┣┫  ┣┳┛ ┃\n");
	printf("┗ ┗━┛┻  ┻┻  ┻┻━┛ ┗━┛┗━┛┻━┛┻┗┛ ┛\n");
}

//*** 要追加
//*** static な整数 over10points を追加
//*** もし point が 10点を超えたら over10points は 1 増える
int isReplay()
{
	char yn[256];
	static int playtimes = 1;//これまで遊んだ回数

	printf("Play: %d times\n", playtimes);
	playtimes++;

	//	printf( "Over 10 Points: %d times\n", over10points);

	printf("replay? [y/n]\n");
	gets(yn);
	if (yn[0] == 'y')
		return 1;
	return 0;
}

int main()
{
	int wait_time = 100;
	int i, j;
	while (1)
	{
		init();
		for (i = 0; i < 50; i++)
		{
			// 自機の移動
			moveRocket();
			for (j = 0; j < ENEMY_NUM; j++)
			{
				moveEnemy();//*** 要修正
			}
			//画面表示
			show();
			//当たり判定
			if (ishit())//*** 要修正 isOnEnemyを使う
				hit();
			renew(wait_time);
		}
		gameOver();
		if (!isReplay())
			return 0;
	}
	return 0;
}
この日の授業を休んでいたため問題の意味があまり分かりません。
友人に聞きましたが、何を言っているのか分かりません。
まず。int isOnEnemy(int x, int y) 関数はどんなコードを書き加えてあげたらいいのでしょうか。

白い変人

Re: 簡単なゲームを作っています。

#2

投稿記事 by 白い変人 » 2年前

てっきり、分からないので作って欲しいという質問だと思ってしまって、私の方で既に完成させてしまいましたが、「int isOnEnemy(int x, int y) 関数はどんなコードを書き加えてあげたらいいのでしょうか。」という質問ですね。

うっかり、ネタバレしてしまい自力で完成させる楽しみを奪うところでした。

isOnEnemyに関しては、無修正で問題無いと私は判断しました。

ex及びeyは敵の座標の配列と思えますが、そうだとしたら、現状のままで当たり判定処理は行われていると判断出来るからです。

>//*** 要追加 授業を良く聞くこと

と記してある通り、授業で何か追加するべき仕様を先生から話されたのではないでしょうか?

それを実装すれば宜しいのではないかと思います。

私はそのような授業は知りませんので、回答は致しかねます。

ルイ

Re: 簡単なゲームを作っています。

#3

投稿記事 by ルイ » 2年前

void moveEnemy 関数 はどう修正すればいいですか?

白い変人

Re: 簡単なゲームを作っています。

#4

投稿記事 by 白い変人 » 2年前

>#define ENEMY_NUM 10

>ex[ENEMY_NUM], ey[ENEMY_NUM]

と定義してある通り、敵は現状では10体設定されていますが、

コード:

void moveEnemy()
{
    int r = rand() % 4;
    switch (r)
    {
    case 0:
        ex--;
        break;
    case 1:
        ex++;
        break;
    case 2:
        ey--;
        break;
    case 3:
        ey++;
        break;
    }
    ex = getWarpPos(ex); //ワープ
    ey = getWarpPos(ey);
}


とある通り、現状のmoveEnemy()関数は、ex,eyという変数の操作をする仕様にしかなっていません。

ですから、繰り返し処理を用いて、ex[0~ENEMY_NUM],ey[0~ENEMY_NUM]の座標を全て変更出来るように、修正すれば良いと思います。

ルイ

Re: 簡単なゲームを作っています。

#5

投稿記事 by ルイ » 2年前

コード:

void moveEnemy()
{
	for (int i = 0;  i < ENEMY_NUM; i++)
	{
		int	r = rand() % 4;
		switch (r)
		{
		case 0:
			ex[i]--;
			break;
		case 1:
			ex[i]++;
			break;
		case 2:
			ey[i]--;
			break;
		case 3:
			ey[i]++;
			break;
		}
		ex[i] = getWarpPos(ex[i]); //ワープ
		ey[i]= getWarpPos(ey[i]);
	}
}
とりあえずこの関数を修正してみましたがこれでいいですか?

白い変人

Re: 簡単なゲームを作っています。

#6

投稿記事 by 白い変人 » 2年前

質問者様のコンパイラ上で、それで動作したのなら、それで良いと思いますよ。

ただ、コンパイラに依っては、「int i」と「int r」をスコープの外に出した方が無難な場合もある事も認識しておいた方が宜しいかとは思います。

因みに、その場合は以下の様に修正すれば良い事になります。(質問者様が間違っているという意味ではなく、教育の観点からの例の提示と思って下さい。)

コード:

 
void moveEnemy()
{
    int i,r;

    for (i = 0;  i < ENEMY_NUM; i++)
    {
        r = rand() % 4;
        switch (r)
        {
        case 0:
            ex[i]--;
            break;
        case 1:
            ex[i]++;
            break;
        case 2:
            ey[i]--;
            break;
        case 3:
            ey[i]++;
            break;
        }
        ex[i] = getWarpPos(ex[i]); //ワープ
        ey[i]= getWarpPos(ey[i]);
    }
}

ルイ

Re: 簡単なゲームを作っています。

#7

投稿記事 by ルイ » 2年前

すみません、いくら粘っても自分で完成させることができません。
ほかの関数はどう修正したらいいですか?

白い変人

Re: 簡単なゲームを作っています。

#8

投稿記事 by 白い変人 » 2年前

show() ← printfでは現状ではex,eyの値を参照しているが、ex,eyは10要素の配列のアドレスになっているのでNG。
isReplay() ←「static int over10points=0;」を宣言し、10 pointを超えてゲームオーバーを迎えた際にはover10pointsに1加算する。

上記2点は修正しましたか?

アバター
へにっくす
記事: 628
登録日時: 7年前
住所: 東京都

Re: 簡単なゲームを作っています。

#9

投稿記事 by へにっくす » 2年前

白い変人 さんが書きました:質問者様のコンパイラ上で、それで動作したのなら、それで良いと思いますよ。
No.1のコードのmoveEnemy関数のコメントをよく見てください。
このままでは先生から突っ込まれると思いますよ。
written by へにっくす

白い変人

Re: 簡単なゲームを作っています。

#10

投稿記事 by 白い変人 » 2年前

ああ、確かに、その様に書いてありますね。

それなら、寧ろ良い機会なので、質問者様は私がとりあえず動作するように完成させたコードを、仕様に合致するように修正してみると良いと思います。

もちろん、私がとりあえず動作するように憶測も含めて仕上げたものなので、これが正解だという保証はありません。

コード:

//////////////////////////////////////////////////////////////////////
//
// シューティングゲームのプログラム shooting.c
//
// ●がキーボードに合わせて上下左右に移動
//
//////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <stdlib.h>	// system()
#include <windows.h>	// Sleep()
#include <conio.h>	// kbhit()

#define SIZE 10 // ステージの大きさ
#define WAIT_TIME 100	//画面表示のスピードを決める
#define ENEMY_NUM 10

//グローバル変数
int cx,cy;	//自機 ●(circle)の場所 
int ex[ENEMY_NUM],ey[ENEMY_NUM];	//敵 ▲(enemy)の場所
int point=0;	//得点

//各種初期化
void init(){
	int i;
	point=0;
	cx=0;
	cy=0;
	
	for(i=0;i<ENEMY_NUM;i++){
		ex[i]=rand()%SIZE;
		ey[i]=rand()%SIZE;
	}
}
 
//ワープの計算
int getWarpPos(int pos){
	int w;
	
	w=(pos+SIZE)%SIZE;
	
	return w;
}
 
//自機の移動
//キーボードに合わせて移動
//4なら左、6なら右、2なら下、8なら上
void moveRocket(){
	int key;
	
	//キーが押されていたら、キーコードを取得する
	if(!kbhit()) return;	//キーが入力されていれば真
	
	key=getch();	//一文字入力、エコーバックなし
	
	switch (key){
		case '4':
			cx--;
			break;
		case '6':
			cx++;
			break;
		case '8':
			cy--;
			break;
		case '2':
			cy++;
			break;
		default:
			break;
	}
	
	cx=getWarpPos(cx);	//ワープ
	cy=getWarpPos(cy);
}

//敵機の移動
//引数を i にし、配列ex、eyのi番目の値を更新させる
//*** 要修正
void moveEnemy(void){
	int i;
	int r;
	
	for(i=0;i<ENEMY_NUM;i++){
		r=rand()%4;
		
		switch(r){
			case 0:
				ex[i]--;
				break;
			case 1:
				ex[i]++;
				break;
			case 2:
				ey[i]--;
				break;
			case 3:
				ey[i]++;
				break;
			default:
				break;
		}
		
		ex[i]=getWarpPos(ex[i]);//ワープ
		ey[i]=getWarpPos(ey[i]);
	}
}

//座標(x,y)に敵がいるかチェック
//敵がいたら 1 を返す いなければ 0 を返す
int isOnEnemy(int x,int y){
	int i;
	
	for(i=0;i<ENEMY_NUM;i++) if(x==ex[i] && y==ey[i]) return 1;	//*** 要追加 授業を良く聞くこと
	
	return 0;
}
 
//表示
void show(){
	int x,y;
	
	for(y=0;y<SIZE;y++){
		for(x=0;x<SIZE;x++){
			if(x==cx && y==cy) printf("●");
			else if(isOnEnemy(x,y)) printf("▲"); //*** 要修正  isOnEnemyを使う
			else printf("  ");
		}
		printf("\n");
	}
	
	printf("\n");
	//printf(" (cx,cy)=(%d,%d)\n",cx,cy);
	//printf(" (ex,ey)=(%d,%d)\n",ex,ey);
}
 
//時間つぶしと画面更新
void renew(int wait_time){
	printf(" point: %d\n",point);
	Sleep(wait_time);	//1秒間(wait_timeミリ秒)何もしない
	system("cls");	//画面消去
}
 
//衝突時の表示など
void hit(){
	point++;
	printf("┏ ┳  ┳  ┳  ━┳━  ┓\n");
	printf("┃ ┣━┫  ┃    ┃    ┃\n");
	printf("┗ ┻  ┻  ┻    ┻    ┛\n");
}
 
//ゲームオーバー
void gameOver(){
	show();
	printf("┏ ┏━┓┏━┓┏┳┓┳━┓ ┏━┓┳  ┳┳━┓┳━┓ ┓\n");
	printf("┃ ┃  ┓┣━┫┃┃┃┣┫   ┃  ┃┃  ┃┣┫  ┣┳┛ ┃\n");
	printf("┗ ┗━┛┻  ┻┻  ┻┻━┛ ┗━┛┗━┛┻━┛┻┗┛ ┛\n");
}
 
//*** 要追加
//*** static な整数 over10points を追加
//*** もし point が 10点を超えたら over10points は 1 増える
int isReplay(){
	char yn[256];
	
	static int playtimes=1;//これまで遊んだ回数
	static int over10points=0;
	
	printf("Play: %d times\n",playtimes);
	playtimes++;
	
	if(point>10) over10points++;
	printf("Over 10 Points: %d times\n",over10points);
	
	printf("replay? [y/n]\n");
	gets(yn);
	
	if(yn[0]=='y') return 1;
	
	return 0;
}
 
int main(){
	int wait_time=100;
	int i,j;
	
	while(1){
		init();
		
		for(i=0;i<50;i++){
			
			moveRocket();	//自機の移動
			
			moveEnemy();	//*** 要修正
			
			show();	//画面表示
			
			//当たり判定
			if(isOnEnemy(cx,cy)) hit();	//*** 要修正  isOnEnemyを使う
			
			renew(wait_time);
		}
		
		gameOver();
		
		if(!isReplay()) return 0;
	}
	
	return 0;
}

返信

“C言語何でも質問掲示板” へ戻る