2DゲームにおけるZソート

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

2DゲームにおけるZソート

#1

投稿記事 by イマダニ » 10年前

今回は2DゲームにおけるZソートについて質問しに来ました。
ひとまずやっつけで組んだのがこちら

コード:

/*main.h*/

#ifndef DEF_MAIN_H
#define DEF_MAIN_H

#define OBJECT_MAX 100

typedef struct{
	int CZ;
}ZSORT;/*Zソート構造体*/

extern ZSORT g_ZSORT[OBJECT_MAX];/*配列で*/

#endif

コード:

/*player.cpp*/

void PDRAW(PLAY p){	
	/*影の描画*/
	DrawRotaGraph(sqx+32 - p.camerax,sqy+32 -p.cameray,exrate,0.0,p.s_img,TRUE);

	/*プレイヤー描画*/
	if(p.jumpflag==true){/*ジャンプの時は*/
		DrawGraph(p.viewx - p.camerax,p.viewy - p.cameray,p.p_jump[p.img_num2],TRUE);/*ジャンプの画像*/
	}else{
		DrawGraph(p.viewx - p.camerax, p.viewy - p.cameray,p.p_img[p.img_num],TRUE);/*立ち画像走る画像*/
	}
	DrawGraph(p.viewx - p.camerax, p.viewy + 48 - p.cameray,img,TRUE);/*キャラの足もとに点を描画。どこが足下かわかるように。*/
	g_ZSORT[1].CZ = p.viewy + 48;/*キャラの足元の座標をZSORT構造体配列の一つ目のメンバに代入*/
}

コード:

/*map.cpp*/

void BDRAW(MAP1 m1,MAP2 m2,PLAY p){
	for(int y=0;y<m1.ReadNumY;y++){
		for(int x=0;x<m1.ReadNumX;x++){
			if(m2.BuildData[y][x]==1){/*建物データが1のところ*/
				DrawGraph(MQX(x,y) - p.camerax, MQY(x,y) - 83 - p.cameray, m1.img4, TRUE);/*建物描画*/
				DrawGraph(MQX(x,y) - p.camerax, MQY(x,y) - 83  + 103 -p.cameray, img2, TRUE);/*建物の底辺に点を描画。Zソートの基準がどこの点かわかるように*/
				g_ZSORT[0].CZ = MQY(x,y) - 83  + 103;/*建物の底辺を代入*/
			}
		}
	}
}

コード:

/*main.cpp*/

#include <DxLib.h>
#include "main.h"
#include "Key.h"
#include "Player.h"
#include "Map.h"

ZSORT g_ZSORT[OBJECT_MAX];/*Zソート構造体の実態を宣言*/

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

	AllocConsole();
    freopen("CONOUT$", "w", stdout); //標準出力をコンソールにする
	//  printf( "これでprintfが使えます\n" );   //←お試し用*/

	//構造体宣言
	PLAY p;
	MAP1 m1;
	MAP2 m2;

	PINI(&p);
	MINI(&m1,&m2);
	
	map_data_load(&m1,&m2);

	while(ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 && updatekey()==0 ){
		PMOVE(&p);

		MCHECK(m2,&p);/*当たり判定*/
		MDRAW(m1,m2,p);/*地面チップ描画*/
		BDRAW(m1,m2,p);/*建物描画*/
		PDRAW(p);/*プレイヤー描画*/
		if(g_ZSORT[1].CZ < g_ZSORT[0].CZ){/*プレイヤーのZ座標 < 建物のZ座標*/
			BDRAW(m1,m2,p);/*建物の方を先に描画*/
		}
	}

	DxLib_End();

	return 0;
}
やっつけですが、建物が一つならこれでいけました。とりあえずの実験なのでソートといえるものではありません。
そのため建物が複数になると、その建物の内で一番Z座標が高いのを基準にするので
それ以外の建物にZソートが反映されません。

なので極端な話なのですが

コード:

void BDRAW(MAP1 m1,MAP2 m2,PLAY p){
	for(int y=0;y<m1.ReadNumY;y++){
		for(int x=0;x<m1.ReadNumX;x++){
			if(m2.BuildData[y][x]==1){/*建物データが1のところ*/
				DrawGraph(MQX(x,y) - p.camerax, MQY(x,y) - 83 - p.cameray, m1.img4, TRUE);/*建物描画*/
				DrawGraph(MQX(x,y) - p.camerax, MQY(x,y) - 83  + 103 -p.cameray, img2, TRUE);/*建物の底辺に点を描画。Zソートの基準がどこの点かわかるように*/
				g_ZSORT[0].CZ = MQY(x,y) - 83  + 103;/*建物の底辺を代入*/
			}
		}
	}
}
このforでマップデータ上の建物すべてをまとめて描画するのをやめて、

コード:


void BDRAW1(){
	for(int y=0;y<m1.ReadNumY;y++){
		for(int x=0;x<m1.ReadNumX;x++){
			if(建物1){/*マップ上のオブジェクトに番号割り振り、それを基準に描画*/
				建物1の描画;
		}
	}
}

void BDRAW2(){
	for(int y=0;y<m1.ReadNumY;y++){
		for(int x=0;x<m1.ReadNumX;x++){
			if(建物2){/*マップ上のオブジェクトに番号割り振り、それを基準に描画*/
				建物2の描画;
		}
	}
}

void BDRAW3(){
	for(int y=0;y<m1.ReadNumY;y++){
		for(int x=0;x<m1.ReadNumX;x++){
			if(建物3){/*マップ上のオブジェクトに番号割り振り、それを基準に描画*/
				建物3の描画;
		}
	}
}

/*全ての描画を一つの関数にまとめる*/
void DRAW(){
	BDRAW1();
	BDRAW2();
	BDRAW3();
	PDRAW();/*プレイヤーの描画;*/

    /*これらをZ値を基準にソート*/
}
こんな風に建物ごとに一つ一つ描画し、それとプレイヤーの描画をソートする形にする感じでいいのでしょうか?
アドバイスお願いします。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: 2DゲームにおけるZソート

#2

投稿記事 by ISLe » 10年前

Zソートが必要な描画オブジェクトを抽象化、Zソート対象リストを用意する。
マップを描画する際に、建物だったらその場で描画せずにZソート対象リストに登録。
プレイヤーもZソート対象リストに登録。
Zソート対象リストに登録された描画オブジェクトをソートして順に描画。

というふうに、わたしなら、します。

イマダニ
記事: 145
登録日時: 11年前

Re: 2DゲームにおけるZソート

#3

投稿記事 by イマダニ » 10年前

抽象化、リスト構造、オブジェクト指向、これらを全く知らなかったため、1から調べていたのと、
結婚式やら葬式やらでいろいろ忙しかったので、
かーなーりおそくなってしまいました。
ISleさんすいません……

ひとまず

ポンクソフト「オブジェクト指向」を活用したシューティング
http://ponk.jp/cpp/dxlib/shooting2

とC++入門サイトとロベールを参考に、二つの描画オブジェクトをZソートするプログラムを作りました。
以下がそのコードになります。

コード:

#include <DxLib.h>
#include <list>
#include <algorithm>

//ゲーム上の物のクラス
class OBJ{
private:
	int img;//画像
	int x,y;//xとy座標
	int z;	//z座標
public:
	void SetPos(int,int);//x,yをセット
	void SetZ(int);		 //z値をセット。これを基準に描画順をソート
	void SetImg(char*);  //画像をセット
	int GetZ();			 //zを取得する関数
	void Draw(); //描画関数
};

//OBJクラス分のメモリを動的確保
typedef std::tr1::shared_ptr<OBJ> Obj;

//なんかこのゲームの全てを司るクラス的なクラス
class GAME{
private:
	/*Zソートに使うリスト*/
	std::list<Obj> obj_list;
public:
	/*ソートに使う演算子定義。<を定義*/
	friend bool operator<(const Obj& ob1,const Obj& ob2)
	{return ob1->GetZ() < ob2->GetZ();};
	
	void Add_Zlist(Obj&);//リストに追加
	void Sort_Zlist();   //zソート
	void init();		 //初期化
	void main();		 //処理をまとめたメイン
};

class Play : public OBJ{/*プレイヤークラス(仮)。OBJクラスを基本に*/
public:
	Play();
};

class Ground : public OBJ{/*地面(仮)*/
public:
	Ground();
};

void OBJ::SetPos(int posx,int posy){
	x = posx;
	y = posy;
}

void OBJ::SetZ(int zet){
	z = zet;
}

int OBJ::GetZ(){
	return z;
}

void OBJ::SetImg(char *filename){
	img = LoadGraph(filename);
}

void OBJ::Draw(){
	DrawGraph(x,y,img,TRUE);
}

Play::Play(){
	SetPos(30,200);
	SetZ(20);//z値を20に。高い方を前へ描画
	SetImg("img/house1.bmp");//画像は適当に青い家に
}

Ground::Ground(){
	SetPos(40,200);
	SetZ(10);//z値を10に。こっちが低いので後ろの方に描画
	SetImg("img/house.bmp");//画像は適当に赤い家に
}

void GAME::Add_Zlist(Obj& o){
	obj_list.push_back(o);
}

void GAME::Sort_Zlist(){
	obj_list.sort();
}

void GAME::init(){
	ChangeWindowMode(TRUE);
	DxLib_Init();
	SetDrawScreen(DX_SCREEN_BACK);
	
	Obj ground(new Ground());
	Add_Zlist(ground);

	Obj play(new Play());
	Add_Zlist(play);
}

void GAME::main(){
	// while( 裏画面を表画面に反映, メッセージ処理, 画面クリア )    
	while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){
		Sort_Zlist();
		std::for_each(obj_list.begin(), obj_list.end(), [](Obj& o) {o->Draw();});
	}
}

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){ 
	GAME game;
	game.init();
	game.main();
	DxLib_End(); // DXライブラリ終了処理      
	return 0;
}  
実行結果は地形の画像とプレイヤーの画像重なり合ってますが、
Z値が高いプレイヤーの方が前に描画されるというものです。

基本はこんな感じでいいのでしょうか?

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

Re: 2DゲームにおけるZソート

#4

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

「描画オブジェクトを抽象化」はC言語でも構造体を使えばできるので、別にC++である必然はありません。
ソートリストは上限が分かるなら配列で、分からないならポインタリストでしょうかね。
ソートも配列ならqsortを使えばよいです。

SetZの値は本来なら表示画面下端からの距離であるべきですね。つまりx,yから求めます。
【追記】 Z(奥行き)の大きいほうが奥であるほうが自然です。今は逆みたいですが。

【補足】
initメソッドで初期化したり、コンストラクタだったり統一性がないのとDXライブラリの場合はコンストラクタに迂闊に書くのはDxLib_Init()のタイミングとずれるとバグるのでやめたほうが良いかもしれません。わかっているなら良いですが。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: 2DゲームにおけるZソート

#5

投稿記事 by ISLe » 10年前

考え方としては正しいと思います。

奥行きはその都度求めることが多いと思います。
先の回答はZソート対象リストは描画の都度、作っては消す(もちろん再利用はアリ)というふうに考えてました。

最初からリストに登録しておくのが悪いということではありませんが、Zソートが必要なオブジェクトと不要なオブジェクトをそれぞれグループ化して同様にアクセスできるよう抽象化しておくと後々何かと便利かと思います。


余談ですが、std::listやstd::shared_ptrを使うと負荷がフレームワーク側に寄り過ぎて個人的に好みではないです。
使うときは局所的に使いますね。

イマダニ
記事: 145
登録日時: 11年前

Re: 2DゲームにおけるZソート

#6

投稿記事 by イマダニ » 10年前

お二方、あけましておめでとうございます。
そして今回もアドバイスありがとうございます
softya さんが書きました: 「描画オブジェクトを抽象化」はC言語でも構造体を使えばできるので、別にC++である必然はありません。
ソートリストは上限が分かるなら配列で、分からないならポインタリストでしょうかね。
ソートも配列ならqsortを使えばよいです。
C言語についてググると大抵C++がヒョコッと顔を出してくるんですよね。
しかもそれがなかなかに便利で扱いやすいと。今回の場合はクラスによる抽象化とstd::list、shared_ptrですね。
pushbackだけで追加、list::sortだけでソートできるの!?便利ー! と安易に使った感じですね。
おかげで最近

cの情報少ないし、その辺の制作ブログもC++ばかりだし、c++いっちゃおうかなー

と揺るぎまくりです。
まあ大抵は結局c++の知識が増えるだけで、慣れてるcに戻るんですが、
今回は「抽象化」に関する情報の大半がC++、C#やらのオブジェクト指向言語ばかりだったので(特にC++)
結果、しょっぼいシューティングぐらいは作った事のあるC++で書いてしまいました。

ソフト屋さんのアドバイスで、cでもできると言う事がわかったのでひとまずチャレンジしてみます。
softya さんが書きました: SetZの値は本来なら表示画面下端からの距離であるべきですね。つまりx,yから求めます。
こんな感じですかね?

コード:

void SetZ(){
	// z = √(画面左下x座標 - オブジェクトのx座標)2 + (画面左下y座標 - オブジェクトのy座標)2
	z = sqrt( pow(SCREEN_ZX-x , 2) + pow(SCREEN_ZY - y , 2) ); 
}
softya さんが書きました: initメソッドで初期化したり、コンストラクタだったり統一性がないのと
DXライブラリの場合はコンストラクタに迂闊に書くのは
DxLib_Init()のタイミングとずれるとバグるのでやめたほうが良いかもしれません。
わかっているなら良いですが。
そうですよね。危ういので書きなおします。

ISLe さんが書きました: Zソートが必要なオブジェクトと不要なオブジェクトを
それぞれグループ化して同様にアクセスできるよう抽象化しておくと
後々何かと便利かと思います。
グループ化という言葉は初めて聞きました。
あってるかどうかわかりませんがこんな感じでしょうか?

コード:

/*こんな感じに二つの基本クラスを作っておいて*/
class OBJ{//普通のオブジェクト
};
class ZOBJ{//zソートがいるオブジェクト
};

/*上記クラスにアクセス*/
class Ground : public OBJ{//地面
};
class Player : public ZOBJ{//プレイヤー
};
ISLe さんが書きました: 余談ですが、std::listやstd::shared_ptrを使うと
負荷がフレームワーク側に寄り過ぎて個人的に好みではないです。
使うときは局所的に使いますね。
そこまで考えがまわりませんでした。というかフレームワークとか一度も考えたことなかったです。
shared_ptrねー、deleteとかでかいほうしなくてもいいんかー、便利ー、俺もつーかおっとくらいの認識でしたね。
もし使わないとしたらどういった感じになるのでしょうか?よろしければ教えてください。

なんというか
お二人のアドバイスを聞いて、設計的な知識の無さを痛感しました。
こうしたほうが後々何かと便利、負荷がこっちに寄りすぎるからここだけに使おうとか、
後々のことを考えてプログラム言語の機能を取捨選択していく、そういうことが自分全くできないです。
とにかく知識を身につけて、作って経験を増やすしかないのでしょうが、早くできるようになりたいです。

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

Re: 2DゲームにおけるZソート

#7

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

Z値を固定した時の問題は背の高いキャラが重なった時です。同じZ値だとどちらが先に表示されるかは保証されません。
私が気にしたのはそこでした。

>// z = √(画面左下x座標 - オブジェクトのx座標)2 + (画面左下y座標 - オブジェクトのy座標)2

内部座標のx,yと言うつもりで書いたので、キャラクタの表示座標の足元のy座標だけでソートできます。
表示座標の場合はyが大きいほど手前ですね。ややこしくしてすいません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: 2DゲームにおけるZソート

#8

投稿記事 by ISLe » 10年前

イマダニ さんが書きました:グループ化という言葉は初めて聞きました。
あってるかどうかわかりませんがこんな感じでしょうか?
それだと逆ですね。
描画オブジェクトを抽象化することによって、グループ化しても・しなくても同様に扱えるようにするということです。

この場合の抽象化というのは描画の仕組みを共通化することです。
描画する内容ではなく仕組みだけなので、描画しない描画オブジェクトというものも作ることができます。
例えば『描画レイヤー』です。
UI部品は常に直接ゲームに関係するグラフィックよりも手前に描画されます。
すべてのグラフィック部品の前後関係を比較してソートすると無駄が多いわけです。
UIレイヤーという描画オブジェクトを定義して、UI部品(これも描画オブジェクト)を登録できるようにします。
ソートはUIレイヤーに対して行われます。
UIレイヤーの描画処理からUIレイヤーに登録された描画オブジェクトの描画処理を呼び出します。
入れ子のピラミッド構造のどこを取っても同様に扱えるというのは汎用性が高くデバッグにも便利です。
イマダニ さんが書きました:shared_ptrねー、deleteとかでかいほうしなくてもいいんかー、便利ー、俺もつーかおっとくらいの認識でしたね。
もし使わないとしたらどういった感じになるのでしょうか?よろしければ教えてください。
shared_ptrを使うとshared_ptrをコピーする必要があるので、クラス内部からthisを出せなくなります。
必然的にオブジェクトを外部から管理しなければならないので、いわゆるフレームワーク的な処理をたくさん書かなくてはいけなくなります。
使わないとしたらの一例としては、ウチのブログで公開してるタスクのコードを見ていただくのが良いかと思います。

イマダニ
記事: 145
登録日時: 11年前

Re: 2DゲームにおけるZソート

#9

投稿記事 by イマダニ » 10年前

テスト、再婚、などなどいろいろイベントがあったせいで返信がかなり遅くなってしまいました。
ISLeさん、Softyaさん、長い間放置してしまい、すいません。
softya さんが書きました: Z値を固定した時の問題は背の高いキャラが重なった時です。同じZ値だとどちらが先に表示されるかは保証されません。
私が気にしたのはそこでした。

内部座標のx,yと言うつもりで書いたので、キャラクタの表示座標の足元のy座標だけでソートできます。
表示座標の場合はyが大きいほど手前ですね。ややこしくしてすいません。
足下のy座標を基準にソートすればいいんですね。
キャラクターとかは以下の画像の一枚目の様に画像の縦の大きさぶん、キャラの縦の大きさぶん、y座標を下に調整すれば簡単に足下のY座標を取得できますが、
二枚目の様な斜め下のに向いた建物とかは、画像の赤い点、一番下の角ではなく、青い点の部分を足下にしたいので、上記のやり方では足下の座標が求められません。
この場合、

本来の足下の座標を計算する処理をプログラム側で書く(画像サイズを取得して、いろいろ頑張るなど)か、
画像を細工する(青い点の所から下は切り取るなどをする)か、

どちらがいいですかね?
ISLe さんが書きました: それだと逆ですね。
描画オブジェクトを抽象化することによって、グループ化しても・しなくても同様に扱えるようにするということです。

この場合の抽象化というのは描画の仕組みを共通化することです。
描画する内容ではなく仕組みだけなので、描画しない描画オブジェクトというものも作ることができます。
ものすっごい大雑把ですけどこんな感じですかね?

コード:

/*こんな感じに二つの基本クラスを作っておいて*/
class Map{//地面
	//描画の仕組み
};
class Hoge{//キャラクター
	//描画の仕組み
};

/*上記クラスにアクセス*/
class OBJ : public Hoge{//普通のオブジェクト
};
class ZOBJ : public Hoge{//zソートがいるオブジェクト
};
/*上記クラスにアクセス*/
class OBJ : public Map{//普通のオブジェクト
};
class ZOBJ : public Map{//zソートがいるオブジェクト
};
 
ISLe さんが書きました: 例えば『描画レイヤー』です。
UI部品は常に直接ゲームに関係するグラフィックよりも手前に描画されます。
すべてのグラフィック部品の前後関係を比較してソートすると無駄が多いわけです。
UIレイヤーという描画オブジェクトを定義して、UI部品(これも描画オブジェクト)を登録できるようにします。
ソートはUIレイヤーに対して行われます。
UIレイヤーの描画処理からUIレイヤーに登録された描画オブジェクトの描画処理を呼び出します。
入れ子のピラミッド構造のどこを取っても同様に扱えるというのは汎用性が高くデバッグにも便利です。
( ゚д゚)<……UI部品?

( ゚д゚ )<UIレイヤー?

とそんな感じでこの回答をぱっと見た時、軽く頭が思考が停止しましたが、
ググって大体は把握しました!
確かに常に手前に、常に奥に、ともうすでに描画位置が決まっている物までいちいち比較するのは無駄ですね。
ゲームで言うと背景とか、メニュー画面とか、そういったものまでソートする必要性はないですね。
なので、ISLeさんの言う上記の形を目指していきたいと思います。
ISLe さんが書きました: 使わないとしたらの一例としては、ウチのブログで公開してるタスクのコードを見ていただくのが良いかと思います。
早速見てます。正直こういったものはかなり助かります。
感謝感謝です。
添付ファイル
asimoto.jpg
asimoto.jpg (17.63 KiB) 閲覧数: 6317 回

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

Re: 2DゲームにおけるZソート

#10

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

確かにナナメの建物だとZソートが難しいですね。
建物とか立っている物の形が必ずナナメでパースが固定なのなら計算処理で青い点を求める事が出来そうな気がします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

イマダニ
記事: 145
登録日時: 11年前

Re: 2DゲームにおけるZソート

#11

投稿記事 by イマダニ » 10年前

softya さんが書きました: 確かにナナメの建物だとZソートが難しいですね。
建物とか立っている物の形が必ずナナメでパースが固定なのなら計算処理で青い点を求める事が出来そうな気がします。
早速作ってみます。

もうISLeさんとsoftyaさんのお二方に、かなりヒントも貰いましたし、あとは自分一人でどうにかなりそうなので、今回はこれで解決にしたいと思います。
できればコードを書いて、皆さんの意見を聞きたいのですが、今回のZソートはかなり時間がかかりそうなのでやめておきます。実際放置気味でしたし……

できたらまた来ますので、その時はまたよろしくお願いします。

ISLeさん、softyaさん、今回もありがとうございました。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: 2DゲームにおけるZソート

#12

投稿記事 by ISLe » 10年前

「オブジェクトを抽象化」という言い方が悪かったかもですね。
設計としては、Zソートするオブジェクトとしないオブジェクトを区別しない、ということです。
Zソートのための仕組みは共通要素として取り込んでおいて、Zソートしないオブジェクトでは実装しない、というふうにします。


Zソートの基準点に限らず、画像を元に座標を求めるのはお勧めしないです。
プログラムで計算して求めるのではなく画像を表示するオフセット位置を準備するのが良いと思います。
例えば、キャラクタが宙に浮かんでいるときは真上から光が当たってできる影の部分が足元です。
地面からキャラクタまでの空中を画像に含めたら無駄にメモリを食うし飛ぶ高さを自由に変えることもできなくなります。

閉鎖

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