【雑談?】自分の書いたコードを見て下さい

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Rittai_3D
記事: 525
登録日時: 7年前

【雑談?】自分の書いたコードを見て下さい

#1

投稿記事 by Rittai_3D » 7年前

こんにちは。前回のトピック( http://dixq.net/forum/viewtopic.php?f=3&t=13466 )でアドバイスを下さった皆様、本当にありがとうございます。

前回の反省を踏まえて作り直してきました。

コード:

#define _CRT_SECURE_NO_WARNINGS 1
#include "DxLib.h"
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "main.h"

static int Key[ 256 ];

static music_t music[ MUSIC_NUM ];

int gpUpdateKey()
{
	char tmpKey[ 256 ]; // 現在のキーの入力状態を格納する

	GetHitKeyStateAll( tmpKey ); // 全てのキーの入力状態を得る

	for( int i=0; i<256; i++ ){
		if( tmpKey[i] != 0 ){	// i番のキーコードに対応するキーが押されていたら
			Key[i]++;			// 加算
		} else {				// 押されていなければ
			Key[i] = 0;			// 0にする
		}
	}
	return 0;
}

int ProcessLoop() // 毎ループ必要な事
{
	if( ProcessMessage()  != 0 ) return 1;
	if( ClearDrawScreen() != 0 ) return 1;
	if( gpUpdateKey()     != 0 ) return 1;

	return 0;
}

void Music_Draw::Init()
{
	m_Font[0] = CreateFontToHandle( "MSPゴシック", 16, 16, DX_FONTTYPE_ANTIALIASING_EDGE_8X8, -1, 1, 0, -1 ); // フォント1
	m_Font[1] = CreateFontToHandle( "MSPゴシック", 14, 10, DX_FONTTYPE_ANTIALIASING_EDGE_8X8, -1, 1, 0, -1 ); // フォント2

	m_SelectNum = 0;
	m_SelectedMusicNo = 0;
}

void Music_Draw::Load()
{
	m_img_back[0] = LoadGraph( "dat/img/title03a.png" ); // 背景画像を読み込む
	m_img_back[1] = LoadGraph( "dat/img/title03b.png" ); // 背景画像を読み込む
}

void Music_Draw::Load_Script()
{
	char FileName[] = "dat/bgm/musiccmt.txt"; // ファイルの名前
	int i,num=0,n=0,line=0; // n曲目の判断やfor文関係 
	int  input[128];		// 一文字読み込むのに必要
	char inputc[128];	// 上に同じ

	FILE* fp = fopen( FileName , "r" ); // ファイルを開く

	if( fp == NULL ){ // ファイルが無い時の処理
		MSG( "No Script File !" );
		exit(1);
	}

	for(i=0 ; i<4 ; i++ ) // 最初の4行はコメントなので読み飛ばす
		while( fgetc( fp ) != '\n' );

	while( 1 ){
		for(i=0 ; i<128 ; i++ ){ // 横64文字まで読み込んで
			input[i] = inputc[i] = fgetc( fp );

			if( input[i] == '#' ){ // コメント記号ならば
				while( fgetc( fp ) != '\n' ); // その行の終わりまでループして
				i = -1; // カウンタを戻して
				continue;
			}

			if( input[i] == '\n' ){	// 改行記号なら(独自フォーマットのファイルだから改行で区切る)
				inputc[i] = '\0';	// そこまでを文字列にして
				break;
			}

			if( input[i] == EOF ){	// EOFなら(ここは、charで判断はしないほうが良い)
				goto EXFILE;		// ファイルクローズタグにジャンプ( でいいのかな? )
			}
		}

		switch( num ){ // 読み込んだファイルから構造体にコピーする
			case 0: strcpy( music[n].path   , inputc ); break; // 音楽再生の為のパス
			case 1: strcpy( music[n].name[0], inputc ); break; // 名前1 : No.~
			case 2: strcpy( music[n].name[1], inputc ); break; // 名前2 : ♪~
				// -----------------以下、コメント読み込み----------------- //
			case 3: strcpy( music[n].comme[ line ]    , inputc );break;
			case 4: strcpy( music[n].comme[ line + 1 ], inputc );break;
			case 5: strcpy( music[n].comme[ line + 2 ], inputc );break;
			case 6: strcpy( music[n].comme[ line + 3 ], inputc );break;
			case 7: strcpy( music[n].comme[ line + 4 ], inputc );break;
			case 8: strcpy( music[n].comme[ line + 5 ], inputc );break;
			case 9: strcpy( music[n].comme[ line + 6 ], inputc );break;
				// -------------------------------------------------------- //
		}

		num++; // num加算

		if( num == 10 ){ // numの値が9(1曲分のファイル読み込みが終わったら)なら
			num = 0;	// numを加算
			n++;		// nも加算
		}
	}
EXFILE: // ファイルクローズ
	fclose( fp );
}

void Music_Draw::Load_LoopFile()
{
	char FileName[] = "dat/bgm/loop.txt"; // ファイル名( path )
	int  input[32];  // 一文字読み込み
	char inputc[32]; // 一文字読み込み
	int i,n=0;

	FILE* fp = fopen( FileName, "r" ); // ファイルをリード形式で展開

	if( fp == NULL ){ // ファイルが無い時の処理
		MSG( "No Loop File !" );
		exit(1);
	}

	for(i=0 ; i<4 ; i++ ) // 最初の4行はコメントなので飛ばす
		while( fgetc( fp ) != '\n' );

	while( 1 ){
		for(i=0 ; i<32 ; i++ ){
			input[i] = inputc[i] = fgetc( fp );

			if( input[i] == '#' ){ // コメント記号なら
				while( fgetc( fp ) != '\n' ); // 改行までループして
				i = -1; // カウンタを戻して
				continue;
			}

			if( input[i] == ';' ){ // 終了記号なら
				inputc[i] = '\0';  // そこまでを文字列として
				break;
			}

			if( input[i] == EOF ){ // ファイルの終わりなら
				goto EXFILE;
			}
		}
		music[n].loop = atoi( inputc ); // 読みとったループ位置を構造体のloopに代入
		n++; // 曲加算
	}

EXFILE:
	fclose( fp );
}

void Music_Draw::DrawBack()
{
	DrawGraph(   0, 0, m_img_back[0], TRUE);	// 画像を描写
	DrawGraph( 512, 0, m_img_back[1], TRUE);	// 同上
}

void Music_Draw::DrawComment()
{
	int i;
	for(i=0 ; i<7 ; i++ ){// コメントの行数
		DrawFormatStringToHandle( 80, 340+16*i, GetColor(240,210,210), m_Font[1], "%s", music[ m_SelectedMusicNo ].comme[ i ] );
	}
}

void Music_Draw::DrawName()
{
	int i,j;

	for(i=0 , j=0 ; i<MUSIC_NUM ; j++ , i++ ){	// No.~の部分
		if( i == m_SelectNum )		// もし選択中なら
			DrawFormatStringToHandle( 60, 130+18*j, GetColor(240,210,210), m_Font[0], "%s", music[i].name[0] );
		else	// そうで無ければ
			DrawFormatStringToHandle( 65, 130+18*j, GetColor(130,105,105), m_Font[0], "%s", music[i].name[0] );
	}

	for(i=0 ; i<MUSIC_NUM ; i++ ){	// 曲名を表示
		DrawFormatStringToHandle( 60, 320, GetColor(240,210,210), m_Font[1], "%s", music[ m_SelectedMusicNo ].name[1] );
	}

}

void Music_Draw::Fin()
{
	InitGraph();
	InitFontToHandle();
}

void Music_SE::Load()
{
	m_se_select  = LoadSoundMem( "dat/se/se_select00.wav" );	// seを読み込む
}

void Music_SE::Fin()
{
	InitSoundMem(); // 音声ハンドルを消す
}

void Music_SE::PlaySE()
{
	if( CheckSoundMem( m_se_select ) == 0 ){
		PlaySoundMem( m_se_select, DX_PLAYTYPE_BACK );
	}
}

void Music_BGM::Load_BGM()
{
	int i;

	for(i=0 ; i<MUSIC_NUM ; i++ ){
		m_BGM[i] = LoadBGM( music[i].path ); // BGMを流し込む

		if( m_BGM[i] == NULL ){
			MSG( "Waveファイルがないぞぅ" ) ;
			exit(1);
		}
	}

	SetLoopTimePosSoundMem( music[ 0 ].loop, m_BGM[ 0 ] );	// 0番目の曲( =タイトル曲 )曲のループ位置
	PlaySoundMem( m_BGM[ 0 ], DX_PLAYTYPE_BACK );			// 0番目の曲( =タイトル曲 )を再生
}

void Music_BGM::PlayBGMFile( int SelectNum )
{
	int i;

	for(i=0 ; i<MUSIC_NUM+1 ; i++ ){
		if( CheckSoundMem( m_BGM[i] ) == 1 ){	// 再生中なら
			StopSoundMem(  m_BGM[i] );			// サウンドファイルを停止する
		} else {
			SetLoopTimePosSoundMem( music[ SelectNum ].loop, m_BGM[ SelectNum ] );	// 選択された曲のループ位置
			PlaySoundMem( m_BGM[ SelectNum ], DX_PLAYTYPE_BACK );					// 音楽を再生
		}
	}
}

void Music_Main::Init()
{
	m_Draw.Init(); // フォントの初期化
}
void Music_Main::Load()
{
	//---------画像読み込み------------//
	m_Draw.Load();
	m_Draw.Load_LoopFile();
	m_Draw.Load_Script();
	//----------SE読み込み----------//
	m_SE.Load();
	//----------BGM読み込み--------//
	m_Bgm.Load_BGM();

}

void Music_Main::Draw()
{
	m_Draw.DrawBack()		; // 背景描写
	m_Draw.DrawComment()	; // コメント描写
	m_Draw.DrawName()		; // 名前描写
}

void Music_Main::Update()
{
	if( Key[ KEY_INPUT_DOWN ] == 1 || ( Key[ KEY_INPUT_DOWN ] % 5 == 0 && Key[ KEY_INPUT_DOWN ] > 30 ) ){ // ↓キーが押されたら
		m_Draw.m_SelectNum = ( m_Draw.m_SelectNum + 1 ) % MUSIC_NUM;
	}

	if( Key[ KEY_INPUT_UP ] == 1  || ( Key[ KEY_INPUT_UP ] % 5== 0 && Key[ KEY_INPUT_UP ]> 30 ) ){ // ↑キーが押されたら
		m_Draw.m_SelectNum = ( m_Draw.m_SelectNum + ( MUSIC_NUM - 1 ) ) % MUSIC_NUM;
	}

	if( Key[ KEY_INPUT_DOWN ] == 1 || Key[ KEY_INPUT_UP ] == 1 || ( Key[ KEY_INPUT_DOWN ] % 5 == 0 && Key[ KEY_INPUT_DOWN ] > 30 )||
		( Key[ KEY_INPUT_UP ] % 5 == 0 && Key[ KEY_INPUT_UP ] > 30 ) ){ // 上下どちらかのキーが押されたら

			m_SE.PlaySE(); // 選択音を再生
	}

	if( Key[ KEY_INPUT_Z ] == 1 || Key[ KEY_INPUT_RETURN ] == 1 ){ // Z Key と Enter Key が押されたら
		m_Draw.m_SelectedMusicNo = m_Draw.m_SelectNum; // 選択された項目を更新する

		m_Bgm.PlayBGMFile( m_Draw.m_SelectedMusicNo ); // 選択されたBGMを再生

	}

}

void Music_Main::Fin()
{
	m_Draw.Fin()	; // 全ての画像とフォントハンドルを削除
	m_SE.Fin()		; // メモリに読み込んだ音声ハンドルを削除
}

int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int)
{
	ChangeWindowMode( TRUE ), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK );

	Music_Main Music; // インスタンス化

	Music.Init();
	Music.Load();

	while( !ProcessLoop() ){

		Music.Update();

		Music.Draw();

		ScreenFlip();
	}

	Music.Fin();

	DxLib_End();
	return 0;
}

コード:

#pragma once

#define MUSIC_NUM 6
#define MSG(message) {MessageBox( NULL, _T( message ), _T( "Message" ), MB_OK );} // エラーメッセージ

#include "DxLib.h"

typedef struct{ // 曲の構造体
	int  loop				; // 曲のループ位置
	char path[ 256 ]		; // 曲のコメント(パス)
	char name[2][ 256 ]		; // [0] = (名前1),[1] = (名前2)
	char comme[7][ 256 ]	; // (コメント)
} music_t;


class Music_Draw // 描写クラス
{
private:

	int m_Font[2]			; // フォントを設定する
	int m_img_back[2]		; // 背景画像を読み込む


public:

	int m_SelectNum			; // 現在選択中 この変数はclass Music_BGMでも使う
	int m_SelectedMusicNo	; // コメントを表示する曲の番号を保持

	void Init()				; // フォントとかの初期化
	void Load()				; // 画像とかの読み込み
	void Load_Script()		; // スクリプトファイルを読み込む
	void Load_LoopFile()	; // ループファイルを読み込む

	void DrawComment()		; // コメント描写関数
	void DrawName()			; // 曲名[0]と[1]描写関数
	void DrawBack()			; // 背景描写

	void Fin()				; // 終了処理

};

class Music_SE // SEクラス
{
private:

	int m_se_select	; // seを読み込む

public:

	void Load()		; // seの読み込み
	void Fin()		; // 終了処理。たぶん,InitSoundMem()呼び出すからBGMも一緒に削除されると思われ

	void PlaySE()	; // seを再生する
};

class Music_BGM // BGMクラス
{
private:

	int m_BGM[ MUSIC_NUM ];	// BGMをメモリに読み込む為の変数

public:

	void Load_BGM();		// BGMをメモリに読み込む為の関数
	void PlayBGMFile( int SelectNum ); // 選択中( エンターキー or Zキーが押された時 )のBGMを再生

};

class Music_Main // 総括クラス
{
private:

	Music_Draw m_Draw	; // インスタンス化( ここでインスタンス化していいのか? )
	Music_SE   m_SE		; // 同上
	Music_BGM  m_Bgm	; // 同上

public:

	void Init();
	void Load();
	void Update();
	void Draw();
	void Fin();
};

また、コードをきれいに書くコツなども教えて下されば幸いです。

#追記 URLの貼り忘れていました
初心者です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 【雑談?】自分の書いたコードを見て下さい

#2

投稿記事 by softya(ソフト屋) » 7年前

とりあえず気になったこと。
・コンストラクタ/デストラクタが活用されていない。
・Loadが色々分かれているのが変。実は別のクラスにすべきものを1つのクラスにまとめているんじゃないかと言う疑惑。
・public公開しなくて良い関数が公開されています。
・メンバ変数はpublic公開しないほうが良いです。全面的な外部操作を許す場合は、設計に問題が有るといって良いと思います。
 公開が必要となる場合、クラスが管理すべきものをクラスが管理していない事になります。
 m_Draw.m_SelectNum = ( m_Draw.m_SelectNum + 1 ) % MUSIC_NUM;
 とかは、外部操作すべきじゃないです。
・Music_DrawとMusic_Mainの権限というかオブジェクトの定義が曖昧だと思います。
 Music_Drawってスクリプトというか定義ファイルの管理クラスじゃないかと思うんですが、それならばそういう名前でそういう機能に限定すべきです。
 少なくとも名前から機能が類推できないのはマズイです。
・コードの発展性というか、曲の数やら画像やらが変わった時の考慮が足りていないのが気になります。
 ただ動けば良いというものでもないと思うので、C++化した時の付加価値を付けましょう。
・あちこちにあるC言語的なものは、勉強して徐々になくしていくってください。
 配列サイズが決め打ちとかstrcpy()やらfgetc()やら。あとエラー処理でexit()で抜けずにthrowでtry~catchしてくださいね。

質問な所に対する回答。
・インスタンスは、そこで良いと思います。ただ、コントラクタを使う場合はDxLIB系の関数は使えないので注意してください。
・gotoを使わず、うまくreturnを使ってほしい。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Rittai_3D
記事: 525
登録日時: 7年前

Re: 【雑談?】自分の書いたコードを見て下さい

#3

投稿記事 by Rittai_3D » 7年前

>>softya様

返信ありがとうございます。
softya(ソフト屋) さんが書きました:とりあえず気になったこと。
・コンストラクタ/デストラクタが活用されていない。
・Loadが色々分かれているのが変。実は別のクラスにすべきものを1つのクラスにまとめているんじゃないかと言う疑惑。
・public公開しなくて良い関数が公開されています。
・メンバ変数はpublic公開しないほうが良いです。全面的な外部操作を許す場合は、設計に問題が有るといって良いと思います。
 公開が必要となる場合、クラスが管理すべきものをクラスが管理していない事になります。
 m_Draw.m_SelectNum = ( m_Draw.m_SelectNum + 1 ) % MUSIC_NUM;
 とかは、外部操作すべきじゃないです。
・Music_DrawとMusic_Mainの権限というかオブジェクトの定義が曖昧だと思います。
 Music_Drawってスクリプトというか定義ファイルの管理クラスじゃないかと思うんですが、それならばそういう名前でそういう機能に限定すべきです。
 少なくとも名前から機能が類推できないのはマズイです。
・コードの発展性というか、曲の数やら画像やらが変わった時の考慮が足りていないのが気になります。
 ただ動けば良いというものでもないと思うので、C++化した時の付加価値を付けましょう。
・あちこちにあるC言語的なものは、勉強して徐々になくしていくってください。
 配列サイズが決め打ちとかstrcpy()やらfgetc()やら。あとエラー処理でexit()で抜けずにthrowでtry~catchしてくださいね。

質問な所に対する回答。
・インスタンスは、そこで良いと思います。ただ、コントラクタを使う場合はDxLIB系の関数は使えないので注意してください。
・gotoを使わず、うまくreturnを使ってほしい。
アドバイスありがとうございます。

コンストラクタ、デストラクタを活用するように書き直します。
C言語の癖がなかなか抜けないので、ちょっと困っています。

LoadはLoadクラスに分けた方がいいですか?まだ、クラス分けのコツ(?)がわかりませんので…。
曲の数やら画像が変わった時の考慮が足りないとは具体的にどのようなことでしょうか?
初心者です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 【雑談?】自分の書いたコードを見て下さい

#4

投稿記事 by softya(ソフト屋) » 7年前

>C言語の癖がなかなか抜けないので、ちょっと困っています。

どちらかと言うと、リファクタリングやライブラリ化を考慮したC言語を使い方をしていなかったんだと思います。
とりあえず動けば良いという書き方が癖になっていると言ったほうが良いかもしれません。

> LoadはLoadクラスに分けた方がいいですか?まだ、クラス分けのコツ(?)がわかりませんので…。

オブジェクト指向は、機能で分けるでのはなくオブジェクトで分けます。
つまり、管理する物の単位でクラスを分けます。
SEクラスがSEのロードから演奏まで受け持つように、スクリプトもロードからスクリプトに関する処理だけを受け持たなくてはいけません。
オブジェクトに関係ないことはしないし、オブジェクトが保持する値の操作を自分でせずに他に明け渡すのは良くない事なのです。

> 曲の数やら画像が変わった時の考慮が足りないとは具体的にどのようなことでしょうか?

曲の数やら画像などが末端のクラスに決め打ちで書かれていますよね。
それを決めるのはmainとか外部ファイルにしないと、汎用性のあるコードの書き方に近づかないのでC++の勉強に成らないのでは?って事です。
クラスの使い回しが困難な書き方をしているのは勉強として不十分だと思ったわけです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Rittai_3D
記事: 525
登録日時: 7年前

Re: 【雑談?】自分の書いたコードを見て下さい

#5

投稿記事 by Rittai_3D » 7年前

>>softya様

返信ありがとうございます。
softya(ソフト屋) さんが書きました:>C言語の癖がなかなか抜けないので、ちょっと困っています。

どちらかと言うと、リファクタリングやライブラリ化を考慮したC言語を使い方をしていなかったんだと思います。
とりあえず動けば良いという書き方が癖になっていると言ったほうが良いかもしれません。
おっしゃる通りです。正直、動けば何とかなると思っていました。
softya(ソフト屋) さんが書きました:> LoadはLoadクラスに分けた方がいいですか?まだ、クラス分けのコツ(?)がわかりませんので…。
オブジェクト指向は、機能で分けるでのはなくオブジェクトで分けます。
つまり、管理する物の単位でクラスを分けます。
SEクラスがSEのロードから演奏まで受け持つように、スクリプトもロードからスクリプトに関する処理だけを受け持たなくてはいけません。
オブジェクトに関係ないことはしないし、オブジェクトが保持する値の操作を自分でせずに他に明け渡すのは良くない事なのです。
なるほど…勉強になります。今、作り直してしるので、その辺りを考慮して書きたいと思います。
softya(ソフト屋) さんが書きました:> 曲の数やら画像が変わった時の考慮が足りないとは具体的にどのようなことでしょうか?

曲の数やら画像などが末端のクラスに決め打ちで書かれていますよね。
それを決めるのはmainとか外部ファイルにしないと、汎用性のあるコードの書き方に近づかないのでC++の勉強に成らないのでは?って事です。
クラスの使い回しが困難な書き方をしているのは勉強として不十分だと思ったわけです。
ヘッダファイルの最初で#defineするのはダメでしょうか?
初心者です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 【雑談?】自分の書いたコードを見て下さい

#6

投稿記事 by softya(ソフト屋) » 7年前

> ヘッダファイルの最初で#defineするのはダメでしょうか?

少なくともコンストラクタの引数にするとか、状況変化に強い書き方のコードを書く癖を付けたほうが良いと思います。
これまた動けば良いコードの再生産になりかねません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Rittai_3D
記事: 525
登録日時: 7年前

Re: 【雑談?】自分の書いたコードを見て下さい

#7

投稿記事 by Rittai_3D » 7年前

softya(ソフト屋) さんが書きました:> ヘッダファイルの最初で#defineするのはダメでしょうか?

少なくともコンストラクタの引数にするとか、状況変化に強い書き方のコードを書く癖を付けたほうが良いと思います。
これまた動けば良いコードの再生産になりかねません。
なるほど、コンストラクタの引数ですか。

いつもvoidにしていたので盲点でした。
初心者です

Rittai_3D
記事: 525
登録日時: 7年前

Re: 【雑談?】自分の書いたコードを見て下さい

#8

投稿記事 by Rittai_3D » 7年前

うーん、catch,throw,tryの便利さがわかりません。

なぜexit()では駄目なのですか?

あと、どうしてもm_SelectNumが外部で必要になったらどうしたらいいでしょうか?
初心者です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 【雑談?】自分の書いたコードを見て下さい

#9

投稿記事 by softya(ソフト屋) » 7年前

3D_3D さんが書きました:うーん、catch,throw,tryの便利さがわかりません。

なぜexit()では駄目なのですか?
maim関数後の処理過程にあるインスタンスのデストラクタが呼び出されないってのが1つで、望まなくてもC++のライブラリを使えばthrowされるのでtry~catchで対策する必要が有るのがもう一つの理由です。
3D_3D さんが書きました: あと、どうしてもm_SelectNumが外部で必要になったらどうしたらいいでしょうか?
私は必要に成らないと思いますが、どうしても必要なら取得関数を用意してください。
そうすれば、変更されないことが保証出来ます。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
usao
記事: 1589
登録日時: 7年前

Re: 【雑談?】自分の書いたコードを見て下さい

#10

投稿記事 by usao » 7年前

●以前も同じようなことを書いた気がしますが
外部変数(正確には何と呼ぶのかな? ファイルスコープな非ローカル変数)
static music_t music[ MUSIC_NUM ];
の存在を前提として各クラスのコードが書かれてしまっています.
 ↓
まず,WinMain()を書くファイルと,Music_XXX系のメソッドの実装を書くファイルを分けましょう.
例えば,現在クラス群の宣言が書かれているヘッダファイルをmusic.hだとすれば
クラスの実装を新しいmusic.cppに書く.
で,「music.hとmusic.cppを別のプログラムに持って行っても再利用できる形」を目標に書いてみるとよいかと思います.

●余計な依存関係を持たせない
避けられない場合を除いて,なるべくヘッダファイルには
#include "DxLib.h"
のような依存関係を記述しない方がよいです.
例えば,↑で書いたようなファイル分けをした場合,music.cppでincludeすれば済すむのであれば,music.hではincludeしない.

Rittai_3D
記事: 525
登録日時: 7年前

Re: 【雑談?】自分の書いたコードを見て下さい

#11

投稿記事 by Rittai_3D » 7年前

>>usao様

返信ありがとうございます。
usao さんが書きました:●以前も同じようなことを書いた気がしますが
外部変数(正確には何と呼ぶのかな? ファイルスコープな非ローカル変数)
static music_t music[ MUSIC_NUM ];
の存在を前提として各クラスのコードが書かれてしまっています.
 ↓
まず,WinMain()を書くファイルと,Music_XXX系のメソッドの実装を書くファイルを分けましょう.
例えば,現在クラス群の宣言が書かれているヘッダファイルをmusic.hだとすれば
クラスの実装を新しいmusic.cppに書く.
で,「music.hとmusic.cppを別のプログラムに持って行っても再利用できる形」を目標に書いてみるとよいかと思います.
わかりました。専用のmusic.cppを追加してそこに書くようにします。

つまり、使い回しても問題ない形にする、ということですね。
usao さんが書きました:●余計な依存関係を持たせない
避けられない場合を除いて,なるべくヘッダファイルには
#include "DxLib.h"
のような依存関係を記述しない方がよいです.
例えば,↑で書いたようなファイル分けをした場合,music.cppでincludeすれば済すむのであれば,music.hではincludeしない.
ヘッダファイルにはなるべくincludeはしないようにします。

ためになるお話ありがとうございます。
初心者です

アバター
usao
記事: 1589
登録日時: 7年前

Re: 【雑談?】自分の書いたコードを見て下さい

#12

投稿記事 by usao » 7年前

>ヘッダファイルにはなるべくincludeはしないようにします。
この話については理由を調べてみてください.
「include 依存関係」とかで検索すれば
「コンパイル依存性がどうので1つ変えただけで全部再コンパイルが必要になって云々」という話が見つかると思います.
オフトピック
別に個人でやってる規模なら全部コンパイルされようが別にいいし…とか感じるかもしれませんけど.
一応,私が経験した弊害(?)として↓のようなのがあります.
●どのcppが何を必要としているのかさっぱりわからない状況になる
以前他人が作ったそれなりに大きいプログラムから本当に必要な部分だけを抜き出す(要らん部分を削る)という作業を行いました.
古い(?)コードのほとんどがもはや使われておらず
ヘッダ内で宣言されているものが実際には全く使われていないのに無駄にincludeされているヘッダが膨大にある状況.
で,どう見てもいらないやつの include を取っ払ってみるたびに…コンパイルエラーが大量に……
要するに,「そのヘッダからさらにincludeされている先からさらにincludeされている…」という形になっていた.
しかもその先でincludeされているものは,別にその先での実装には必要ないとか,もうわけがわからない様相.
「本当に必要な箇所(だけ)でincludeする」ことをしないとどうなるのか ということを思い知らされた.

Rittai_3D
記事: 525
登録日時: 7年前

Re: 【雑談?】自分の書いたコードを見て下さい

#13

投稿記事 by Rittai_3D » 7年前

>>usao様

返信ありがとうございます。
usao さんが書きました:>ヘッダファイルにはなるべくincludeはしないようにします。
この話については理由を調べてみてください.
「include 依存関係」とかで検索すれば
「コンパイル依存性がどうので1つ変えただけで全部再コンパイルが必要になって云々」という話が見つかると思います.
下のURLをみました。面倒なことになる前にわかってよかったです。
(参考: http://jianji.noor.jp/wiki/index.cgi?pa ... 4%BD%A4%A6 )
usao さんが書きました:
オフトピック
別に個人でやってる規模なら全部コンパイルされようが別にいいし…とか感じるかもしれませんけど.
一応,私が経験した弊害(?)として↓のようなのがあります.
●どのcppが何を必要としているのかさっぱりわからない状況になる
以前他人が作ったそれなりに大きいプログラムから本当に必要な部分だけを抜き出す(要らん部分を削る)という作業を行いました.
古い(?)コードのほとんどがもはや使われておらず
ヘッダ内で宣言されているものが実際には全く使われていないのに無駄にincludeされているヘッダが膨大にある状況.
で,どう見てもいらないやつの include を取っ払ってみるたびに…コンパイルエラーが大量に……
要するに,「そのヘッダからさらにincludeされている先からさらにincludeされている…」という形になっていた.
しかもその先でincludeされているものは,別にその先での実装には必要ないとか,もうわけがわからない様相.
「本当に必要な箇所(だけ)でincludeする」ことをしないとどうなるのか ということを思い知らされた.
貴重なお話ありがとうございます。本当に必要な箇所(だけ)でincludeする」を常に考えながらコードを書くようにします。
初心者です

Rittai_3D
記事: 525
登録日時: 7年前

Re: 【雑談?】自分の書いたコードを見て下さい

#14

投稿記事 by Rittai_3D » 7年前

新たな問題が発生しました。

新たにmusic.cppとmusic.hをプロジェクトに追加して、music.hに関数のプロトタイプ宣言、ミュージックルーム構造体、クラスを書いていたのですがちょっと詰まってしまいました。

コード:

typedef struct{
       int loop;
       std::string path,name,comme;
}music_t;
と書いたところ、構文エラーと"型指定子がありません"というエラーがでました。

因みに、include文は一切書いておりません。

このような場合は素直に #include <cstring> を書いた方が良いのでしょうか?
初心者です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 【雑談?】自分の書いたコードを見て下さい

#15

投稿記事 by softya(ソフト屋) » 7年前

厳しく追求して申し訳ないですが、C++でソースコードを書くと言う行為の意義として、こう言う問題を解決して行かないとC++の意味が無いので申し訳ないですね。
さて、music.cppって何を管理するクラスを入れるところでしょうか? スクリプトじゃないかと思うのですが、名前がアヤフヤでなんとでも取れる名前になっているので危険な徴候です。名前とオブジェクトの特性は一致させて下さい。名は体を表すです。

>このような場合は素直に #include <cstring> を書いた方が良いのでしょうか?
書いたほうが良いです。
ちなみに、std::stringはCのライブラリではないので、#include <string>です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Rittai_3D
記事: 525
登録日時: 7年前

Re: 【雑談?】自分の書いたコードを見て下さい

#16

投稿記事 by Rittai_3D » 7年前

softya(ソフト屋) さんが書きました:厳しく追求して申し訳ないですが、C++でソースコードを書くと言う行為の意義として、こう言う問題を解決して行かないとC++の意味が無いので申し訳ないですね。
C++初心者なので厳しくしていただいた方が自分の為になると思いますので、これからも厳しくお願いします。
softya(ソフト屋) さんが書きました:さて、music.cppって何を管理するクラスを入れるところでしょうか? スクリプトじゃないかと思うのですが、名前がアヤフヤでなんとでも取れる名前になっているので危険な徴候です。名前とオブジェクトの特性は一致させて下さい。名は体を表すです。
わかりました。たしかに、music.cppとあるのに、スクリプトクラスがあるのは変ですね。作り直します。
softya(ソフト屋) さんが書きました:>このような場合は素直に #include <cstring> を書いた方が良いのでしょうか?
書いたほうが良いです。
ちなみに、std::stringはCのライブラリではないので、#include <string>です。
了解しました。music.hに#include <string>で追加しておきました。
初心者です

アバター
usao
記事: 1589
登録日時: 7年前

Re: 【雑談?】自分の書いたコードを見て下さい

#17

投稿記事 by usao » 7年前

>music.cpp
この名前については多分私のせいです.
私がてきとー(*)に書いたのをそのまま使ってしまっているのだと思います.
もう少し真っ当な名前を例示すべきでしたね.

で,このhとcppに何を入れるのか?についてですが,とりあえず最初に貼られているコードに対して
最初の段階として
>まず,WinMain()を書くファイルと,Music_XXX系のメソッドの実装を書くファイルを分けましょう.
をやる,という話のままであれば
「ミュージックルーム(?)」という大きなモジュールに必要な諸々(スクリプトのロードはその中の機能の一つ,ですね.)
が収まることになるのかな?と思いますので
例えば,MusicRoom.h/.cpp とかが妥当でしょうか.

最初からもっと細かい単位にわけて書くのであれば,個々のファイル名もそれに合わせて付けることになります.
(スクリプト周りの処理だけを小分けにしたならMusicRoomScript.cpp とか.)
オフトピック
* ”てきとー” : ”適当”と漢字で書くと「適切」という(本来の?)意味に読めてしまうので
          あえて平仮名で.

Rittai_3D
記事: 525
登録日時: 7年前

Re: 【雑談?】自分の書いたコードを見て下さい

#18

投稿記事 by Rittai_3D » 7年前

>>usao様

返信ありがとうございます。
usao さんが書きました:>music.cpp
この名前については多分私のせいです.
私がてきとー(*)に書いたのをそのまま使ってしまっているのだと思います.
もう少し真っ当な名前を例示すべきでしたね.

で,このhとcppに何を入れるのか?についてですが,とりあえず最初に貼られているコードに対して
最初の段階として
>まず,WinMain()を書くファイルと,Music_XXX系のメソッドの実装を書くファイルを分けましょう.
をやる,という話のままであれば
「ミュージックルーム(?)」という大きなモジュールに必要な諸々(スクリプトのロードはその中の機能の一つ,ですね.)
が収まることになるのかな?と思いますので
例えば,MusicRoom.h/.cpp とかが妥当でしょうか.

最初からもっと細かい単位にわけて書くのであれば,個々のファイル名もそれに合わせて付けることになります.
(スクリプト周りの処理だけを小分けにしたならMusicRoomScript.cpp とか.)
オフトピック
* ”てきとー” : ”適当”と漢字で書くと「適切」という(本来の?)意味に読めてしまうので
          あえて平仮名で.
おっしゃる通りにbgm,se,script,drawのように小分けにしました。行数が増えるのは嫌なので。
オフトピック
このトピックとは関係ないですが、softya様にコンストラクタ/デストラクタを活用するように、と言われました。コンストラクタは変数の初期化に使いますが、デストラクタはどのような時に活用するのですか?
初心者です

アバター
usao
記事: 1589
登録日時: 7年前

Re: 【雑談?】自分の書いたコードを見て下さい

#19

投稿記事 by usao » 7年前

デストラクタは そのオブジェクトが解体されるときに呼ばれます.
無くなる前に絶対に何かしないとダメな処理がある場合に使います.

例えば,3D_3Dさんが示されたコードには Fin() というメソッドを持つクラスがあり,
そのクラスオブジェクトを使い終わる際に,何かしら後始末が必要なのだと見受けます.
そういったことをデストラクタに書いておくと(例えばデストラクタの実装に Fin(); と書いておく)
インスタンスが解体される直前に自動でやってもらえて便利です.
 とはいえ,DXライブラリではどうやらDxLib_End()というやつが存在しているっぽいので
 オブジェクトの後始末時にDXライブラリの機能を必要とする場合は注意が必要そうです.
 ↓のようにするといいのかな?

コード:

int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int)
{
    ChangeWindowMode( TRUE );  //※これをDXLib_Init()より先に書くべきなのかどうか,私にはわからないので放置※

    DxLib_Init();
    {//DxLib_Init()とDxLib_End()の間をブロックにした.
        SetDrawScreen( DX_SCREEN_BACK );
        Music_Main Music; // インスタンス化
 
        Music.Init();
        Music.Load();
 
        while( !ProcessLoop() ){
            Music.Update();
            Music.Draw();
            ScreenFlip();
        }

        //Music.Fin();  //もし,デストラクタにFin()のコールが書かれているなら,明示的に呼ばなくて済む
    }  //この時点で,Musicは解体される.デストラクタが動く.
 
    DxLib_End();
    return 0;
}
後処理を自動でやってくれるなら,例えば
ある関数の中からreturnで唐突に抜けるような場合とか楽.

コード:

bool func()
{
  Music_Main Music; //インスタンス生成
  ...
  //何かエラーがあった際に,途中で関数を抜けたい
  if( XXX )return false;  //デストラクタが無かったら,return;の前にFin()しないとダメ.
  ...
  if( YYY )return false;
  ...
  //正常終了
  return true;
}

アバター
usao
記事: 1589
登録日時: 7年前

Re: 【雑談?】自分の書いたコードを見て下さい

#20

投稿記事 by usao » 7年前

例えば,「後始末が必要なこと」すら利用側は知らなくて済む.

コード:

//このクラスはメモリを動的に確保して使うが,その後始末は自動で行われる.
//利用側は,メモリが動的に確保されていること→解放の必要性があること を知らなくても使える.
//
//※デストラクタ説明用の最低限のコードです(主題ではない箇所は全て省略)※
class CTest
{
public:
  CTest(){  m_pBuffer = new int[10];  }  //このクラスはメモリを動的に確保しているが,そのことを利用者は知らなくていい.
  ~CTest(){  delete[] m_pBuffer;  }  //デストラクタでメモリを解放.
private:
  int *m_pBuffer;
};

Rittai_3D
記事: 525
登録日時: 7年前

Re: 【雑談?】自分の書いたコードを見て下さい

#21

投稿記事 by Rittai_3D » 7年前

>>usao様

返信ありがとうございます。
usao さんが書きました:デストラクタは そのオブジェクトが解体されるときに呼ばれます.
無くなる前に絶対に何かしないとダメな処理がある場合に使います.
ということは、その処理がない場合は呼び出さなくてもいいのですか?
usao さんが書きました:例えば,3D_3Dさんが示されたコードには Fin() というメソッドを持つクラスがあり,
そのクラスオブジェクトを使い終わる際に,何かしら後始末が必要なのだと見受けます.
そういったことをデストラクタに書いておくと(例えばデストラクタの実装に Fin(); と書いておく)
インスタンスが解体される直前に自動でやってもらえて便利です.
 とはいえ,DXライブラリではどうやらDxLib_End()というやつが存在しているっぽいので
 オブジェクトの後始末時にDXライブラリの機能を必要とする場合は注意が必要そうです.
Fin()はdxライブラリを利用してメモリに読み込んだ画像やwavファイルなどを解放(?)するための処理を書いています。書かなくてもDxLib_End()を呼び出せば勝手に解放してくれるらしいので、特に終了処理は書かなくてもいいそうですが、dxlibを使用しなくなった時のことを考えて、終了処理を書いて見ました。

さらに質問ですが、softya様が「コントラクタを使う場合はDxLIB系の関数は使えないので注意してください。」とおっしゃっていましたが何故使えないのでしょうか?

また、デストラクタでもDxlib系の関数は使えないのでしょうか?

長くなりましたが、回答よろしくお願いします。
初心者です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 【雑談?】自分の書いたコードを見て下さい

#22

投稿記事 by softya(ソフト屋) » 7年前

>ということは、その処理がない場合は呼び出さなくてもいいのですか?

そういう事です。

> さらに質問ですが、softya様が「コントラクタを使う場合はDxLIB系の関数は使えないので注意してください。」とおっしゃっていましたが何故使えないのでしょうか?
> また、デストラクタでもDxlib系の関数は使えないのでしょうか?

コンストラクタとデストラクタが、Dxlib_Init()からDxlib_End()の間で働くように気をつければ使えます。
usaoさんのNo.19が答えになりますね。

> おっしゃる通りにbgm,se,script,drawのように小分けにしました。行数が増えるのは嫌なので。

まぁ、C++にした時点で書くコードの量は増えるんですけどね。
たぶん、これは関数内の行数のことだと思いますけど。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Rittai_3D
記事: 525
登録日時: 7年前

Re: 【雑談?】自分の書いたコードを見て下さい

#23

投稿記事 by Rittai_3D » 7年前

>>softya様

返信ありがとうございます。

Dxlib_Init()からDxlib_End()までなら使えるんですね。

さらに質問ですが、
softya(ソフト屋) さんが書きました:> ヘッダファイルの最初で#defineするのはダメでしょうか?

少なくともコンストラクタの引数にするとか、状況変化に強い書き方のコードを書く癖を付けたほうが良いと思います。
これまた動けば良いコードの再生産になりかねません。
とありますが、コンストラクタ以外の方法はあるのでしょうか?あるならば教えて頂きたいです。
初心者です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 【雑談?】自分の書いたコードを見て下さい

#24

投稿記事 by softya(ソフト屋) » 7年前

動的確保すれば良いので、newで確保すればコンストラクタじゃなくてもどうにでもなりますが、コンストラクタに書くほうが分かりやすいのも事実です。
まぁ、STL(Standard Template Library)と言う便利なものがあるのでstd::vectorやらstd::listを使うのが無難ですけどね。これらは動的に拡張できます。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Rittai_3D
記事: 525
登録日時: 7年前

Re: 【雑談?】自分の書いたコードを見て下さい

#25

投稿記事 by Rittai_3D » 7年前

>>softya様

返信ありがとうございます。
softya(ソフト屋) さんが書きました:動的確保すれば良いので、newで確保すればコンストラクタじゃなくてもどうにでもなりますが、コンストラクタに書くほうが分かりやすいのも事実です。
まぁ、STL(Standard Template Library)と言う便利なものがあるのでstd::vectorやらstd::listを使うのが無難ですけどね。これらは動的に拡張できます。
std::vectorやstd::listは使ったことが無いので、無難にコンストラクタでいきたいと思います。

とりあえず、これが出来たらnewやらstd::vectorやらを使って見たいと思います。
初心者です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 【雑談?】自分の書いたコードを見て下さい

#26

投稿記事 by softya(ソフト屋) » 7年前

3D_3D さんが書きました:>>softya様

返信ありがとうございます。
softya(ソフト屋) さんが書きました:動的確保すれば良いので、newで確保すればコンストラクタじゃなくてもどうにでもなりますが、コンストラクタに書くほうが分かりやすいのも事実です。
まぁ、STL(Standard Template Library)と言う便利なものがあるのでstd::vectorやらstd::listを使うのが無難ですけどね。これらは動的に拡張できます。
std::vectorやstd::listは使ったことが無いので、無難にコンストラクタでいきたいと思います。

とりあえず、これが出来たらnewやらstd::vectorやらを使って見たいと思います。
動的にするしかないので、ポインタであるnewは必須ですよ。
扱いはstd::vectorの方が簡単ですけどね。ポインタ意識しなくて良いですし。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Rittai_3D
記事: 525
登録日時: 7年前

Re: 【雑談?】自分の書いたコードを見て下さい

#27

投稿記事 by Rittai_3D » 7年前

>>softya様

返信ありがとうございます。
softya(ソフト屋) さんが書きました:動的にするしかないので、ポインタであるnewは必須ですよ。
扱いはstd::vectorの方が簡単ですけどね。ポインタ意識しなくて良いですし。
std::vectorを調べて見ました。やはり、よくわかりませんでした。

思ってた以上にc++は難しいです。c言語の時は汎用性のあるコードなんて考えてしませんでした。

もう一度最初から勉強し直したほうがいいかもしれません。

まだ勉強し始めて一ヶ月も経ってないので最初から勉強しても苦にはならないと思います。
初心者です

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 【雑談?】自分の書いたコードを見て下さい

#28

投稿記事 by softya(ソフト屋) » 7年前

3D_3D さんが書きました:>>softya様

返信ありがとうございます。
softya(ソフト屋) さんが書きました:動的にするしかないので、ポインタであるnewは必須ですよ。
扱いはstd::vectorの方が簡単ですけどね。ポインタ意識しなくて良いですし。
std::vectorを調べて見ました。やはり、よくわかりませんでした。

思ってた以上にc++は難しいです。c言語の時は汎用性のあるコードなんて考えてしませんでした。

もう一度最初から勉強し直したほうがいいかもしれません。

まだ勉強し始めて一ヶ月も経ってないので最初から勉強しても苦にはならないと思います。
勉強というより、沢山のコードを書いていく中で慣れていくしか無いと思います。
c++でも雑に書こうと思えば書けるんですが、それだとC++の仕組みがややこしい分C言語の悪いプログラムよりも質が悪いです。
それを避けるためには、色んな仕組みを理解しつつ書かないといけません。
まぁ、C++で始めてやるにはMusicRoomが少々複雑なので、もう少しシンプルな題材にした方がよいでしょうね。
あとMusicRoom自体がC言語のソースコードの時点で整理・汎用性のあるコードとは言いがたいので、その修正も含めて行っている事になり余計苦労していると思います。

ちなみに、私はC++はJavaやC#よりも覚えることや仕組みが多く難易度が高いと思います。

【補足】MusicRoom自体を持て余しているなら、他の題材にチェンジして下さい。
頑張るという話であれば、引き続きやっても良いと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Rittai_3D
記事: 525
登録日時: 7年前

Re: 【雑談?】自分の書いたコードを見て下さい

#29

投稿記事 by Rittai_3D » 7年前

>>softya様

返信ありがとうございます。
softya(ソフト屋) さんが書きました:勉強というより、沢山のコードを書いていく中で慣れていくしか無いと思います。
c++でも雑に書こうと思えば書けるんですが、それだとC++の仕組みがややこしい分C言語の悪いプログラムよりも質が悪いです。
それを避けるためには、色んな仕組みを理解しつつ書かないといけません。
まぁ、C++で始めてやるにはMusicRoomが少々複雑なので、もう少しシンプルな題材にした方がよいでしょうね。
あとMusicRoom自体がC言語のソースコードの時点で整理・汎用性のあるコードとは言いがたいので、その修正も含めて行っている事になり余計苦労していると思います。

ちなみに、私はC++はJavaやC#よりも覚えることや仕組みが多く難易度が高いと思います。

【補足】MusicRoom自体を持て余しているなら、他の題材にチェンジして下さい。
頑張るという話であれば、引き続きやっても良いと思います。
アドバイスありがとうございます。いきなり複雑なMusicRoomはC++初心者の自分には早いということがわかったので、別の題材で作って見たいと思います。

このトピックはこれにて解決とします。回答してくださった皆様わ本当にありがとうございました。また次も質問すると思いますので、その時も厳し指導して下さい。
初心者です

閉鎖

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