|
Name: ibis ..上級者(15,947ポイント)
Date: 2008/12/15(月) 18:28
No:25714
|
|
Title: ○×ゲーム作ってみた。
|
|
とあるスレッドを見てたら○×ゲームを作りたくなったので。
でもゲームを作るのはあまり好きではないので、1時間半くらいで意欲が消失しました。
それからはもう何も考えずにキーボード叩いて、気づけば動くものができてた、という感じです。
故に終盤にコーディングした部分は「動けば何でも良い」みたいな状態になってますが・・・
製作時間は2時間ちょい。
何なんでしょうねぇ、ライブラリとか作るのは何時間でも楽しめるのですが。
用法:
1.数字が書いてあるマスをクリックして入力します。
2.1を繰り返します。
3.勝敗決定時にダイアログボックスで勝者を表示します。ダイアログボックスを消すとプロセスを終了します。
4.引き分けの場合は何も起こりません。手動で終了してください。
座標計算がおかしい気もしますが、
まぁそれも愛嬌ということで許してやってくださいな。
あ、そうそう。
ややこしくなってるので一応明記しときますが、
これはコンソールアプリケーションとしてコンパイルしてます。
313ポイント を手に入れた。
|
|
|
|
Name: Dixq (管理人) ..伝説なるハッカー(926,891ポイント)
Date: 2008/12/15(月) 18:34
No:25717
|
|
Title: Re:○×ゲーム作ってみた。
|
|
遊んでみました^^
これは、一人二役ってことですか?w 難しいw
私も昔○×ゲーム作ったことあります。
その当時は最強AIを作るのに苦労しました^^;
まず最強のAI作るためには自分が最強のアルゴリズム知ってないといけないんですよね・・。
ノートに何度も自分で○×ゲームかいて考えた記憶があります。
>何なんでしょうねぇ、ライブラリとか作るのは何時間でも楽しめるのですが。
そうなんですかぁ、私は逆でゲーム作ってると何日でも寝なくて大丈夫です(ぇ
151ポイント を手に入れた。
|
|
|
|
|
Name: ibis ..上級者(16,048ポイント)
Date: 2008/12/15(月) 18:48
No:25723
|
|
Title: Re:○×ゲーム作ってみた。
|
|
>一人二役
いや、2人用というか何と言うか。
確かにこれは1人では楽しめませんね。
その内AIでも作ってみましょかねぇ。
>最強AI
あー。
多分、優先順位が「詰む所>真ん中>直線上に敵がいない角>対角以外の角(すでに角を取ってる場合)>角>それ以外」みたいな感じかな。
とりあえず、気合を入れなおして座標計算を改善しました。
やっぱり座標計算間違ってました。
101ポイント を手に入れた。
|
|
|
|
Name: onboro ..ぴよぴよ(11ポイント)
Date: 2008/12/15(月) 18:37
No:25718
|
|
Title: DXライブラリについて
|
|
ゲームプログラミングをやってみようとして、DXライブラリを落として簡単なプログラムをやってみていたんですが1>c:\program files\microsoft visual studio 8\vc\platformsdk\include\mmreg.h : warning C4819: ファイルは、現在のコード ページ (932) で表示できない文字を含んでいます。データの損失を防ぐために、ファイルを Unicode 形式で保存してください。とエラーが出ます。どう対策をとればいいんでしょうか?
プログラミングの知識はある程度は把握できています。
11ポイント を手に入れた。
|
|
|
Name: うい ..かけだし(2,458ポイント)
Date: 2008/12/13(土) 18:26
No:25623
|
|
Title: for文
|
|
どうもfor文をいれてアドベンチャーゲームぽいものを作ろうとしているのですが、
うまくうごいてくれなく、曲も流れてくれない状況です。
また、ウィンドウをクリックもしくは動かすだけで応答なしになってしまうようになってしまいました。
↓がfor文の内容です。
for(i=0;i<10;){
if(CheckSoundFile==0)
PlaySoundFile ( "music/kyoku.wav" , DX_PLAYTYPE_BACK ) ;
ClearDrawScreen(); // 裏画面のデータを全て削除
LoadGraphScreen( 0, 0, "graph/haikei1.png" , FALSE ) ;
LoadGraphScreen( 50, 270, "graph/hito1.png" , TRUE ) ;
LoadGraphScreen( 550, 270, "graph/hito2.png" , TRUE ) ;
if(i==0)
DrawString( 70, 350, "あ", black);
else if(i==1)
DrawString( 70, 350, "い", black);
else if(i==2)
DrawString( 70, 350, "う", black);
else if(i==3)
DrawString( 70, 350, "え", black);
else if(i==4)
DrawString( 70, 350, "お", black);
else if(i==5)
DrawString( 70, 350, "か", black);
else if(i=6)
DrawString( 70, 350, "き", black);
else if(i==7)
DrawString( 70, 350, "く", black);
else if(i==8)
DrawString( 70, 350, "け", black);
else if(i==9)
DrawString( 70, 350, "こ", black);
ScreenFlip() ; // 裏画面データを表画面へ反映
if(Key[KEY_INPUT_RETURN]==1)
i++;
}
743ポイント を手に入れた。
|
|
|
|
Name: kazuoni [URL] ..熟練のプログラマー(41,790ポイント)
Date: 2008/12/13(土) 19:05
No:25626
|
|
Title: Re:for文
|
|
すみません。よく意味がわからないのですが。。
よくないとこだけ記述しておきます。
LoadGraphScreen()は重い(?)処理なので、
なるべく少なくしたほうが良いです。
for文の外に出しましょう。
今のままだと、returnが押されるまでものすごい回数呼び出していることになるので、
処理落ちしているのかと。。
PlaySoundFile()の条件がよくわからないのですが、
for文中もバックサウンドで流すなら、for文の外に出しましょう。
今のままだと文が返ってくるたびに最初から再生していることになります。
168ポイント を手に入れた。
|
|
|
|
|
Name: うい ..入門者(2,590ポイント)
Date: 2008/12/13(土) 19:17
No:25629
|
|
Title: Re:for文
|
|
外に出してみたのですが、やはり駄目で、相変わらずエンター押しても動かず、ウィンドウを動かすだけで応答なしになってしまいました。
曲はもし流れていないなら流すという感じにしているのでそのようなことにはなっていないとは思うのですがその辺はどうでしょうか?
ただ、今PlaySoundFileをforの外にやった結果一応流れました。
132ポイント を手に入れた。
|
|
|
|
|
Name: kazuoni [URL] ..熟練のプログラマー(42,035ポイント)
Date: 2008/12/13(土) 19:30
No:25630
|
|
Title: Re:for文
|
|
>外に出してみたのですが、やはり駄目で、相変わらずエンター押しても動かず、
>ウィンドウを動かすだけで応答なしになってしまいました
上のコードだけでは、ちょっと分かりませんが、
for文から出しただけでも、
mainのwhileで毎回呼び出してしまっていても同じことが起こります。
呼び出すのは一度だけにしてください。
>曲はもし流れていないなら流すという感じにしているので
>そのようなことにはなっていないとは思うのですがその辺はどうでしょうか?
それならばループで一度だけ呼び出したほうがいいと思います。
245ポイント を手に入れた。
|
|
|
|
|
Name: ななし ..かけだし(1,419ポイント)
Date: 2008/12/15(月) 15:24
No:25704
|
|
Title: Re:for文
|
|
Key[KEY_INPUT_RETURN] が 1 になるのはいつですか?
そこが 1 になっている場合だけ i++ をしているようですが、1 にならない限りループは永遠に止まりません。
42ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) ..伝説なるハッカー(926,037ポイント)
Date: 2008/12/15(月) 15:33
No:25706
|
|
Title: Re:for文
|
|
CheckSoundFileは関数ですから、関数としての記述をして下さい。
後、このままでは何度もループ再生する事になると思いますが、ループ再生するときは、ループのオプションを指定しましょう。
また、サウンドも、画像も一旦メモリに展開してから使うようにして下さい。
詳しくはゲームプログラミングの館やサンプルプログラミングの館をご覧下さい。
また、Keyにキーの入力状態が格納されていませんからi++が行われません。
そしてProcessMessageを定期的に呼ばないと応答不能になります。
DXライブラリを使ったプログラムコードの骨格は
http://dixq.net/g/#41
この辺を参考にして下さい。
253ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) ..伝説なるハッカー(926,186ポイント)
Date: 2008/12/15(月) 15:39
No:25707
|
|
Title: Re:for文
|
|
似たようなことを行うためのサンプルを先ほどのリンク先のコードを元に作ってみました。
#include "DxLib.h"
int Key[256];
int GetHitKeyStateAll_2(int GetHitKeyStateAll_InputKey[]){
char GetHitKeyStateAll_Key[256];
GetHitKeyStateAll( GetHitKeyStateAll_Key );
for(int i=0;i<256;i++){
if(GetHitKeyStateAll_Key[i]==1) GetHitKeyStateAll_InputKey[i]++;
else GetHitKeyStateAll_InputKey[i]=0;
}
return 0;
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
int i=0;
char DataStr[21]="あいうえおかきくけこ", DrawStr[3]={0,};
ChangeWindowMode(TRUE);//ウィンドウモード
if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化
while(ProcessMessage()==0 && ClearDrawScreen()==0 &&
GetHitKeyStateAll_2(Key)==0 && Key[KEY_INPUT_ESCAPE]==0 && i<10){
strncpy(DrawStr,&DataStr[i*2],2);
DrawFormatString(0,0,GetColor(255,255,255),"%s",DrawStr);
if(Key[KEY_INPUT_RETURN]==2)
i++;
ScreenFlip();
}
DxLib_End();
return 0;
}
エンターを押しながら確認してみて下さい。
149ポイント を手に入れた。
|
|
|
|
Name: Dixq (管理人) ..伝説なるハッカー(925,784ポイント)
Date: 2008/12/15(月) 15:25
No:25705
|
|
Title: ■龍神録の館 利用規約改正■
|
|
大学や専門学校等に通っている方々は忙しくなっている時期だと思いますが、皆さんいかがお過ごしでしょうか。
今回龍神録プログラミングの館の利用規約を改正しました。
http://dixq.net/rp/kiyaku.html
「利用したいけどせっかく作っても見せたらダメって言われたんじゃやり切れない」
「画像を自分で用意するのがめんどくさい」
「プログラムをどれ位オリジナルにすればいいのかこれじゃわからない」
そんな声があったので、
・画像の二次使用OK
・あまりにそのままのコピーに近い物でないかぎり、販売、卒業制作の利用OK
・龍神録のプログラムを使ってアクションを起こすときは基本的に報告だけすればOK
そんな感じに変更しました。
どのように使われるのか把握だけはしておきたいので、使用して何かされる際はお手数ですが報告だけお願いしますm(_ _)m
344ポイント を手に入れた。
|
|
|
Name: とうや ..ぴよぴよ(211ポイント)
Date: 2008/12/04(木) 18:23
No:25087
|
|
Title: 周期境界条件を用いたプログラム
|
|
いつもお世話になっています。
今回はC言語について質問させていただきます。
〜〜〜〜〜〜〜プログラムについて〜〜〜〜〜〜〜〜
■渋滞のプログラムを作成中です。
概要として…
0=何もない
1=車がある
と思ってください。
例として…
『0010101110010』
とあった場合です。
※右端と左端は連続したものと考えてください
「条件」
●1(車)は前に移動する
●1は前に0の場合前に進むことが出来る
●1は前に1があった場合その場にとどまる
です。
これを複数回繰り返しています。
例題を動かすと・・・
例→『0010101110010』
次→『0001011101001』
次→『1000111010100』
のように動いていきます。
(*プログラム参照)
今回はこのプログラムを作成し、このプログラムを元に次のプログラムを作成しようと考えていたところ
どのようにすればよいか分からなくなったため質問しました。
〜〜〜〜〜〜作りたいプログラム〜〜〜〜〜
先ほどの●の条件に加え
●1がある確率で0になる
●0がある確率で1になる
としたいと思っています。
rand time 関数などを使えばよいのかな?と思って作成していたのですが
上手くいきませんでした。
アドバイス・意見よろしくお願いします。
211ポイント を手に入れた。
|
|
|
|
Name: conio ..初心者(5,142ポイント)
Date: 2008/12/05(金) 08:57
No:25112
|
|
Title: Re:周期境界条件を用いたプログラム
|
|
srand関数と、rand関数を使えばいいと思います。
-------------------------------------
srand(time(NULL));
if(rand() % 5 == 4)
x = (x + 1) % 2
-------------------------------------
xに1を足して2で割れば、
xが0の場合は、xは1に、
xが1の場合は、xは0になります。
あとはこの処理が実行される確率を決めてあげればいいと思います。(ここでは約5分の1)
こんな感じで、どうでしょう?
100ポイント を手に入れた。
|
|
|
|
|
Name: とうや ..ぴよぴよ(237ポイント)
Date: 2008/12/06(土) 20:27
No:25236
|
|
Title: Re:周期境界条件を用いたプログラム
|
|
ありがとうございます!
しかし、その部分をプログラムのどの部位に入れたら良いか分からず迷っています。
アドバイスよろしくお願いします。
26ポイント を手に入れた。
|
|
|
|
|
Name: 組木紙織 [URL] ..熟練のプログラマー(66,873ポイント)
Date: 2008/12/07(日) 18:55
No:25297
|
|
Title: Re:周期境界条件を用いたプログラム
|
|
今、プログラムを解析中です。
Windows環境でコンパイルするとエラーが出ますね。
ちょっとそれで引っかかりました。
別すれも言及がありましたが、C99で作っていますね。
それも引っかかってしまいました。
根本的な問題なので聞きたいのですが、
条件と例の動きが一致していないように思います。
本当にその条件、その動き方でいいのでしょうか?
再検討を願います。
8ポイント を手に入れた。
|
|
|
|
|
Name: 組木紙織 [URL] ..熟練のプログラマー(67,050ポイント)
Date: 2008/12/07(日) 22:42
No:25311
|
|
Title: Re:周期境界条件を用いたプログラム
|
|
一通りプログラム読んでみました。
このまま変更かけるよりは、
最初から全部作り直したほうが速そうです。
まずは、設計をきちんとすべきですね。
気づいていないかもしれない問題点があります。
添付してもらったプログラムはそれぞれの車の総移動距離を最後に出しますよね。
途中で消えた車と、途中で入ってきた車はどうするのですか?
129ポイント を手に入れた。
|
|
|
|
|
Name: とうや ..ぴよぴよ(724ポイント)
Date: 2008/12/07(日) 22:43
No:25312
|
|
Title: Re:周期境界条件を用いたプログラム
|
|
解析ありがとうございます
環境としてUnix(Linux)環境で作成しています
PC自体譲り受けたものですので詳しいことが分かりません。
調べてみたいと思います。
C99、C95、C90などの区別も詳しくは分かっていないのですが・・・
Windows環境でプログラムを作ったことがないので、Windowsでの動作確認は行っていません。
まことに申し訳ございません。
私のPC上の動作確認では・・・
gnuplot上で円系に●が動く形になっています。
例1
n ○●○●○●●● (右と左は繋がっている)
n+1 ●○●○●●●○
n+2 ○●○●●●○●
n+3 ●○●●●○●○
n+4 ○●●●○●○●
のような形が円状になっています。
動作中の1コマを添付しました。
条件としては、
●1は前に移動する
●1は前に0の場合前に進むことが出来る
●1は前に1があった場合その場にとどまる
が基本なことに変わりはありません。
ただ、●がある確率で○に・・・
○がある確率で●に・・・
変わるようなプログラムを作成したいと思っています。
それはランダムな●、○にしたいと思っています
確率が0の場合は例1のような形から変更はなしといって形です。
確率が100の場合は反転するという形に
(反転後次の時間に移動、移動後に反転は現段階ではどちらでもよいと思っています)
現在UPしているプログラムをそのまま使わずに
もっと良い方法があればアドバイス下さると助かります。
親切な質問ありがとうございます。
分からないことがあれば色々聞いてください。精一杯お答えしようと思います。
487ポイント を手に入れた。
|
|
|
|
|
Name: どうや ..ぴよぴよ(75ポイント)
Date: 2008/12/07(日) 22:50
No:25314
|
|
Title: Re:周期境界条件を用いたプログラム
|
|
問題点の指摘ありがとうございます。
総移動距離のことは気づいていませんでした。
今回では、移動距離よりも、どれくらい込み合うかのプログラムを作ろうと思っています。
どれくらいの確率で車が入ってくれば渋滞するのか
どれくらいの確率で車が出れば全く渋滞しなくなるのか
その境目を調べてみたいと思っています。
アドバイスありがとうございます
75ポイント を手に入れた。
|
|
|
|
|
Name: 組木紙織 [URL] ..熟練のプログラマー(67,382ポイント)
Date: 2008/12/07(日) 23:30
No:25319
|
|
Title: Re:周期境界条件を用いたプログラム
|
|
>条件と例の動きが一致していないように思います。
>本当にその条件、その動き方でいいのでしょうか?
>再検討を願います。
ここは勘違いがあったので修正です。
元々の条件とプログラムの動作が一致していないので、
その部分は問題がないのでしょうか?
(多分条件文のほうが正しいとは思いますが。)
また、プログラム上での移動方向と例での移動方向が異なっているのも問題はないのでしょうか?
アドバイスとしては、
まずは、設計をして、
確率変動しない場合のコードを作り直してみてください。
(その際自分に必要ない部分は出来るだけ省くこと)
そのときの考え方は
道は一本なんですよね。
なら一次元配列を道に見立てればよいです。
車の位置ですが、一次元配列にそのまま書き込んであげればよいかと。
次に車の動き方ですが、それは添付してあるコードを参考にすればいいです。
#コメントを見る限りでは大学の研究のようなので、回りに聞ける人がいると思うのでそっちのほうが速いと思いますが。
332ポイント を手に入れた。
|
|
|
|
|
Name: conio ..初心者(7,899ポイント)
Date: 2008/12/07(日) 23:56
No:25321
|
|
Title: Re:周期境界条件を用いたプログラム
|
|
@車は前(右)に進む
Aループして戻ってくる(一番左に戻る)
B前(右)に車があった場合動かない
とりあえず、参考になるかは分かりませんがこの条件だけでプログラムを作ってみました。
突貫作業で作ったのでミスなどあるかもしれません。
-------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#define NUM 20
int a[NUM] = {0};
void set(void)/*車を配置する。*/
{
srand((unsigned)time(NULL));
for(int i = 0; i < NUM; i++)
a[ i ] = rand() % 2;
}
void hyouzi(void)/*現在の状態を表示する*/
{
for(int i = 0; i < NUM; i++)
printf("%d┃",a[ i ]);
printf("\n");
}
void idou(void)/*車を右に移動させる*/
{
for(int i = 0; i < NUM; i++)
if(a[ i ] != 0 && a[(i + 1) % NUM] == 0){
a[(i + 1) % NUM] = 1;
a[ i ] = 0;
i++;
}
}
int main(void)
{
set();
while(1){
hyouzi();
idou();
Sleep(3000);
}
return(0);
}
-------------------------------------------------------------
|
|
|
|
|
Name: とうや ..ぴよぴよ(756ポイント)
Date: 2008/12/09(火) 13:13
No:25380
|
|
Title: Re:周期境界条件を用いたプログラム
|
|
様々なアドバイスありがとうございます!
今から新たしくプログラムを作成しようと思います。
32ポイント を手に入れた。
|
|
|
|
|
Name: Justy ..ハッカー(284,567ポイント)
Date: 2008/12/11(木) 01:52
No:25531
|
|
Title: Re:周期境界条件を用いたプログラム
|
|
> 組木紙織さん
最初の方しか見ていないのですが、
>get_rand()
Unixでコンパイルしたとき、RAND_MAXが 0x7fffffffだったりすると、
get_rand()でおかしなこと(オーバーフロートとか)になりませんか?
>struct grand
関数オブジェクトを実行するとき毎回 srandが time()を伴って呼ばれていますが、
これって前回実行時とほとんど差がない場合、毎回同じ値を rand()が出力してしまうのでは
ないでしょうか?
>std::random_shuffle(road.begin(),road.end(),grand())
この行もちょっとおかしいです。grandの一時変数を 非constな参照で渡しています。
203ポイント を手に入れた。
|
|
|
|
|
Name: non ..上級者(20,772ポイント)
Date: 2008/12/11(木) 10:58
No:25544
|
|
Title: Re:周期境界条件を用いたプログラム
|
|
最初の説明では
→進行方向
例→『0010101110010』
次→『0001011101001』
次→『1000111010100』
でしたが、次の説明では、
←進行方向
n ○●○●○●●● (右と左は繋がっている)
n+1 ●○●○●●●○
n+2 ○●○●●●○●
n+3 ●○●●●○●○
n+4 ○●●●○●○●
となっています。
文章で書かれた条件からすれば、最初の方が正しいのかと思いますが、
下のは、現在のプログラムはこうなっているからまずいという説明だったのでしょうか?
要するに自動車は一斉に動くのか、順番に動くのかです。
自然の状態なら、電車のように同速度で動いて問題ないけど、
車の渋滞のような場合だと、ワンテンポ、スタートが遅れますものね。
さて、どっち?
conioさんのプログラムでは配列の0番からスタートしていますが、最後のNUM-1番目の車は
0番目の位置を見に行きますが、このときすでに0番目の車は1番目に動いているので
まずいと思われます。
402ポイント を落としてしまった。
|
|
|
|
|
Name: non ..上級者(20,885ポイント)
Date: 2008/12/11(木) 11:58
No:25546
|
|
Title: Re:周期境界条件を用いたプログラム
|
|
ものすごい勘違いをしてました。
進行方向→
n ○●○●○●●● (右と左は繋がっている)
n+1 ●○●○●●●○
n+2 ○●○●●●○●
n+3 ●○●●●○●○
n+4 ○●●●○●○●
進行方向が逆でした。2つの説明はまったく同じでした。大変失礼しました。
79ポイント を手に入れた。
|
|
|
|
|
Name: とうや ..ぴよぴよ(791ポイント)
Date: 2008/12/15(月) 14:15
No:25698
|
|
Title: Re:周期境界条件を用いたプログラム
|
|
C++のサンプルコード アドバイスありがとうございます。
C++は触ったことがないので、これを機に勉強(解読)します。
35ポイント を手に入れた。
|
|
|
|
Name: トト ..ぴよぴよ(166ポイント)
Date: 2008/12/15(月) 13:51
No:25697
|
|
Title: アンマネージドなゲームプログラミングについて
|
|
こんにちわ
今、VC++でゲーム作成をはじめようと考えています(初心者です)。
そのプログラミングに関して気になった点があったので質問させて頂きました。
最近のゲームプログラミング(自作ゲーム・同人ゲーム)では、マネージドコードかアンマネージドコードのどちらで書かれることがメジャーなのでしょうか?
またVC++2008でアンマネージドなプログラミングをする方法を教えていただけないでしょうか?
166ポイント を手に入れた。
|
|
|
Name: dic ..初心者(6,591ポイント)
Date: 2008/12/15(月) 06:33
No:25687
|
|
Title: VC++2008にてのコンパイルエラー
|
|
質問させてもらいます
#include "stdafx.h"
#include <iostream>
#include <vector>
using namespace std;
void func( int *p )
{
printf( "%d\n", *p );
}
int _tmain(int argc, _TCHAR* argv[])
{
vector<int> vi;
int i;
for( i=0; i<10; i++ )
vi.push_back(i);
vector<int>::iterator p = vi.begin();
while( p != vi.end() ) {
func(p); // ここがエラー
p++;
}
return 0;
}
上記のように書いたのですが VC++2008 Express にてコンパイルエラー
error C2664: 'func' : 1 番目の引数を 'std::_Vector_iterator<_Ty,_Alloc>' から 'int *' に変換できません。(新しい機能 ; ヘルプを参照)
with
[
_Ty=int,
_Alloc=std::allocator<int>
]
この変換を実行可能なユーザー定義変換演算子がないか、または演算子を呼び出せません。
とでます
VC++6.0 では通るのですが
どうすればコンパイルが通るのでしょうか?
344ポイント を落としてしまった。
|
|
|
|
Name: non ..上級者(22,338ポイント)
Date: 2008/12/15(月) 09:18
No:25690
|
|
Title: Re:解決
|
|
func(* p);で呼び出して、
void func( int p )
{
printf( "%d\n", p );
}
にするのでは?
70ポイント を手に入れた。
|
|
|
|
Name: しょしょしょしんしゃ ..中級者(10,131ポイント)
Date: 2008/12/12(金) 20:04
No:25598
|
|
Title: 非線形方程式 3分法
|
|
学校の課題です。
非線形方程式を2分法または3分法(分割数を3にした場合)
を用いて、プログラムを作成して、25の3乗根を求めよ。(x^3-25=0)
という問題で、2分法はできましたが、3分法の求め方が分かりません。
2分法は以下の通りです。
#include<stdio.h>
#include<math.h>
#define f(x) ((x)*(x)*(x)-25)
int main(void){
float a=2.0,b=3.0,c;
do{
c=(a+b)/2.0;
if(fabs(f(c))<=1.0e-7)break;
if(f(a)*f(c)<0)b=c;
if(f(b)*f(c)<0)a=c;
}while((b-a)>=1.0e-6);
printf("方程式x^3-25=0の解は%fです\n",c);
return 0;
}
実行結果は 方程式x^3-25=0の解は2.924108です。
という風になり、3分法も、これに近い値で実行できる。
よろしくお願いします。
284ポイント を手に入れた。
|
|
|
|
Name: 初級者 ..入門者(3,109ポイント)
Date: 2008/12/12(金) 20:52
No:25602
|
|
Title: Re:非線形方程式 3分法
|
|
3分法について習った内容を教えてください。
2倍のポイントを手に入れた! 34ポイント を手に入れた。
|
|
|
|
|
Name: non ..上級者(21,374ポイント)
Date: 2008/12/12(金) 21:28
No:25604
|
|
Title: Re:非線形方程式 3分法
|
|
>}while((b-a)>=1.0e-6);
この終了条件は、どうして必要なんだっけ?
>if(fabs(f(c))<=1.0e-7)break;
こっちがあるなら必要がないような気がするけど。もし、振動するのなら、ループ回数を
制限するのかな?でも、3乗根だから収束すると思うけどな。
ただ、有効桁数が1.0e-7まで取れるか心配だけど。
doubleだと単独だと15桁ぐらいだけど、3乗だから、どうだっけ?
163ポイント を手に入れた。
|
|
|
|
|
Name: しょしょしょしんしゃ ..中級者(10,386ポイント)
Date: 2008/12/12(金) 23:06
No:25606
|
|
Title: Re:非線形方程式 3分法
|
|
>3分法について習った内容を教えてください。
えーと 申し訳ないのですが、3分法は 高校、大学で習った覚えがないのですが・・・。
2分法は、平均値の定理で 習った覚えはありますが....
>}while((b-a)>=1.0e-6);
>この終了条件は、どうして必要なんだっけ?
cを計算しf(c)=0ならば解が得られたらのでdo-while文からぬける。
でもきれいに0になるわけではないので、小さくなったらぬけるようにしてあります。
>if(fabs(f(c))<=1.0e-7)break;
これはaとbがほぼ同じになったら計算をやめて解とする。らしいです。
この部分はたぶん、2分法特有じゃないんですか?
255ポイント を手に入れた。
|
|
|
|
|
Name: box ..ハッカー(131,808ポイント)
Date: 2008/12/12(金) 23:21
No:25607
|
|
Title: Re:非線形方程式 3分法
|
|
> えーと 申し訳ないのですが、3分法は 高校、大学で習った覚えがないのですが・・・。
ていうか、そもそも3分法というのがあるんでしょうか。
収束条件の話は、どちらか片方があればじゅうぶんだと思います。
48ポイント を手に入れた。
|
|
|
|
|
Name: non ..上級者(21,492ポイント)
Date: 2008/12/13(土) 09:30
No:25616
|
|
Title: Re:非線形方程式 3分法
|
|
3分法があるかないかは兎も角、
要は、abの区間を3つに分けて、仮にそれをcdとすると、
a-c区間を通る場合は、b=c
d-b区間を通る場合は、a=d
c-d区間を通る場合は、a=c、b=d
にすればいいでしょう。
while(1)にして、収束条件は1.0e-5で。
118ポイント を手に入れた。
|
|
|
|
|
Name: box ..ハッカー(131,837ポイント)
Date: 2008/12/13(土) 10:34
No:25617
|
|
Title: Re:非線形方程式 3分法
|
|
あ〜なるほど、そういうことですね。
判定のたびに区間が1/3になるので、
二分法より速く収束するのですね。
29ポイント を手に入れた。
|
|
|
|
|
Name: しょしょしょしんしゃ ..中級者(10,678ポイント)
Date: 2008/12/14(日) 13:27
No:25638
|
|
Title: Re:非線形方程式 3分法
|
|
#include<stdio.h>
#include<math.h>
#define f(x) ((x)*(x)*(x)-25)
int main(void){
float a=2.0,b=3.0,c,d;
do{
d=(a+b)/2.0;
if(fabs(f(d))<=1.0e-5)break;
if(f(a)*f(c)<0)b=c;
if(f(d)*f(b)<0)a=d;
if(f(c)*f(d)<0)a=c,b=d;
}while(1);
printf("方程式x^3-25=0の解は%fです\n",d);
return 0;
}
つまり、こうゆうことなのですか?
ちょっと話についていけなくてすみません。
>要は、abの区間を3つに分けて、仮にそれをcdとすると、
うまく abの区間をわけることができませんでした・・。
292ポイント を手に入れた。
|
|
|
|
|
Name: box ..ハッカー(131,904ポイント)
Date: 2008/12/14(日) 14:12
No:25640
|
|
Title: Re:非線形方程式 3分法
|
|
>うまく abの区間をわけることができませんでした・・。
高校の数学Tあたりで学ぶ「内分の公式」について調べてみると、
nonさんが示してくださった式の意味がわかるかもしれません。
67ポイント を手に入れた。
|
|
|
|
|
Name: しょしょしょしんしゃ ..中級者(10,882ポイント)
Date: 2008/12/14(日) 15:14
No:25641
|
|
Title: Re:非線形方程式 3分法
|
|
#include<stdio.h>
#include<math.h>
#define f(x) ((x)*(x)*(x)-25)
int main(void){
float a=2.0,b=3.0,c=a+(b-a)/3,d=a+(b-a)*2/3;
int count=0;
do{
d=(a+b)/2.0;
if(fabs(f(d))<=1.0e-5)break;
if(f(a)*f(d)<0)b=d;
if(f(b)*f(d)<0)a=d;
printf("%d方程式x^3-25=0の解は%fです\n",count,d);
count++;
}while(1);
printf("方程式x^3-25=0の解は%fです\n",d);
return 0;
}
こんなかんじですかね?
しかし、2分法の場合は20回繰り返されて、こちらのプログラマムは18回繰り返されました。
数は少なくなったのはいいのですが、これでよろしいのでしょうか?
204ポイント を手に入れた。
|
|
|
|
|
Name: box ..ハッカー(131,974ポイント)
Date: 2008/12/14(日) 15:48
No:25644
|
|
Title: Re:非線形方程式 3分法
|
|
> float a=2.0,b=3.0,c=a+(b-a)/3,d=a+(b-a)*2/3;
ここでせっかく求めた d の値を、
> d=(a+b)/2.0;
ここで上書きしてはいけません。
ていうか、2分法のところで
> c=(a+b)/2.0;
を do 文によるループの「中に」書いた理由がおわかりですか?
70ポイント を手に入れた。
|
|
|
|
|
Name: しょしょしょしんしゃ ..中級者(11,191ポイント)
Date: 2008/12/15(月) 00:14
No:25675
| 解決!
|
Title: Re:非線形方程式 3分法
|
|
#include<stdio.h>
#include<math.h>
#define f(x) ((x)*(x)*(x)-25)
int main(void){
float a=2.0,b=3.0,c,d;
do{
c=a+(b-a)/3;
d=a+(b-a)*2/3;
if(fabs(f(d))<=1.0e-5)break;
if(f(a)*f(c)<0)b=c;
if(f(d)*f(b)<0)a=d;
if(f(c)*f(d)<0)a=c,b=d;
}while(1);
printf("方程式x^3-25=0の解は%fです\n",d);
return 0;
}
こんな感じでいいでしょうか? 実行は12回繰り返しました。
ご指摘があれば、直します。
長い間、御苦労かけました。
boxさん,nonさんには、多大なご協力感謝しています。
309ポイント を手に入れた。
|
|
|
|
|
Name: non ..上級者(22,268ポイント)
Date: 2008/12/15(月) 08:37
No:25689
|
|
Title: Re:非線形方程式 3分法
|
|
>if(fabs(f(d))<=1.0e-5)break;
cに収束分も加えること。
24ポイント を落としてしまった。
|
|
|
|
Name: 砂 ..ぴよぴよ(75ポイント)
Date: 2008/12/14(日) 19:22
No:25658
|
|
Title: 処理手順
|
|
はじめまして。
シューティングゲームを作ってみようと思うのですが、
その際のプログラムの処理手順というのは、どのようにして行われるものなのでしょうか?
75ポイント を手に入れた。
|
|
|
|
Name: array [URL] ..熟練のプログラマー(41,207ポイント)
Date: 2008/12/14(日) 19:41
No:25661
|
|
Title: Re:処理手順
|
|
砂さん初めまして。今からシューティングを作ってみたいという事なので
細かい処理手順じゃなくて、大まかな流れを知りたいという事ですかね。
1.自機を動かす(移動・ショットなど)
↓
2.敵・ボスの制御(予め決められた動き・攻撃をする)
↓
3.弾の動きを制御
↓
4.当り判定(敵の攻撃に被弾していないか。自機のショットが敵に当たっているか)
↓
5.描画(自機や敵、背景などの画像を表示する)
大雑把に説明すればこんな感じの手順で処理しています。
この1〜5までの流れを1フレームといいFPS(実行速度)と密接に関係してきます。
60FPSで実行されてるなら1秒間に60回 1〜5の処理を行っている事になります。
実際はもっといろいろなプログラムが組み込まれていて(一概には言えませんが関数など)、複雑に思える部分もあるかもしれません。
プログラミングの経験があるのなら龍神録の館を手書きで入力していくなりして一つ一つ理解していけばいいと思います。
199ポイント を手に入れた。
|
|
|
|
|
Name: 砂 ..ぴよぴよ(194ポイント)
Date: 2008/12/14(日) 20:01
No:25662
|
|
Title: Re:処理手順
|
|
arrayさんご回答ありがとうございます。
もう少し詳しい流れとしては下記のような形でよろしいのでしょうか?
ゲーム開始
↓
敵出現
↓
当たり判定
↓
自機に当たっているか→YES:ライフ減算:残機があるか→YES:当り判定へ
↓NO ↓NO
ゲーム終了
敵機に当たっているか→YES:敵機グラフィック消去
↓NO
敵機出現へ
119ポイント を手に入れた。
|
|
|
|
|
Name: array [URL] ..熟練のプログラマー(41,370ポイント)
Date: 2008/12/14(日) 20:14
No:25663
|
|
Title: Re:処理手順
|
|
ゲームの流れでいえば、だいたいそんな感じになると思います。
もう少し詳しく知りたければ、実際にシューティングゲームをプレイしてみるのも手だと思います。
私も言える事といえば、龍神録を実際にプレイしてみての価値観からと
龍神録の館のプログラムに触れてみての考えだけです。
ちなみに(既にプレイ済みかもしれませんが)龍神録でいえば、残機が0になってもゲーム終了ではなく、コンティニュー画面を表示させたりしてると思います。
他にも、プレイ中にも割り込み処理で[Esc]キーを押したら 一時停止画面に飛んだり
ストーリー上、途中ボスが割り込んできたりとします。
163ポイント を手に入れた。
|
|
|
|
|
Name: 砂 ..ぴよぴよ(231ポイント)
Date: 2008/12/14(日) 20:20
No:25664
| 解決!
|
Title: Re:処理手順
|
|
arrayさんいろいろありがとうございます。
またいろいろと試してみようと思います。
37ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) [URL] ..伝説なるハッカー(924,765ポイント)
Date: 2008/12/15(月) 03:51
No:25681
|
|
Title: Re:処理手順
|
|
ちょっと処理の流れの説明がよくわかりませんが・・、
ここで言う処理手順と言うのは、関数を呼ぶ順番だったり、画面内容消去から、裏画面反映までのメインループ内の処理の順番のことでしょうか?
なかなか口で言ってもわかりにくい場合もあると思うので、ゲームプログラミングの館を見ていただき、
STGのサンプルでしたら龍神録の館のサンプルを見ていただいたりしたほうがわかりやすいかもしれません。
何かサンプルで解らない事があれば聞いて下さいm(_ _)m
162ポイント を手に入れた。
|
|
|
|
Name: nisi ..ぴよぴよ(44ポイント)
Date: 2008/12/14(日) 17:49
No:25649
|
|
Title: Windowsが速攻で終わってしまう
|
|
ウインドウを表示したいのですが
実行した瞬間に終わってしまいます。
何が間違えているのか教えて頂けないでしょうか?
44ポイント を手に入れた。
|
|
|
|
Name: Justy ..ハッカー(284,867ポイント)
Date: 2008/12/14(日) 17:56
No:25650
|
|
Title: Re:Windowsが速攻で終わってしまう
|
|
メッセージループがないからです。
ウインドウを折角つくっても、そのまま「とりあえず0を返して」アプリを
終了させてしまっていますよ。
3章 Windowsアプリケーションの骨格(その1)
ttp://web.kyoto-inet.or.jp/people/ysskondo/chap3.html
58ポイント を手に入れた。
|
|
|
|
|
Name: conio ..中級者(9,712ポイント)
Date: 2008/12/14(日) 20:24
No:25665
|
|
Title: Re:Windowsが速攻で終わってしまう
|
|
原因は、すぐreturn(0)のところに行ってしまうからですね。
return(0)の前に、こちらの入力を待つ関数などを挟めばいいと思います。
もしくは無限ループにし、条件に応じてbreak。
--------------------------------------------------------------------------------------------------
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // ウィンドウプロシージャ
HINSTANCE hInst;// インスタンス
HWND hWnd; // ウィンドウハンドル
HDC hDC_Wnd; // ウィンドウのデバイスコンテキスト
//==============================================================================================
// Windows メイン処理
//==============================================================================================
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
// ウィンドウクラスの登録
WNDCLASS wc; // windows.hにあるウインドウの情報を入れることができる変数
ZeroMemory(&wc, sizeof(WNDCLASS)); // 構造体で作ったwcの変数をすべて0で初期化
wc.style = CS_HREDRAW | CS_VREDRAW; // ウィンドウスタイル
wc.lpfnWndProc = (WNDPROC)WndProc; // ウィンドウプロシージャ
wc.cbClsExtra = 0; // 補助領域サイズ
wc.cbWndExtra = 0; // 補助領域サイズ
wc.hInstance = hInstance; // インスタンスハンドル
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); // アイコン
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // マウスカーソル
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); // クライアント領域背景色
wc.lpszMenuName = NULL; // ウィンドウメニュー
wc.lpszClassName = TEXT("Windows"); // ウィンドウクラス名
if(!RegisterClass(&wc)) return 0;
// ウィンドウの作成
hWnd = CreateWindow(
wc.lpszClassName, // ウィンドウクラス名
TEXT("タイトル"), // ウィンドウタイトル
WS_OVERLAPPEDWINDOW, // ウィンドウスタイル
300, // 表示X座標
200, // 表示Y座標
640, // 幅
480, // 高さ
NULL, // 親ウィンドウ
NULL, // ウィンドウメニュー
hInstance, // インスタンスハンドル
NULL); // WM_CREATE情報
// ウィンドウの表示
ShowWindow(hWnd, nCmdShow); // 表示状態の設定
UpdateWindow(hWnd); // クライアント領域の更新
hInst = hInstance;
hDC_Wnd = GetDC(hWnd);
ReleaseDC(hWnd,hDC_Wnd);
MessageBox(hWnd, TEXT("OKボタンで終了"),TEXT("動作テスト"),MB_OK);
return 0; // とりあえず0を返す
}
//==============================================================================================
// ウィンドウプロシージャ
//==============================================================================================
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
switch(msg){
case WM_DESTROY: // ウィンドウが破棄されたときの処理
PostQuitMessage(0); // 終了メッセージ
return 0;
default: // デフォルト処理
return DefWindowProc(hWnd, msg, wParam, lParam);
}
}
--------------------------------------------------------------------------------------------------
1,105ポイント を手に入れた。
|
|
|
|
Name: pupil、 ..ぴよぴよ(510ポイント)
Date: 2008/12/13(土) 17:27
No:25622
|
|
Title: 移動判定について
|
|
皆様、始めまして。
今、キャラクターをスタート地点からゴール地点まで移動させると言う
ゲームを作ろうと考えているのですが、どう考えても解決できない部分
があるのでお力を貸して下さい。
MAPの壁の判定なのですが、1マスに上下左右の壁の情報を入れたいと思
っています。
ゲームプログラミングの館24を応用したいと考えているのですが;
int hantei[15][20] = {
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
{ 1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1 },
{ 1,1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1 },
{ 1,1,1,1,1,0,0,0,0,0,1,0,0,0,1,0,0,0,1,1 },
{ 1,1,1,1,1,0,0,0,1,1,1,0,0,0,1,0,0,0,1,1 },
{ 1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1 },
{ 1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
};
int can_or_cannot(int x,int y,int muki){//進めるかを判定する
if(muki==0)//上向きなら
if(hantei[y/32-1][x/32]==1)//進めるか判定
return 1;//エラー
if(muki==1)//左向きなら
if(hantei[y/32][x/32-1]==1)
return 1;
if(muki==2)//下向きなら
if(hantei[y/32+1][x/32]==1)
return 1;
if(muki==3)//右向きなら
if(hantei[y/32][x/32+1]==1)
return 1;
return 0;//正常
}
コレを工夫して1マスに壁の上下左右の情報を入れるにはどうすればいいでしょうか?
1ならx+側とx-側が壁 2ならy-側とy+側が壁 と言うような感じです。
510ポイント を手に入れた。
|
|
|
|
Name: kazuoni [URL] ..熟練のプログラマー(41,622ポイント)
Date: 2008/12/13(土) 18:57
No:25624
|
|
Title: Re:移動判定について
|
|
もしマップチップを使用するなら
int hantei[15][20] = {
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
{ 1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,1,1 },
{ 1,1,1,1,1,0,0,0,0,1,0,1,0,0,0,0,0,0,1,1 },
{ 1,1,1,1,1,0,0,0,0,1,0,1,0,0,0,0,0,0,1,1 },
{ 1,1,1,1,1,0,0,0,1,1,0,1,0,1,0,1,0,0,1,1 },
{ 1,1,1,1,1,0,0,0,0,0,0,1,0,1,0,1,0,0,1,1 },
{ 1,1,1,1,1,0,0,0,1,1,1,1,0,1,0,1,0,0,1,1 },
{ 1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
};
ですかね。
まあマップが狭くなっちゃいますが。。
でも障害のチップにキャラがめり込んでしまったら元も子もないと思いますし^^;
もし線で道を書くつもりならちょっと工夫が必要ですね。
まず2^4=16パターンの数字を用意します。
0=全部通れる
1=全部通れない
2=上だけ通れない
3=右だけ通れない
...
次に
can_or_cannot(int x,int y,int muki)
でif文条件にそれぞれの数字の時に通行不可の条件を加えればよいです。
理論上はこんな感じですけど、結構大変そうですね。。
773ポイント を手に入れた。
|
|
|
|
|
Name: lbfuvab ..中級者(11,382ポイント)
Date: 2008/12/13(土) 19:00
No:25625
|
|
Title: Re:移動判定について
|
|
進む事のできる方向を
#define UP 0x1
#define DOWN 0x2
#define RIGHT 0x4
#define LEFT 0x8
と定義し判定時は
if(hantei[x][y] & UP){
//処理
}
などとする方法はどうでしょうか?
34ポイント を手に入れた。
|
|
|
|
|
Name: non ..上級者(21,874ポイント)
Date: 2008/12/13(土) 19:12
No:25627
|
|
Title: Re:移動判定について
|
|
>コレを工夫して1マスに壁の上下左右の情報を入れるにはどうすればいいでしょうか?
>1ならx+側とx-側が壁 2ならy-側とy+側が壁 と言うような感じです。
質問です。
添付は、自分がいる場所の上下左右の座標のデータが1なら壁(進めない)という情報ですが、
pupilさんが目指しているのは、薄い壁といういうイメージだと考えていいのでしょうか?
例えばマイクロマウスの壁のように隣のブロックも通れる通路ではあるけど、間に壁があるような。
だとすれば、
方法1、ビットをうまく使う。
上 右 下 左
b3 b2 b1 b0 を上下左右の状態として入れる。
0 0 0 0 (10進0)なら上下左右とも進める
0 1 1 0 (10進6)なら右と下は壁
方法2 構造体を使う
static KABE{
int up;
int right;
int down;
int left;
}
などの方法があります。
382ポイント を手に入れた。
|
|
|
|
|
Name: pupil、 ..ぴよぴよ(899ポイント)
Date: 2008/12/13(土) 20:16
No:25631
|
|
Title: Re:移動判定について
|
|
>kazuoniさん
なるほど〜確かに0〜順にif分で分岐すれば何とかなりそうですが^^;
数が多くてわかりにくくなりますよね〜
>lbfuvabさん
なるほど〜定義と言う数学的な方法も使えるのですね〜
えと、1が上で2が下なら、3が上下壁って事なのでしょうか?
いやはや、C言語の奥の深さには驚かされてばかりです;
>nonさん
>質問です。
>添付は、自分がいる場所の上下左右の座標のデータが1なら壁(進めない)という情報ですが、
>pupilさんが目指しているのは、薄い壁といういうイメージだと考えていいのでしょうか?
ですです。すみません、テンプはゲーム館からコピペした物なので;
確か2年ほど前に情報Aの授業でbitの話が出てきましたが、
何でそんなややこしいもん使うねん!とスルーした記憶が
あります。あぁ、今から思えばもう少し理解を深めておけ
ばよかったですね。でも、何とか理解しました。
方法2の構造体の話なのですが、イマイチイメージが沸きません;
もう少し詳しく書いてはいただけ無いでしょうか?
すみません、環境書くの忘れてました;
OS WindowsVista
コンパイラ Visual C++ 9.0
C暦 1ヶ月
ツクール買ってゲーム作るのももったい無いかな〜とおもっていろいろ
探していたらこのサイトに出会いました。この掲示板は解答が早いんですね〜
ものすごくびっくりしました。今回は丁寧な解答ありがとうございました。
また困ったら助けてください。よろしくお願いします。
389ポイント を手に入れた。
|
|
|
|
|
Name: non ..上級者(21,678ポイント)
Date: 2008/12/13(土) 21:36
No:25632
|
|
Title: Re:移動判定について
|
|
添付プログラムと同じように書けばこうなります。
static KABE{
int up;
int right;
int down;
int left;
};
static KABE hantei[15][20]={{1,1,1,1},{1,1,0,1}・・・以下略
int can_or_cannot(int x,int y,int muki){//進めるかを判定する
if(muki==0)//上向きなら
if(hantei[y][x].up==1)//進めるか判定
return 1;//エラー
if(muki==1)//左向きなら
if(hantei[y][x].left==1)
return 1;
以下略
初期値を与えるのが、やや面倒ですね。一つの座標につき、4つ入力が必要です。
207ポイント を落としてしまった。
|
|
|
|
|
Name: non ..上級者(22,281ポイント)
Date: 2008/12/13(土) 22:06
No:25633
|
|
Title: Re:移動判定について
|
|
データを与えるのが面倒そうなので、共有体を使ってみました。
union KABE{
unsigned char BYTE;
struct {
unsigned char up:1;
unsigned char right:1;
unsigned char down:1;
unsigned char left:1;
unsigned char work:4;
}BIT;
};
union KABE hantei[15][20]={15,11,・・・以下略
int can_or_cannot(int x,int y,int muki){//進めるかを判定する
if(muki==0)//上向きなら
if(hantei[y][x].BIT.up==1)//進めるか判定
return 1;//エラー
if(muki==1)//左向きなら
if(hantei[y][x].BIT.left==1)
return 1;
以下略
ただし、この方法の場合、どちらが上位ビットになるかは環境に依存しますので、
よく確認することが必要です。
共有体とは、同じ箱に2つの名前がつくようなものです。
ですから8ビットまとめて値を代入するときは
hantei[y][x].BYTE=0x06; //16進数で入力する場合
のようにすれば良く、
1ビット単位で参照するときは
hantei[y][x].BIT.left のように使います。
このときleftがBit0(最下位ビット)になるかは環境に依存しますので注意が必要です。
環境によってはBit7(最上位ビット)になることもあります。
unsigned char work:4;は8ビットになるように調整するためのものです。
603ポイント を手に入れた。
|
|
|
|
Name: うい ..かけだし(1,533ポイント)
Date: 2008/12/12(金) 00:05
No:25564
|
|
Title: .h
|
|
自分で新しく.hをつくり、それをほかのやつとおなじとこに入れてちゃんとincludesしているのですが、どうも反映されてないみたいです。
.hの内容は
#ifdef GLOBAL_INSTANCE
#define GLOBAL
#else
#define GLOBAL extern
#endif
#include "struct.h"
GLOBAL int black=(0,0,0);
これでほかの関数でblackという色を使おうとしているのですが
'black' : 定義されていない識別子です。
と出てしまいます。
135ポイント を手に入れた。
|
|
|
|
Name: うい ..かけだし(1,676ポイント)
Date: 2008/12/12(金) 00:35
No:25567
|
|
Title: Re:.h
|
|
今自分なりに対処したところ、上のようなエラーは消えましたが、次のようなエラーが出るようになってしまいました。
int black" (?black@@3HA) は既に main.obj で定義されています。
fatal error LNK1169: 1 つ以上の複数回定義されているシンボルが見つかりました。
どのように対処したらよろしいかアドバイスもらえるとうれしいです。
143ポイント を手に入れた。
|
|
|
|
|
Name: conio ..初心者(8,607ポイント)
Date: 2008/12/12(金) 00:52
No:25568
|
|
Title: Re:.h
|
|
エラーに書いてある通り、"black"が重複定義されているからだと思います。
現在はファイルがどうなっているのかは分かりませんが、
複数のファイルにまたがって、"black"の定義をしていませんか?
2倍のポイントを手に入れた! 98ポイント を手に入れた。
|
|
|
|
|
Name: うい ..かけだし(1,703ポイント)
Date: 2008/12/12(金) 00:56
No:25569
|
|
Title: Re:.h
|
|
そうならないように
#ifdef GLOBAL_INSTANCE
#define GLOBAL
#else
#define GLOBAL extern
#endif
で場合分けし、mainのときにはちゃんと
#define GLOBAL_INSTANCE
とやっていて、他ではこれをしていないので、重複している原因がわからないです。
27ポイント を手に入れた。
|
|
|
|
|
Name: YuO ..プログラマー(25,911ポイント)
Date: 2008/12/12(金) 03:10
No:25570
|
|
Title: Re:.h
|
|
> とやっていて、他ではこれをしていないので、重複している原因がわからないです。
せっかくこうやっても,定義をしてしまっているからです。
> GLOBAL int black=(0,0,0);
が
extern int black=(0,0,0);
と展開されたとしても,初期化子があるので宣言ではなく定義になります。
76ポイント を手に入れた。
|
|
|
|
|
Name: 初級者 ..入門者(3,046ポイント)
Date: 2008/12/12(金) 07:34
No:25571
|
|
Title: Re:.h
|
|
そもそも
black=(0,0,0)
という初期化はできるのでしょうか?
文法と合っていないように見えます。
38ポイント を手に入れた。
|
|
|
|
|
Name: 初級者 ..入門者(3,075ポイント)
Date: 2008/12/12(金) 08:05
No:25573
|
|
Title: Re:.h
|
|
あ、そうでした。
まあ、仮にRGBの初期化をしたいのだとすると、
正しくないことには変わりないのですけれど。
29ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) [URL] ..伝説なるハッカー(922,031ポイント)
Date: 2008/12/12(金) 13:57
No:25579
|
|
Title: Re:.h
|
|
blackにはGetColor(0,0,0)みたいなものが入れたかったんですかね?
頑張ったら以下のように宣言と同時に格納することもできますが、
初期化や初期設定をする為の関数を作った方がいいと思います。
ちなみに0なら自動的に入るので入れる必要はないです。
(例)
#ifdef GLOBAL_INSTANCE
#define GLOBAL
#define GLOBAL_VAL(v) =(v)
#define GLOBAL_ARR2(a,b) ={a,b}
#else
#define GLOBAL extern
#define GLOBAL_VAL(v)
#define GLOBAL_ARR2(a,b)
#endif
GLOBAL int black GLOBAL_VAL(1);//1を格納
GLOBAL int color[2] GLOBAL_ARR2(2,3);//[0]に2,[1]に3を格納
173ポイント を手に入れた。
|
|
|
|
|
Name: ななし ..かけだし(1,377ポイント)
Date: 2008/12/13(土) 14:07
No:25619
|
|
Title: Re:.h
|
|
main では、ちゃんとヘッダをインクルードする前に GLOBAL_INSTANCE を定義していますか?
他のファイルをインクルードした際にそのヘッダをインクルードしている可能性もあるので、main のファイルの先頭で GLOBAL_INSTANCE を定義した方が良さそうです。
69ポイント を手に入れた。
|
|
|
|
Name: 桃印 ..かけだし(1,387ポイント)
Date: 2008/12/10(水) 22:26
No:25521
|
|
Title: 円と矩形の当たり判定について
|
|
はじめまして、桃印と申します。
こちらの講座を参考にしつつシューティングゲームを製作しているのですが、
円と矩形(四角)の当たり判定を製作する部分で行き詰ってしまいました。
矩形が傾いていない時の判定は出来るのですが、矩形が傾いていた場合の判定計算の方法がわからないのです。
そこで過去ログを探っていたところ、管理人様がこちら(http://www.play21.jp/board/formz.cgi?action=res&resno=24537&page=&lognum=77&id=dixq&rln=24727)で分かりやすい判定方法を提示なさっていました。
分からないながらも自分なりに考えたところ、円から伸ばした十字(それぞれ四角の縦横に平行なもの)と四角から伸ばした十字(X軸Y軸に対してθ分だけ傾いたもの)との交点二点の座標を求め、そのそれぞれ二つと四角の中心の距離を求め、その長さがともに「円の判定の長さ+縦(または横)の判定の長さ」より小さければ当たりである、という処理を行えば良いと思いました。
しかし実際にプログラムへと落とし込んでみたところ、問題の十字同士の交点の座標を算出する方法がわかりません。
どなたか考え方なりヒントだけでも教えていただけないでしょうか。よろしくおねがいします。
一応、当たり判定を考える上で使っているプログラムのソースも載せておきます。
キーボード入力で円(当たり判定)が動きます。読み込んでいる画像は50×15ピクセルの塗りつぶしの四角です。
環境:WindowsXP VC++ 2008EE DXライブラリ
#include "DxLib.h"
#include "math.h"
#define PI 3.1415926535898
char Key[256];
int KeyBuf;
int image;
int hit=0;
double cx=200, cy=200;
double ex_cx=0, ex_cy=0;
double c_range=10;
double ex=640/2, ey=480/2;
double tate=25, yoko=15;
double ANGLE=0*(PI/180);//傾けたい角度
double x[4],y[4];//四角形の頂点四つの座標
double kyori[4],kyori_x,kyori_y;//当たり判定と比べる距離
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //初期化処理
SetDrawScreen( DX_SCREEN_BACK ); //描画先を裏画面に設定
SetDrawBlendMode( DX_BLENDMODE_ADD , 256 ) ;//これは気にしなくていい。
while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
//↑メッセージ処理 ↑画面をクリア ↑キーボード入力状態取得 ↑ESCが押されると終了
// キー入力取得
KeyBuf = GetJoypadInputState( DX_INPUT_KEY_PAD1 ) ;
// 上を押していたら上に進む
if( KeyBuf & PAD_INPUT_UP ) cy -= 1 ;
// 下を押していたら下に進む
if( KeyBuf & PAD_INPUT_DOWN ) cy += 1 ;
// 右を押していたら右に進む
if( KeyBuf & PAD_INPUT_RIGHT ) cx += 1 ;
// 左を押していたら左に進む
if( KeyBuf & PAD_INPUT_LEFT ) cx -= 1 ;
image=LoadGraph("1.png");//30×50の画像
x[0]=(ex-yoko);//左上
y[0]=(ey-tate);
x[1]=(ex+yoko);//右上
y[1]=(ey-tate);
x[2]=(ex-yoko);//左下
y[2]=(ey+tate);
x[3]=(ex+yoko);//右下
y[3]=(ey+tate);
//円と四角の四点
int i;
for(i=0; i<4; i++){
kyori[i]=sqrt((cx-x[i])*(cx-x[i])+(cy-y[i])*(cy-y[i]));
if(kyori[i]<=c_range)
hit=1;
}
//ここから
double point_x[2], point_y[2];
point_x[0]=;//???
point_y[0]=;//???
point_x[1]=;//???
point_y[1]=;//???
kyori_y=sqrt((cx-point_x[0])*(cx-point_x[0])+(cy-point_y[0])*(cy-point_y[0]));
kyori_x=sqrt((cx-point_x[1])*(cx-point_x[1])+(cy-point_y[1])*(cy-point_y[1]));
//ここまで
if(kyori_x=c_range+yoko && kyori_y<=c_range+tate)
hit=1;
DrawCircle(cx,cy,c_range,GetColor(255,255,255), TRUE);//円形当たり判定(自機)
DrawRotaGraphF(ex,ey,1.0,ANGLE,image,true);//矩形当たり判定(敵機)
if(hit==1){
DrawString( 0,0,"○接触しています!!○",GetColor(255,255,0));
hit=0;
}
else
DrawString(300,0,"×接触していません。×",GetColor(255,255,0));
ScreenFlip();
}
DxLib_End();
return 0;
}
1,387ポイント を手に入れた。
|
|
|
|
Name: Libra ..かけだし(1,677ポイント)
Date: 2008/12/11(木) 00:04
No:25524
|
|
Title: Re:円と矩形の当たり判定について
|
|
簡単に考えてみた感じですが
θ'-θを行い、θ''を出す。
(矩形の中心座標から円の中心座標の距離)×cos or sin(θ'')・・・この距離をA、Bとする
Aは円の中心から(point_x[1],point_y[1])の距離を指します。
Bは円の中心から(point_x[0],point_y[0])の距離を指します
また、矩形の中心からpoint_x[0],point_y[0]の角度は『θ+90度』なので
矩形の中心座標(x,y)+ A or B ×cos or sin(θ+90度)
で交点座標が出ると思うのですが、どうでしょう?
2倍のポイントを手に入れた! 250ポイント を手に入れた。
|
|
|
|
|
Name: Sleepy ..入門者(2,763ポイント)
Date: 2008/12/11(木) 00:30
No:25528
|
|
Title: Re:円と矩形の当たり判定について
|
|
傾いていなければ判定できるのであれば、
傾いていない状態に座標変換して判定すれば良いのでは?
46ポイント を手に入れた。
|
|
|
|
|
Name: 桃印 ..かけだし(2,225ポイント)
Date: 2008/12/11(木) 01:23
No:25530
|
|
Title: Re:円と矩形の当たり判定について
|
|
>Libra様
素早い回答ありがとうございます!
なるほど、AとBの長さを算出するまでは自分でも思いついていたのですが、
さらにそこからsin cosをかけてから矩形の座標に足すんですね。
中学数学レベルですが、すっかり失念していました。
早速プログラムに組み込んで、実際に判定できるのか実験してみた結果、
確かに当たり判定を取ることが出来ました。
――が、しかしここでまた一つの問題が。
私のプログラム方法が悪かったのか、どうやら当たり判定を取る際に
円の無効部分でも当たりと判定してしまうという結果が出ました。
どうやら円と矩形ではなく、矩形同士の判定になってしまっているようです。
以下が判定部分のプログラムになります。上のソースの//ここから 〜 //ここまでの部分です。
効率化は後回しにしているので、かなり回りくどいですが;
double point_x[2], point_y[2], ANGLE2, range2, A, B;
range2=sqrt((cx-ex)*(cx-ex)+(cy-ey)*(cy-ey));//円の中心と矩形の中心の距離
ANGLE2=atan2(cy-ey,cx-ex);//θ'-θ
A=range2*cos(ANGLE2-ANGLE);
B=range2*sin(ANGLE2-ANGLE);
point_x[0]=ex+B*cos(ANGLE+(90*(PI/180)));
point_y[0]=ey+B*sin(ANGLE+(90*(PI/180)));
point_x[1]=ex+A*cos(ANGLE);
point_y[1]=ey+A*sin(ANGLE);
kyori_x=abs(sqrt((ex-point_x[1])*(ex-point_x[1])+(ey-point_y[1])*(ey-point_y[1])));
kyori_y=abs(sqrt((ex-point_x[0])*(ex-point_x[0])+(point_y[0]-ey)*(point_y[0]-ey)));
うーん、どこがおかしいんでしょう。それとも計算後の判断式
if(kyori_x<=c_range+yoko && kyori_y<=c_range+tate)
がおかしいのでしょうか。
>Sleepy様
回答ありがとうございます!
その通りです。そのために上で述べた「十字の交点部分の座標」を出したいのですけど、
恥ずかしい話ですがその計算方法が思いつきませんで。
こうして質問させていただいた次第です。
838ポイント を手に入れた。
|
|
|
|
|
Name: Libra ..入門者(2,533ポイント)
Date: 2008/12/11(木) 02:28
No:25532
|
|
Title: Re:円と矩形の当たり判定について
|
|
自分もシューティングで円と矩形の判定を考えているので、参考にさせていただきました。
矩形と円の当たり判定は図のような形になると考えてます。
図の灰色より内側が当たり判定。
今回矩形と矩形の判定になってしまったのは、図の紫の部分の当たり判定を抜いてないためだと考えられます。
自分なりの方法で:
図の紫の部分を抜くには、各頂点で図のA、Bのような座標を取り、角度A〜Bを求めます。
角度AとBを出した後、大きい方と小さい方をソートしておく。A<Bとなるように。
頂点から円の中心までの角度が角度A〜Bに入っている時、頂点からの距離が円の半径より大きいの時が当たり判定の無い部分となるので、この範囲に円の半径が入っている時当たり判定から外してやればいいと思います。
また、A、Bの出し方ですが、スレ主の最初の図より、
A:矩形の中心座標(x,y)+(矩形の縦方向の辺の長さの半分+円の半径)×cos or sin(θ)+矩形の半分の長さ×cos or sin(θ+90度)
B:矩形の中心座標(x,y)+(矩形の縦方向の辺の長さの半分+円の半径)×cos or sin(θ+90度)+矩形の半分の長さ×cos or sin(θ)
をやれば求められると予想してます。
またatan2関数を使う時の返り値は-π〜πなので角度A〜Bの範囲がatan2関数の角度の範囲より小さくなってしまったり大きくなってしまう場合は、また新たに条件式が必要になると思います。
この方法で上手くいくのであれば、2段階の計算だけで円と矩形の当たり判定が出来るので、結構短いソース量で当たり判定ができるのではないでしょうか?
2倍のポイントを手に入れた! 856ポイント を手に入れた。
|
|
|
|
|
Name: 桃印 ..かけだし(2,382ポイント)
Date: 2008/12/11(木) 17:47
No:25554
|
|
Title: Re:円と矩形の当たり判定について
|
|
なるほど、四角側の当たり判定の有効領域を考えたらよいのですね。
自分なりに解釈してみたところ、角部分の座標と円の中心の角度を求め、その角度-矩形の傾きで出した角度が、
0〜90度+θの場合(角の箇所によって範囲は変わる?)であれば上で作った当たり判定処理を実行。
無効だった場合は角部分の座標と円の中心の距離を求め、その距離がrangeだった場合は当たり、そうでなければ当たっていない処理を返すということだと理解しました。
しかしそのためには角の座標が分かっていないといけないのですが、
θ分だけ傾いている場合のそれぞれの角の座標の計算方法が分かりません。
単純にxにcosθ、yにsinθ+90をかけただけでは出ないみたいですし(傾きは矩形の中心からの数値なので)。
初歩的な数学だとは思うのですが、どうも思いつきません。
どなたか計算方法を教えていただけないでしょうか。
157ポイント を手に入れた。
|
|
|
|
|
Name: 柏 ..上級者(17,920ポイント)
Date: 2008/12/11(木) 18:06
No:25555
|
|
Title: Re:円と矩形の当たり判定について
|
|
こんばんは。
いつも質問させてもらっている者ですが、
回答者側に回るのは初めてなのでおかしな点があるかもしれませんが、参考までに。
まず、桃印さんの書いたプログラムですが、計算部分はほぼ全てあっており、予想されている通り判断式が違います。
大雑把に言えば判断式だけ誤っていますので、そこだけ変えれば一応判定は取れるようになります。
それと後のレスでは修正されていますが、一番最初に書いたソースの判断式のところで、
if(kyori_x=c_range+yoko && kyori_y<=c_range+tate)
となっていたので、一応確認してみてください。
また、最初に画像は50×15ピクセルと書いてありますが、プログラムソース中では30×50の画像というコメントがありますので、もう一度画像のサイズを確認してみるのもいいかもしれません。
DXライブラリのGetGraphSize関数で画像サイズを取得すれば一番確実ではありますが。
なお、この判定が取れるようになった事が確認出来たあとは、最初に行っている四角形の4頂点との当たり判定は無くても大丈夫なはずです。というよりも4頂点の位置が傾きに対応していないため、この状態で傾けると判定の妨げになる可能性があります。
一応こんな感じです。
確認はしましたが、間違っていたらごめんなさいm(__)m
追記:
すいません、画像を見た限りでは30×50ですね。
それなら、4頂点との当たり判定部分を無くすだけで少しマシになるはずです。
もっと厳密に判定する場合は、私にはちょっと今の所分かりません^^;
・参考画像
http://www1.axfc.net/uploader/Img/link.pl?dr=7651900951&file=Img_28291.png
http://www1.axfc.net/uploader/Img/link.pl?dr=4993907147&file=Img_28292.png
542ポイント を手に入れた。
|
|
|
|
|
Name: 桃印 ..入門者(2,690ポイント)
Date: 2008/12/11(木) 19:00
No:25556
|
|
Title: Re:円と矩形の当たり判定について
|
|
柏様、回答ありがとうございます!
画像のサイズは私のミスです、申し訳ありません。正しくは30×50です。
また、確かに4点との距離を求める部分は不要ですね。
この点が傾きに対応できるよう、四点が傾いたときの座標の算出方法が知りたいのですが、なかなか考えつきません;
判断式部分がおかしいとのことですが、私の書いた判断式では「矩形同士の判定」になっているものを、修正することで「円と矩形の判定」にすることができるということでしょうか? その場合はどのような式で判断させたら良いのでしょうか。上手く円形の部分を削れるような式、全く思いつきません……;;
これが分かれば、かなり短い式で円と矩形の判定ができるのですが……もうちょっと考えて見ます。
308ポイント を手に入れた。
|
|
|
|
|
Name: 柏 ..上級者(17,235ポイント)
Date: 2008/12/11(木) 21:39
No:25558
|
|
Title: Re:円と矩形の当たり判定について
|
|
前回の私のレスで、追記部分を書いたせいでごちゃごちゃになってしまいましたので、まずは一旦前回のレスの内容を以下に整理します。
まず、円と矩形の当たり判定(傾きも考慮する)については桃印さんが書かれたプログラムソースから、
int i;
for(i=0; i<4; i++){
kyori[i]=sqrt((cx-x[i])*(cx-x[i])+(cy-y[i])*(cy-y[i]));
if(kyori[i]<=c_range)
hit=1;
}
の部分を削除するだけで円と4頂点及び4辺の当たり判定がほぼ正確に(前回の私のレスにある画像程度)とれます。
……と思います。
確認はしたのですが、
それが桃印さんの想定されている判定と合っているかどうかがちょっと自信がないので^^;
とりあえず試しにANGLEを変え、傾いていても当たり判定が取れている事を確認してみてください。
前回のレスでは画像のサイズを勘違いしていたため判断式が違うという指摘をしてしまい、
その後気づき追記を書いた、という流れですが、
追記以前の文章を削除なりしておけばよかったのですが……混乱させてしまって申し訳ないですm(__)m
ここまでが前回のレスのまとめですが、この点は恐らく理解されていると思いますが、一応ということで。。。
で、ここからが本題の「傾きにも対応した4頂点の座標」の求め方です。
とりあえず右上の点だけを考えてみることにします。
まず、この四角形はPI、つまり0°〜180°の間で傾きます。
0°〜180°の間で回転すると思ってもらっても大丈夫です。
四角形が回転すると、右上の座標も当然一緒に回転します。
回転するということは、その回転する為の中心座標が存在することになりますが、
この場合は四角形の中心、つまり(ex,ey)です。
右上は(ex,ey)を中心にして回転している事になります。
どこを中心にして回転しているかが分かれば、次に求めるのは、
その点(この場合は右上)は中心からどの角度でどれだけの大きさ(長さ)の位置にあるのかを求める事になります。
まずは中心と右上の角度を求めましょう。
例えば、これはatan2関数で求めればいい事が分かると思います。
次は中心からどれだけの大きさ(長さ)の位置にあるかです。
例えば、これは三平方の定理(ピタゴラスの定理)を使って求めることが出来ます。
角度、大きさが求まりましたので、これで中心から見た右上の座標が求められるはずです。
ヒントとしては、、、
x[1] = ex + cos(?) * ?;
y[1] = ey + sin(?) * ?;
という感じです。
まとめると、
1.回転の中心座標(ex,ey)と右上の角度を求める。
2.回転の中心座標(ex,ey)と右上の大きさ(長さ)を求める。
3.上記のヒントと合わせながら、求めた値をどう使えば良いか考える。
です。
ちなみに変数ANGLEも当然上記の式のどこかに入れなければいけません。
これはあくまでも一例であり、他にいくらでも簡単なやり方はあると思いますのでその点ご注意ください。
桃印さんのやりたい事と私の解釈にもしかしたらズレがあるかもしれませんが、
少しでも参考になれば幸いです。
685ポイント を落としてしまった。
|
|
|
|
|
Name: 桃印 ..かけだし(2,265ポイント)
Date: 2008/12/12(金) 00:27
No:25566
| 解決!
|
Title: Re:円と矩形の当たり判定について
|
|
>柏様
回答ありがとうございます。
私のミスで混乱させてしまってすいません;
そして本題の「傾きにも対応した4頂点の座標」ですが、
柏様のヒントと照らし合わせて試行錯誤してみたところ、
なんとか完成できました!
//傾きに対応している頂点四つ
x[0]=ex-kyori[0]*cos(ANGLE+atan2(tate,yoko));//左上
y[0]=ey-kyori[0]*sin(ANGLE+atan2(tate,yoko));
x[1]=ex+kyori[1]*cos(-ANGLE+atan2(tate,yoko));//右上
y[1]=ey-kyori[1]*sin(-ANGLE+atan2(tate,yoko));
x[2]=ex-kyori[2]*cos(-ANGLE+atan2(tate,yoko));//左下
y[2]=ey+kyori[2]*sin(-ANGLE+atan2(tate,yoko));
x[3]=ex+kyori[3]*cos(ANGLE+atan2(tate,yoko));//右下
y[3]=ey+kyori[3]*sin(ANGLE+atan2(tate,yoko));
kyori[0~1]はそれぞれの点と円の中心の大きさ(長さ)です。
これで与えた座標と円の中心の距離を求めることで、当たりの判定処理を行いました。
ANGLEを適当なフレームごとに回転させて実験してみたところ、ばっちり当たり判定を取ることが出来ました!
後は円の中心が無効部分でない場合の時に、上で作ったプログラムを実行させたら矩形と円形の当たり判定の完成です。
>Sleepy様
回答ありがとうございます。
すいません、もっと詳しく検索しておくべきでした……。
テーブル化とのことですが、確かに今回完成させたプログラムの計算方法は負担の大きい、処理の重いものであることは間違いないので、Sleepy様のお言葉通り軽量化してみたいと思います。
さて、判定処理の計算部分は完成しましたので、これで一応の解決とさせていただきます。
Libra様、Sleepy様、柏様、ご助力ありがとうございました!
425ポイント を落としてしまった。
|
|
|
|
|
Name: 桃印 ..かけだし(2,337ポイント)
Date: 2008/12/12(金) 16:23
No:25585
|
|
Title: Re:円と矩形の当たり判定について
|
|
御津凪様、回答ありがとうございます!
そもそも今回の判定方法を使うことになったのは、
恥ずかしい話ですが私がベクトルや内積・外積を理解できなかったからなんです。
公式や解説を見ても、それをプログラムへと落とし込む方法がいまいち分からない。
ただ逃げてばっかりでは勉強にならないので、いつかまたリベンジするつもりです。
72ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) ..伝説なるハッカー(922,860ポイント)
Date: 2008/12/12(金) 16:56
No:25586
|
|
Title: Re:円と矩形の当たり判定について
|
|
円と四角形の当たり判定について、ま〜くさんとK様にご指導いただきました。
その方法を以下に紹介します。
(それぞれの条件は独立したものじゃないので、あわせてご覧下さい)
これをプログラムで実装したのが
// 四角形(p1-p2, width)と円(pt, r)の当たり判定
// p1x : 四角形中心線分の始点x
// p1y : 四角形中心線分の始点y
// p2x : 四角形中心線分の終点x
// p2y : 四角形中心線分の終点y
// width : 四角形の幅
// px : 円の中心x
// py : 円の中心y
// radius : 円の半径
bool
hittest (double p1x, double p1y, double p2x, double p2y,
double width,
double px, double py,
double radius)
{
double l = sqrt ((p2x - p1x) * (p2x - p1x) + (p2y - p1y) * (p2y - p1y)) / 2.0;
double w = width / 2.0;
double r = radius;
double Pa = p2y - p1y;
double Pb = p1x - p2x;
double Pc = -Pa * p1x - Pb * p1y;
double cx = (p1x + p2x) / 2.0;
double cy = (p1y + p2y) / 2.0;
double Qa = -Pb;
double Qb = Pa;
double Qc = Pb * cx - Pa * cy;
double lp = fabs (Pa * px + Pb * py + Pc) / sqrt (Pa * Pa + Pb * Pb);
double lq = fabs (Qa * px + Qb * py + Qc) / sqrt (Qa * Qa + Qb * Qb);
return (lp <= w && lq <= l
|| (lp <= w + r && lq <= l + r
&& (lq <= l
|| lp <= w
|| (lp - w) * (lp - w) + (lq - l) * (lq - l) <= r * r)));
}
です。
PDFファイルをキャプチャした式を見ると若干複雑に見えるものの、
プログラムで表現するとすごく簡単に計算出来てしまうようです。
後はsqrtを使わずに計算できるように式を変更すれば高速で計算出来る関数になると思います。
ご指導下さったま〜くさん、K様、本当にありがとうございますm(_ _)m
(矩形→四角形 に修正しました)
610ポイント を手に入れた。
|
|
|
|
|
Name: ななし ..かけだし(1,308ポイント)
Date: 2008/12/12(金) 21:07
No:25603
|
|
Title: Re:円と矩形の当たり判定について
|
|
円と矩形の当たり判定なら、円の中心から矩形の一番近い場所への長さを求めて、それが円の半径より大きいかどうかを判断するだけですね。
// 点 p と 矩形 r の間の距離の平方を計算する
double SquareDistance_PointRectangle(
double px, double py,
double rx, double ry, double rw, double rh)
{
double sqDist = 0.0;
if (px < rx) sqDist += (rx - px) * (rx - px);
if (px > rx + rw) sqDist += (px - rx - rw) * (px - rx - rw);
if (py < ry) sqDist += (ry - py) * (ry - py);
if (py > ry + rh) sqDist += (py - ry - rh) * (py - ry - rh);
return sqDist;
}
bool TestCircleRectangle(
double cx, double cy, double cr,
double rx, double ry, double rw, double rh)
{
// 円の中心と矩形 r の間の距離の平方を計算
double sqDist = SquareDistance_PointRectangle(cx, cy, rx, ry, rw, rh);
// 円と矩形 r が交差するのは、それらの間の平方した距離が
// 平方した円の半径よりも小さい場合
return sqDist <= cr * cr;
}
↑は「ゲームプログラミングのためのリアルタイム衝突判定」にあるソースを少し書き換えただけです。
こんな感じで書けば動作するのではないでしょうか。
2倍のポイントを手に入れた! 928ポイント を手に入れた。
|
|
|
|
|
Name: 桃印 ..かけだし(2,442ポイント)
Date: 2008/12/12(金) 22:56
No:25605
|
|
Title: Re:円と矩形の当たり判定について
|
|
管理人様、名無し様、回答ありがとうございます!
どちらのソースでも「円と矩形の判定処理」の正常動作を確認しました。
どちらもスマートなプログラムで感動しました!
傾いた場合に対応させる方法は、自分なりに考えてみようと思います。
ありがとうございました〜。
105ポイント を手に入れた。
|
|
|
|
|
Name: ま〜く ..初心者(8,365ポイント)
Date: 2008/12/12(金) 23:49
No:25608
|
|
Title: Re:円と矩形の当たり判定について
|
|
桃印さん
管理人さんが貼り付けたものは傾きに対応していますよ^^
線分(レーザーの始点と終点)の座標が変わることにより、傾いた四角形となります。
タイトルでは「矩形」とあり、矩形とは傾きなし(上、左、下、右辺)を意味する四角形
の場合が多い?ので、正確には、「円と四角形の当たり判定」というべきでしょうね^^;
65ポイント を手に入れた。
|
|
|
|
|
Name: 桃印 ..入門者(2,858ポイント)
Date: 2008/12/13(土) 00:33
No:25610
|
|
Title: Re:円と矩形の当たり判定について
|
|
ま〜く様、回答ありがとうございます!
すいません、確かに管理人様のソースは傾きにも対応してますね……理解したつもりで全然理解できてなかったみたいです;
また、矩形と四角形を誤解していたようでご迷惑をおかけしました。勉強が足りません;
一応管理人様のプログラムに
start_x=ex-yoko*cos(ANGLE);
start_y=ey-yoko*sin(ANGLE);
end_x=ex+yoko*cos(ANGLE);
end_y=ey+yoko*sin(ANGLE);
if(hittest(start_x, start_y, end_x, end_y, tate*2, cx, cy, c_range)==true)
hit=1;
こんな感じで当たり判定処理を渡してみました。
結果、数フレームごとに角度を変化させて実験してみても、ばっちり四角形と矩形の判定が取れました!
かなり分かりやすく、比較的少量でかつ簡単な判定方法で素晴らしいです。
独りで悩んでいるままでは絶対に分かりませんでした。皆様に相談して良かったです!
今度こそ、ありがとうございました〜。
416ポイント を手に入れた。
|
|
|
|
|
Name: Libra ..入門者(2,763ポイント)
Date: 2008/12/13(土) 04:03
No:25614
|
|
Title: Re:円と矩形の当たり判定について
|
|
矩形=長方形 なのでそのままでいいと思いますよ。『座標に対して角度の付いてる矩形の当たり判定』とか。
四角形だと台形とかも含んでしまうので。
以前、本屋にあるシューティングゲーム作成の本を3〜4冊程立ち読みしたのですが、当たり判定は円と円の判定しか記載されておらず、レーザーの当たり判定等も記載されてなかったです。
レーザーに関しては円の集合で作成し、当たり判定は円と円で行ってました。
さらに、言語がC++であったので、(Cのみの自分にとっては)本はほとんど参考にならなかったです。
自分も大変参考になりました、ありがとうございます。
230ポイント を手に入れた。
|
|
|
|
|
Name: 御津凪 [URL] ..熟練のプログラマー(45,364ポイント)
Date: 2008/12/12(金) 13:34
No:25577
|
|
Title: Re:アプリケーションのサイズについて
|
|
・デバッグ版はデバッグ情報を実行ファイルに入れる。
・プロジェクトのプロパティで、最適化に関する項目(ここではリリース版)に関係。
・DX ライブラリは マルチスレッド DLL (/MTd)で作成したライブラリで無いので、
ランタイムデータが実行プログラムに組み込まれる。
(強制的に /MTd でリンクしてしまえば小さくなるかも)
・C++ は例外関係及び型情報を持つようにコンパイルすると大きくなる。
等が上げられます。
特に、デバッグ版とリリース版の実行ファイルのサイズは大きく違います。
ランタイムライブラリを実行ファイルにリンクする方法では、使用している
ランタイムライブラリの数によって比例的に増加します。
ただし、ランタイム DLL として作成した実行ファイルは、
ランタイムライブラリのインストールをしていないと起動できません。
200ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) [URL] ..伝説なるハッカー(921,858ポイント)
Date: 2008/12/12(金) 13:34
No:25578
|
|
Title: Re:アプリケーションのサイズについて
|
|
VisualStudioですか?
ReleaseではなくDebugにしていませんか?
もしVisualStudioでしたら、メニューバー付近に「Debug」と表示されていると思うので「Release」に変更して下さい。
もし表示されていない時は「ビルド」>「構成マネージャー」からも変更できます。
自動変数の表示など、デバッグできなくなる代わりに、実行ファイルが軽くなります。実行速度も変わるようなので、配布時にはReleaseにするといいです。
後、Releaseにしたままでデバッグすると、自動変数に変な値が表示されるので、デバッグする時はDebugに戻してください。
239ポイント を手に入れた。
|
|
|
|
|
Name: kazuoni [URL] ..熟練のプログラマー(40,849ポイント)
Date: 2008/12/12(金) 20:13
No:25599
| 解決!
|
Title: Re:アプリケーションのサイズについて
|
|
御津凪さん、管理人さんご回答ありがとうございます^^
お二方のおっしゃる通りでした。。
今まで全く気にしたことがなかったので
デバッグ・リリースの全く違いを理解できていませんでした。
こんな性能のいいvisual C++がまだ使いこなせてません^^;
でもDebug機能はすごいですね。
学校で使ってるLinuxはこの機能がなく、
エラーと言えば「セグメンテーション違反」ですね^^;
最初のころはポインタで躓いていたので、
このエラー文字でどれだけ苦しんだことか・・・w
すみません。。話がそれました。
本当にありがとうございました。
またよろしくお願いします。
79ポイント を手に入れた。
|
|
|
|
|
Name: ようすけ ..入門者(2,809ポイント)
Date: 2008/12/10(水) 21:38
No:25518
|
|
Title: Re:マウスを使ったゲーム
|
|
管理人さんどうもです。
ズバリ、オリジナルです(*^_^*)
まぁ、似たようなゲームは探せばあるとは思いますが(笑)
本当は、食べ物を皿の上に置いた時に、置いた位置によって
得点を変えようと思ってました。
(皿の真ん中辺りなら1000点で、外に向かうにつれて得点を低くするとか・・)
あとは、タイムが残り10秒を切ったら敵の動きを早くするとか、クリアした時に、
残タイムを得点に加算するとか・・
マウスを使ったゲームを試しにつくって見たかっただけなんで、結局やめましたけどね(苦笑)
>昔やったマウスで操作する迷路を思い出しました。
迷路の中をマウスで進んでいくんですが、ポインタが壁に接触したらアウトって奴です。
そんなゲームあったんですか?
最初はそういう感じのゲームを作ろうと思ってました。危なかった(汗
371ポイント を手に入れた。
|
|
|
|
|
Name: ようすけ ..入門者(2,891ポイント)
Date: 2008/12/12(金) 19:19
No:25594
|
|
Title: Re:マウスを使ったゲーム
|
|
おもしろいと言われると嬉しいものです(*^_^*)
これからもちょくちょくゲーム作りはしていくつもりなので、
その時はまたこちらのサイトを利用させてもらいますので、
管理人さん&みなさん宜しくお願いいたしますね☆
82ポイント を手に入れた。
|
|
|
|
Name: 鹿好き ..ぴよぴよ(824ポイント)
Date: 2008/12/09(火) 19:28
No:25416
|
|
Title: 大きいサイズの配列(1次)について
|
|
2度目の質問になります
前回の質問で、お世話になった方々には重ねて御礼申し上げます。
さて今回の質問なのですが、javaで大きいサイズの配列(具体的にはx[50000]など)を扱っていたのですが、
C言語でおなじように大きいサイズの配列を扱おうとすると、コンパイルはできるのですが、
実行画面で途中でとまってしまいます。
とりあえず、例として簡単なプログラムを組んでみました。
#include <stdio.h>
void main(void)
{
int i;
double x[3500];
for(i=0;i<3500;i++)
{
x[i]=0.0;
printf("%5d\n",i);
}
}
このプログラムを実行すると3000あたりでとまりCPU使用率が100%になってしまいます。
これはPCスペックの問題なのか、コンパイラの問題なのか、それとも根本的にプログラムの書き方が間違ってるのか
もしくは単にC言語ではそこまでの大きさの配列は扱えないのか、はたまたそれ以外の理由なのか、
お答えいただければと思います。
(理想は可能ならdouble型の配列でサイズ[50000]くらいのを4つ扱いたいとおもっています、
なんだか無理っぽい気がひしひしとしてますが)
以下スペックその他になります。
OS ウインドウズXP
コンパイラ LSI C-86 試食版
PC VGC-H31B
メインメモリ 512MB
CPU インテル® Celeron® D プロセッサー 351 (3.20GHz)
C言語の能力 機械工学部生が基礎科目でとりあえず学んだ程度です。
510ポイント を手に入れた。
|
|
|
|
Name: box ..ハッカー(131,404ポイント)
Date: 2008/12/09(火) 19:52
No:25417
|
|
Title: Re:大きいサイズの配列(1次)について
|
|
>コンパイラ LSI C-86 試食版
CPU使用率の件はよくわかりませんが、
このコンパイラーは別のものに取り替えられる方がいいような気がします。
MS-DOS時代の16ビットコンパイラーを使い続けるメリットは
ほとんどないように思います。
double型で50000×4=200000個の領域を定義しようとすると、
おそらくコンパイル時にout of memoryあたりのエラーが出るのではないかと思います。
136ポイント を手に入れた。
|
|
|
|
|
Name: toyo ..上級者(20,875ポイント)
Date: 2008/12/10(水) 07:40
No:25458
|
|
Title: Re:大きいサイズの配列(1次)について
|
|
LSI-C試食版はスモールモデルと呼ばれるプログラムしか作成できません。
スモールモデルというのはポインタが2バイトのnearポインタと呼ばれるものだけになり64Kバイトのメモリしか扱えません。
ちなみにintも2バイトになります。
64Kバイトのプログラムですからスタック領域もかなり少なくなるためdouble(8バイト)を3500個を確保するのは無理でしょう。
もちろん他のコンパイラでもスタックは有限ですのでスタック内に確保できる数には制限があります。
大きいサイズの配列はスタック外に確保されるようにグローバルで宣言したりmalloc等で確保したほうがいいでしょう。
146ポイント を手に入れた。
|
|
|
|
|
Name: 鹿好き ..かけだし(1,390ポイント)
Date: 2008/12/12(金) 15:34
No:25583
| 解決!
|
Title: Re:大きいサイズの配列(1次)について
|
|
boxさま,Dixq (管理人)さま,toyoさまお早い回答ありがとうございます.
返信が遅くなって申し訳ありません.
VisualC++2008,インストールしてプログラムをコピペして実行してみましたところ解決しました!
(一応今後のことも考えて,グローバルで宣言しておきました,mallocはちょっと使い方が分からなかったので参考書と格闘してからになります)
やっぱりLSI-C試食版は古すぎたのですね,(VC++6.0というのもPCの片隅に入っていたのですが98年発売?らしい骨董品…,日本語と英語が入り混じってわけがわからなかったw)
とりあえずこれであとはカタカタとコードを書き込むだけです.
本当にありがとうございました.
2倍のポイントを手に入れた! 566ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) ..伝説なるハッカー(922,250ポイント)
Date: 2008/12/12(金) 15:50
No:25584
|
|
Title: Re:大きいサイズの配列(1次)について
|
|
専門ではないのに実験でプログラムを使う事になったりすると大変ですよね。
私の知り合いも、実験データを計算する為に、数百個ものデータを配列に手入力していました・・。
(ファイルから読めるということを知らなかったらしいです)
なので、もし「大変だな〜・・もっと簡単にプログラムで実現出来ないのかな」って事があればまた
気軽に聞いて下さいm(_ _)m
134ポイント を手に入れた。
|
|
|
|
Name: ざこ ..入門者(4,190ポイント)
Date: 2008/12/12(金) 13:13
No:25575
|
|
Title: 図形
|
|
VC++を使って図形を作図したいのですが今MFC使ってますが
LineToやArcなど整数しか扱えず小数部分は切捨てられると聞きました。
VC++を使う作図方法で浮動少数で作図する方法はありませんか?
74ポイント を手に入れた。
|
|
|
|
Name: YuO ..プログラマー(26,004ポイント)
Date: 2008/12/12(金) 14:24
No:25581
|
|
Title: Re:図形
|
|
GDI自体の座標は整数ですから,小数を扱うことは出来ません。
というか,なぜ小数を使いたいのですか?
内部処理に浮動小数点数が使えないわけではないのですが。
# どうせ画面表示上はピクセル単位という離散情報になるわけですし。
93ポイント を手に入れた。
|
|
|
|
Name: めーる ..ぴよぴよ(406ポイント)
Date: 2008/12/10(水) 11:04
No:25472
|
|
Title: ゲームプログラミング
|
|
少しずつプログラミングにも慣れてきたので、年末少し時間もあるのでゲームプログラミングに触れてみよう
と思います。今検討してるのはシューティングゲームの館で学んでから龍神録の方も見てみようかと思います。
少しおかしな質問ではございますが・・ゲームプログラミングの練習はプログラミングの向上に役立ちますか?
実際にプログラミング技術向上の為にゲームプログラミングを始められた方、どういうゲームを作ってみたのか
その感想、こういうのが身についたなどございましたら教えて下さい。
2倍のポイントを手に入れた! 356ポイント を手に入れた。
|
|
|
|
Name: Dixq (管理人) ..伝説なるハッカー(920,629ポイント)
Date: 2008/12/10(水) 11:23
No:25473
|
|
Title: Re:ゲームプログラミング
|
|
役立つと思いますよ。
どう学ぶ姿勢を持つかによってその成長度合いは様々だと思います。
「とりあえず知っている範囲で出来ることだけやる」というスタンスか
「あらゆるアルゴリズムをゲームを制作を通して学ぼう」
「方法1で実装出来たけど、方法2でも出来るかもしれないからそれも実装してみよう」というスタンスか
でも結構違ってくると思います。
(例1)
int e[10];
double a;
char name[32];
(とりあえずこれでも書けるけど、ひとまとまりの情報として扱いたいけどいい方法無いかな)
↓
(構造体を勉強してみよう)
(例2)
関数1(){
}
関数2(){
}
関数3(){
}
(似たような関数が沢山あるなぁ、これでも書けるけど、もっと効率的に呼べないかな?)
↓
(関数ポインタを勉強してみよう)
そんな感じですね。
「単にコンソール出力だけじゃどうしてもやる気が出ない」
そんな人にとっては基本的なアルゴリズムの勉強も、ゲーム制作を通して学ぶとより身に付き易いと思います。
プログラミングスキルの向上に役立つか・・といわれると、どこまでをその対称範囲としていいか悩みますが、
基本的なプログラミングスキル向上には大いに役立つと思います。
ある程度ちゃんとしたプログラムがかけるようになれば、後はどういう専門性を身に付けるか
例えば通信プログラムがかけるようになるとか、windowsプログラミングができるようになるとか、
DirectXやOpenGLが使えるようになるとか、になってくると思うので、その段階になったら
色んなライブラリを使ってみるとか、色んな関数が使えるようになるよう勉強していけば良いと思います。
私は最初の頃からゲーム作ってたので、他との違いはよくわかりませんが、
ゲーム制作をしないとわからなかっただろう事も知りました。
はじめたばかりの頃、コンソールプログラムしか書いてない頃、Sleep関数などの細かい誤差や
math.hの計算時間の長さ(といっても○万分の1秒程度)は意識することがありませんでしたが、
正確なフレームレート制御や1秒間に何十万回も行う高速計算処理が必要になってくると
それらの実際の時間を細かく測定してみたり、詳しく調べてみたりしました。
こういう事はなかなか必要に迫られないと詳しく調べないと思うので、ゲーム制作をしたからこそ
解っただろうこともあります。
逆にゲーム制作ばかりするから偏る知識もあるでしょう。
ですから色んな経験をすること、幅広く学ぶ事が大事だろうとは思います。
でも一番大事なのは「プログラミングが楽しいと感じる事」ですから、
ゲーム制作が好きならまずそちらばっかりやってもいいと思います。
好きこそものの上手なれという言葉があるとおり、好きなら上達も早いと思います。
勉強だと思ったら取れない時間も、趣味だと思えば自然に時間が取れるものだと思います。
はっきりいって勉強はそんなに好きじゃない私ですが、ゲーム制作するときは一日中こもってプログラム書いたりします。
やはり好きであることが一番大事だと思います。
序盤は効率や範囲を特に限定せずとにかく好きなことをやってみるに限ると思います。
ある程度わかってくれば足りない知識の分野や勉強方法もわかってくると思いますよ。
(あと、作った本人が言うのもなんですが、シューティングゲームの館はあまり参考にしない方がいいと思います・・・orz)
1,027ポイント を手に入れた。
|
|
|
|
|
Name: めーる ..ぴよぴよ(531ポイント)
Date: 2008/12/10(水) 11:29
No:25474
|
|
Title: Re:ゲームプログラミング
|
|
士気の面でゲームプログラミングを選んだのでその辺は大丈夫じゃないかなと。
>>あと、作った本人が言うのもなんですが、シューティングゲームの館はあまり参考にしない方がいいと思います
何故ですか?ちらっと見た程度ですがすごくわかりやすかった印象がありますが・・
125ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) ..伝説なるハッカー(921,080ポイント)
Date: 2008/12/10(水) 11:40
No:25475
|
|
Title: Re:ゲームプログラミング
|
|
「C言語歴1ヶ月でも出来る」と謳っているからには最低限の構文しか使うまいとしたせいで、
わざわざ非効率になっている部分もあり、
また私のスキルの低さゆえにわかりにくい構造、名前になっている部分があるのです。
(やってること意味不明な部分がいろいろとあります^^;)
まぁそれをいうと私の作ったサンプル全部ですがorz
また、龍神録を作ることで私自身色々わかったこともあり、新しい館の方が効率化されている箇所がいくつかあります。
それに、シューティングの館は中途半端で終わっているくせにあれ以上作る予定は無いですが、龍神録の館はある程度出来ていて、かつまだ作る予定があります。
そして四聖龍神録Plusとの互換性もありますし、質問された時に答え易いということもあります。
今から始めるのでしたら、わざわざ古いサイトをご覧頂かなくてもいいかな・・と思いました。
自分の中では既に消去したサイトだと思ってます・・。
(リンク外して抹消したいんですが、残して欲しいという声があったので、リンクを小さくして残してあるのです^^;)
いや、シューティングの館じゃないとヤダ!って場合は参考にしていただいてもいいと思いますが、龍神録の館をご覧になるか、むしろ自分で考えて作った方が早いかもしれませんm(_ _;)m
451ポイント を手に入れた。
|
|
|
|
|
Name: めーる ..ぴよぴよ(516ポイント)
Date: 2008/12/10(水) 11:54
No:25476
| 解決!
|
Title: Re:ゲームプログラミング
|
|
そういうことでしたか。そういうことなら先龍神録の方をしてみて
それからシューティングの方もちょっと触れてみようと思います。
違いが完璧にわかれば、と思います。
15ポイント を落としてしまった。
|
|
|
|
|
Name: ぶらっくぼっくす ..ぴよぴよ(244ポイント)
Date: 2008/12/11(木) 22:43
No:25561
|
|
Title: Re:ゲームプログラミング
|
|
個人的には龍神録よりもシューティングゲームの館のほうが
使われてる関数?も少なく非常に見やすかったのです。
あれ以上作らないのも少々残念な気持ちではあります。
なにはともあれこれからも管理人さまのサイトを参考に勉強に励んでいきたいと思います。
これからもがんばってください。
15ポイント を落としてしまった。
|
|
|
|
Name: こめかみ ..プログラマー(39,688ポイント)
Date: 2008/12/11(木) 03:24
No:25533
|
|
Title: 構造体のshort型のメンバ配列変数の表示について
|
|
cygwinで下記のコードをコンパイルして実行し、
例えば4回とも
"1"
を入力すると。
↓このように表示されて欲しいのですが、
A点:(1,1)
B点:(1,1)
実際には
↓このようにA点のy座標が0で出力されてしまいます。
A点:(1,0)
B点:(1,1)
int型だとこの問題は起きません、
また、B点の座標の入出力をカットすると、short型でもうまく表示されます。
何が起きているのでしょうか、調べ方などアドバイスよろしくお願いします。
#include <stdio.h>
typedef struct{
short x[2];//x座標
short y[2];//y座標
//short area;//面積
} cordinate_t;
int main()
{
cordinate_t cord;
puts("A点");
printf("X座標:"); scanf("%d", &cord.x[0]);
printf("Y座標:"); scanf("%d", &cord.y[0]);
puts("B点");
printf("X座標:"); scanf("%d", &cord.x[1]);
printf("Y座標:"); scanf("%d", &cord.y[1]);
printf("A点:(%d,%d)\n", cord.x[0], cord.y[0]);
printf("B点:(%d,%d)\n", cord.x[1], cord.y[1]);
return 0;
}
ちなみに構造体に面積の変数があるのは本来このようなプログラムだったからです。
#include <stdio.h>
typedef struct{
short x[2];
short y[2];
short area;
} cordinate_t;
int main()
{
cordinate_t cord;
short m;
cord.area = 0;
while (1){
printf("面積:%d\n", cord.area);
printf("座標を変更しますか? 【Yes…1/No…0】:\n");
scanf("%d", &m);
if (!m){ break; }
puts("左下");
printf("X座標:"); scanf("%d", &cord.x[0]);
printf("Y座標:"); scanf("%d", &cord.y[0]);
puts("右上");
printf("X座標:"); scanf("%d", &cord.x[1]);
printf("Y座標:"); scanf("%d", &cord.y[1]);
if ( cord.x[0] > cord.x[1] || cord.y[0] > cord.y[1] ){
puts("右上は左下よりも大きくしてください");
continue;
}
printf("左下:(%d,%d)\n", cord.x[0], cord.y[0]);
printf("右上:(%d,%d)\n", cord.x[1], cord.y[1]);
cord.area = (cord.x[1] - cord.x[0]) * (cord.y[1] - cord.y[0]);
};
return 0;
}
505ポイント を手に入れた。
|
|
|
|
Name: toyo ..上級者(21,733ポイント)
Date: 2008/12/11(木) 06:17
No:25534
|
|
Title: Re:構造体のshort型のメンバ配列変数の表示について
|
|
scanf("%d", &cord.x[0]);
が間違いです。
short型への読み込みには
scanf("%hd", &cord.x[0]);
を使います。
coordinate_t構造体にshort型メンバが4個として
x0 x1 y0 y1
???? ???? ???? ????
のようにメモリ確保されたとします。(??で1バイト)
初期化してないので??にしています。
scanf("%d", &cord.x[0]);
で1が入力されるとするとint型として代入されるので
x0 x1 y0 y1
0100 0000 ???? ????
のようにx1の領域まで代入されます(リトルエンディアンなので01が最初になっています)
以下同様に1が入力されるとして
scanf("%d", &cord.y[0]);
x0 x1 y0 y1
0100 0000 0100 0000
scanf("%d", &cord.x[1]);
x0 x1 y0 y1
0100 0100 0000 0000 *y0が0に書き換えられる
scanf("%d", &cord.y[1]);
x0 x1 y0 y1
0100 0100 0000 0100 0000 *スタックオーバーフロー
表示の際はshortなので
x0 = 1
y0 = 0
x1 = 1
y1 = 1
と表示されます。
(スタックオーバーしてるのでエラーになるかもしれません)
x1の入力に0x00010001(65537)を入力して全部1になるのを確認してみましょう
515ポイント を手に入れた。
|
|
|
|
|
Name: toyo ..上級者(21,758ポイント)
Date: 2008/12/11(木) 06:29
No:25536
|
|
Title: Re:構造体のshort型のメンバ配列変数の表示について
|
|
追伸
printf( )でもshortの表示には h をつけましょう
(%hd, %hx)
25ポイント を手に入れた。
|
|
|
|
|
Name: toyo ..上級者(21,873ポイント)
Date: 2008/12/11(木) 08:31
No:25539
|
|
Title: Re:構造体のshort型のメンバ配列変数の表示について
|
|
スタックオーバーフローじゃなくてバッファオーバーフローですかね
cygwinでコンパイルされてるそうですが
$ gcc -Wall sample.c
のように警告表示オプションをつけるとフォーマット指定と引数の型が違うときに警告を出してくれますよ。
115ポイント を手に入れた。
|
|
|
|
Name: ざこ ..入門者(4,116ポイント)
Date: 2008/12/11(木) 15:51
No:25550
|
|
Title: 戻り値と引数
|
|
【戻り値に関するご質問】
戻り値の概念がひどく曖昧です。戻り値というものを調べると関数に値を返すとだけ書いてあります。
その返すという表現がひどく曖昧です。
@何故値を返すのですか?(void型は例外)決まりなのですか?
A若干@とかぶりますが値を返すとどうなるのですか?
char *str_chr(const char *s,int c)
{
c=(char);
while(*s!=c){
if(*s=='\0')
return (NULL);
s++
}
return((char *)s);
}
例えば上記の例で言うとどういう風になるのでしょう。
【引数に関するご質問】
char *str_chr(const char *s,int c)
{
c=(char);
while(*s!=c){
if(*s=='\0')
return (NULL);
s++
}
return((char *)s);
}
int main(void)
{
char *ptr;
char ch[2];
char letter[]="ABCDEFGHIJKLMN";
printf("英大文字を入力してください\n");
scanf("%s",&ch);
if((ptr=str_chr(letter,ch[0]))==NULL)
printf("%cは英大文字ではありません\n",ch[0]);
else
printf("%cからの跡のアルファベットは%sです\n",ch[0],ptr);
return 0;
}
実引数と狩引数は別の文字でも構わないとは聞いたことありますが
(const char *s,int c)の値が(letter,ch[0])に渡されていますよね。
型まで完全に違うのに渡せるっというのはイメージが掴みずらいのですが、
説明していただける方いませんか?
146ポイント を手に入れた。
|
|
|
|
Name: 御津凪 [URL] ..熟練のプログラマー(45,094ポイント)
Date: 2008/12/11(木) 16:20
No:25552
|
|
Title: Re:戻り値と引数
|
|
# なにか構文的におかしいのは置いといて、
str_chr 関数は、文字列 s の中から、文字 c を先頭から探し、一致した箇所のポインタを返す、
というものですね。
この、「返す」値が戻り値です。
プログラムの関数は、数学の関数と同じで、三角関数(角度に対応する0〜1の値を返す)を考えると
戻り値の意味が分かりやすいかと思います。
次に引数のほうですが、
char*(データを書き換え可能なポインタ型)
↓
const char*(データを書き換えられないポインタ型)
と、変換されています(これは可能)。
この逆はエラーになります。
読み込み専用のデータを勝手に書き換え可能にするのは困りますよね。
もう一つの方は、一バイト文字を表す char 型から、 int 値に変換されています。
これは、変換しても値が変化しないため、問題がないためです。
逆の方では、コンパイル環境(オプション)によっては警告、あるいはエラーが出ます。
int 型は char 型よりも大きい数値を表せるため、 int -> char では数値を維持できないことになり、
値が変化してしまいます。
( int 値が char 型で表せる範囲の値であれば、 char 型に代入しても値に変化はありません)
このように暗黙的に変換できるものは、
・整数型(小) -> 整数型(大)
・float -> double
・void* -> const void* (ポインタ型ならどれでも)
等があります。
40ポイント を手に入れた。
|
|
|
|
|
Name: non ..上級者(21,036ポイント)
Date: 2008/12/11(木) 16:39
No:25553
|
|
Title: Re:戻り値と引数
|
|
>実引数と狩引数は別の文字でも構わないとは聞いたことありますが
仮引数です。「別の文字でもかまわない」というよりも「同じ名前でもかまわない」と言った方が良いかと。
つまり、名前はたとえ同じでも、別の箱(変数)だと考えてください。
仮引数はその関数内だけしか存在しません。関数から帰るとき、破棄されます。
>(const char *s,int c)の値が(letter,ch[0])に渡されていますよね。
>型まで完全に違うのに渡せるっというのはイメージが掴みずらいのですが、
御津凪さんの説明でわかったかと思いますが、代入だと考えてください。
つまり、
仮引数=実引数;
ですから、型がちがっても、普通の代入文と同じように自動的に型が変換されるときもあるということですね。
192ポイント を手に入れた。
|
|
|
|
|
Name: box ..ハッカー(131,760ポイント)
Date: 2008/12/11(木) 21:54
No:25559
|
|
Title: Re:戻り値と引数
|
|
> 戻り値の概念がひどく曖昧です。戻り値というものを調べると関数に値を返すとだけ書いてあります。
> その返すという表現がひどく曖昧です。
中学校あたりの数学でも「関数」という概念が登場しますね。
例えば、y=2x+1 という関数は、「もらったデータを2倍して1を足した結果を返す」という
仕事をします。
この関数に、
1を渡すと3が返ってくる
2を渡すと5が返ってくる
3を渡すと7が返ってくる
ことはおわかりかと思います。
このとき、「○を渡すと□が返ってくる」の○がC言語でいうところの引数で、□が戻り値(返り値)です。
そして、○から□に変換する方法(2倍して1を足す)が関数の中身(関数の仕事)です。
そんなことはとっくの昔にわかっている、ということでしたら、
上の回答は無視してください。
170ポイント を手に入れた。
|
|
|
|
Name: ムンバ ..上級者(16,065ポイント)
Date: 2008/12/11(木) 00:06
No:25526
|
|
Title: 練習問題の解釈について教えて下さい。(雑談?)
|
|
こんばんは。お世話になります。
参考書の「構造体の練習問題」の解釈について、ご指導下さい。
以下、練習問題です。
「あるクラスで国語と理科の試験を行いました。受験者数は5人です。
各受験者の氏名、国語、理科の点数(0〜100の整数)を格納する構造体配列を作り
氏名と点数を格納して下さい。
また、氏名の一部を入力すると点数を表示するプログラムを作って下さい。」
(猫でもわかるC言語・参考書内の練習問題引用)
という問題です。
氏名や各教科の点数を5人分、予め格納しておいてから
氏名の一部を入力すると点数を表示するプログラム。
を作るのか?
氏名や各教科の点数を入力するプログラム(入力画面)を作ってから、それぞれ5人分を入力した後に
氏名の一部を入力すると点数を表示するプログラム。
を作るのか?
きっと、また私の考え方が変なのかもしれませんが・・・。(涙
深く考えすぎなのでしょうか?^^;
お時間ある方、ご指導の程よろしくお願い致します。
371ポイント を手に入れた。
|
|
|
|
Name: s-rush ..初心者(6,816ポイント)
Date: 2008/12/11(木) 00:25
No:25527
|
|
Title: Re:練習問題の解釈について教えて下さい。(雑談?)
|
|
>氏名と点数を格納して下さい。
と書いてあるので、私としては
氏名と点数を入力するプログラム
↓
それぞれ5人分を入力
↓
氏名の一部を入力
↓
点数を表示するプログラム
という流れになると思います。
構造体の練習問題ということなら、
・構造体のメンバへの何かしらの数値(文字列)の代入、
・メンバへのアクセス
を理解しましょう、という観点からムンバさんの後者の考えでいいのではないでしょうか?
実際に私も構造体のメンバ云々の話で少々理解に苦しみましたので^^;
いまだに時々間違えることもorz
190ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) [URL] ..伝説なるハッカー(921,307ポイント)
Date: 2008/12/11(木) 08:05
No:25537
|
|
Title: Re:練習問題の解釈について教えて下さい。(雑談?)
|
|
あ〜確かに2通りに解釈出来ますね。
でもこういうのは大抵キーボード入力で格納させると思います。
なので私もキーボード入力だと思います。
ファイル入力とかだったらそう書いてあると思いますし。
あとは、s-rushさんの仰るプログラムに、string.hの文字列を検索するあの関数を使えば出来上がりだと思います。
あの関数を使うと一行で検索出来てしまって面白くないので、その関数を自作すると勉強になっていいいかもしれません。
192ポイント を手に入れた。
|
|
|
|
|
Name: non ..上級者(21,307ポイント)
Date: 2008/12/11(木) 09:08
No:25540
|
|
Title: Re:練習問題の解釈について教えて下さい。(雑談?)
|
|
私なら、まずは、初期値としてデータを与えます。
それは、表示する方を先に作るためです。そこが、完成してから、次の段階で
データの入力を標準入力からできるようにします。
そうしないと、実行して試すときに、何度も5人分のデータを入力しなければいけないので
面倒だからです。
84ポイント を手に入れた。
|
|
|
|
|
Name: ムンバ ..上級者(16,481ポイント)
Date: 2008/12/11(木) 20:48
No:25557
| 解決!
|
Title: Re:練習問題の解釈について教えて下さい。(雑談?)
|
|
こんばんは。
レス遅くなりまして、すみませんでした。
s-rushさん、管理人さん、nonさん
早速のご解説どうもありがとう御座います。
なるほどですね〜。
格納する構造体配列を作り・・・
って質問なんだから、「予め値を設定して」ではないのですものね。
皆さんのご解説、しっかり読ませて頂きました。ありがとうございます。
私は、初心者なのでいきなり入力画面を作らないで^^;
nonさんの言われてる様な方法で試しながらやってます。
まず表示できるかどうかを試してから、入力画面を作ってます。
流れは、s-rushさんの、ご解説を参考に作ってみます。ありがとうございます。
次の勉強が「ファイルの入出力」なんですよ。管理人さん!^^
すごく興味があるところなので早くやりたいんですけど
ポインタと構造体で・・・今こんな感じで格闘してます。(自爆
「あの関数」ですか?ん?その関数・・・?^^;
えと〜?それでは、今回は「その関数」は作らないで、また一通り勉強すると思いますので
その時に思い出してトライしてみますので「あの関数」解らなかったら
質問させて頂きますので、よろしくお願いします。w
(PS:いつの間にか「上級者」になってしまってますが、「初級者」に戻せませんか?<爆)
よしっ!練習問題がんばるぞぉ〜♪
本当に、どうもありがとう御座いました。
また、よろしくお願い致します。(謝
416ポイント を手に入れた。
|
|
|
|
Name: VARIO ..かけだし(2,084ポイント)
Date: 2008/12/10(水) 19:15
No:25509
|
|
Title: txtを読み込み、それを元に配列を作る方法
|
|
先日はlp_solveをC言語に組み込ませる方法についてご指導賜りましてありがとうございました。
おかげさまでうまくいきました。
今回、そのlp_solveで出力された結果(txtファイル)を読み込み、その結果に依存した配列を作る方法を考えています。
lp_solveで出力される結果のテキストは、
Value of objective function: 10
Actual values of the variables:
x1_2 0.272727
x1_5 0.493506
x1_6 0.207792
x1_8 0.454545
x1_10 0.571429
・
・
・
y1_2_1_2 0.272727
y1_2_2_1 0
y1_2_1_5 0.493506
・
・
・
のような形式です。
このテキストの3行目からのx○_□の行(yの行は無視)の右側の数字が0.5以上の場合のみ、
あらかじめ用意してある配列aに対して、配列の要素a[○][□]=1と更新させたいのです。
私がわからないのは、どうやってテキストファイルの読み込ませたい部分だけを指定するのか、
というところです。列数を指定することも考えましたが、その場合、例えば、x10_1とx1_10などをどう
場合分けすれば良いのかわかりません。
どういう関数を使えばいいのかや大まかな流れなど、ヒントだけでも構いませんので
教えていただけないでしょうか?
ちなみに、私の環境はVista/Visual2008です。よろしくお願いします。
648ポイント を手に入れた。
|
|
|
|
Name: つうこうにん ..かけだし(1,246ポイント)
Date: 2008/12/10(水) 20:44
No:25514
|
|
Title: Re:txtを読み込み、それを元に配列を作る方法
|
|
かなりずさんな例ですがたたき台にどうぞ。
配列に入れてませんけど条件に合うものを出力しています。
#include <stdio.h>
#define BUFSIZE (256)
const char *FILENAME = "data.txt";
char buf[BUFSIZE];
int main()
{
FILE *fp;
if((fp=fopen(FILENAME,"r"))==NULL){
fprintf(stderr,"%s : ファイルが見つかりません\n",FILENAME);
return 0;
}
while(fgets(buf,BUFSIZE,fp)!=NULL)
{
if('x' == buf[0]){
int n,m;
float f;
sscanf(buf,"%*c%d_%d %f",&n,&m,&f);
if(0.5 <= f)
printf("[%d,%d]=%f\n",n,m,f);
}
}
if(ferror(fp))
fprintf(stderr,"%s : 読み込みエラー\n",FILENAME);
fclose(fp);
return 0;
}
397ポイント を手に入れた。
|
|
|
|
|
Name: non ..上級者(21,223ポイント)
Date: 2008/12/10(水) 20:46
No:25516
|
|
Title: Re:txtを読み込み、それを元に配列を作る方法
|
|
関数ならstrstrを使って分解すればいいと思います。
それより、配列の大きさの最大は決まっているのですか?
それとも、出てくるたびにリサイズする?
72ポイント を手に入れた。
|
|
|
|
|
Name: VARIO ..かけだし(2,132ポイント)
Date: 2008/12/10(水) 20:55
No:25517
|
|
Title: Re:txtを読み込み、それを元に配列を作る方法
|
|
>>つうこうにんさん
ありがとうございます。参考にさせてもらいます。
>>nonさん
はい、決まっています。この例の場合では11×11の配列です。
48ポイント を手に入れた。
|
|
|
|
|
Name: VARIO ..かけだし(2,170ポイント)
Date: 2008/12/11(木) 16:13
No:25551
| 解決!
|
Title: Re:txtを読み込み、それを元に配列を作る方法
|
|
おかげさまで大幅に課題を進めることができました。
つうこうにんさん、本当にありがとうございました。
また機会があればよろしくお願いします。
38ポイント を手に入れた。
|
|
|
|
Name: じつかた ..ぴよぴよ(71ポイント)
Date: 2008/12/11(木) 13:35
No:25547
|
|
Title: ファイルの読み込みetc...
|
|
C言語のファイルの読み込み関連の質問です。
コマンドパラメーターで指定されたファイルを読み込む。
→int main(int argc,char *argv[]){}
その際に別途で用意されたファイルの中身を
行指定で読み込みたいのですが、
fseek()を使うということはわかるのですが、
どのようにしたらよろしいでしょうか?
お願いいたします。
71ポイント を手に入れた。
|
|
|
|
Name: non ..上級者(20,844ポイント)
Date: 2008/12/11(木) 13:41
No:25548
|
|
Title: Re:ファイルの読み込みetc...
|
|
読み込むファイルはバイナリファイルでしょうか?
それをランダムに読み込みたいのでしょうか?(行単位?レコード単位でなく)
何がわからないのかをもう少し、明確にしてください。
41ポイント を落としてしまった。
|
|
|
|
Name: 化学系 ..ぴよぴよ(24ポイント)
Date: 2008/12/09(火) 14:20
No:25383
|
|
Title: 無題
|
|
さっぱりわからないのでどうかお助けください
実行例
入力された整数の各桁の和が0の倍数になるように1桁の数を付け加えます。
6桁の数を入力してください:071501
各桁の和:14
付け加える数字:6
得られた数:0715016
どうかお願いします
24ポイント を手に入れた。
|
|
|
|
Name: non ..上級者(18,924ポイント)
Date: 2008/12/09(火) 15:13
No:25394
|
|
Title: Re:無題
|
|
スレッド「C言語の因数分解」のioioさんとは別の学校の方でしょうか。
なぜかと言いますと、
桁数が指定してあって、桁数を揃えるために、先頭に0がついてます。
例として使われている数値も似通ってるし・・・
こんなのが流行っているのですか?
別に、他意はありませんけど。
2倍のポイントを手に入れた! 276ポイント を手に入れた。
|
|
|
|
|
Name: non ..上級者(19,682ポイント)
Date: 2008/12/09(火) 17:15
No:25405
|
|
Title: Re:無題
|
|
例外処理はこんな使い方でいいでしょうか?
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
class Num{
int n[7];
public:
void set(string);
void disp(void);
};
void Num::set(string str)
{
int i,q=0;
for(i=0;i<6;i++){
n[i]=str[i]-'0';
q+=n[i];
}
q%=10;
n[6]=(q)?10-q:0;
}
void Num::disp(void)
{
int i;
for(i=0;i<7;i++)
cout << n[i];
cout << endl;
}
string cinStr(void)
{
string str;
try{
cout << "6桁の数を入力してください:";
cin >> str;
if(str.size()!=6)
throw "ERROR";
for(int i=0;i<6;i++)
if(!isdigit(str[i]))
throw i;
}
catch(char *){
cout << "6桁入力のこと" << endl;
throw "";
}
catch(int){
cout << "数字以外が入力されてます" << endl;
throw "";
}
return str;
}
int main(void)
{
Num num;
string str;
try{ str=cinStr();}
catch(char *){
cout << "入力エラー" << endl;
return 0;
}
num.set(str);
num.disp();
return 0;
}
406ポイント を手に入れた。
|
|
|
|
|
Name: s-rush ..初心者(6,168ポイント)
Date: 2008/12/09(火) 19:00
No:25414
|
|
Title: Re:無題
|
|
さっぱりわからないではなく、せめてどのように処理をすれば
自分の望む結果が得られるかくらいは考えましょう。
考え方の一例
3桁の数で考えてみましょう。
たとえば入力された数が987だった場合、
987=9×100+8×10+7×1
になりますよね?
入力された値から、上記の式の右辺の係数に当たる数値を計算でそれぞれ取り出すこと処理を考えます。
計算例
987÷10の余り:7 商:98
98÷10の余り :8 商:9
9÷10の余り:9 商:0
一応この計算で係数に当たる数値を求めることができます。
(少し考えてもらうために説明を多少省略していますが、分かりますよね?)
あとは入れる数値ですが、これは自分で考えてみてください。
上の計算法でも入れる数値を求めることができるので、
この求め方を関数化してしまってもいいかもしれませんね。
P.S Dixq さんへ
新入りなのに出しゃばったマネをしてすいません。
まだまだ未熟者ですが、できる範囲でお手伝いしていきます。
306ポイント を手に入れた。
|
|
|
|
|
Name: 組木紙織 [URL] ..熟練のプログラマー(67,748ポイント)
Date: 2008/12/09(火) 22:46
No:25440
|
|
Title: Re:無題
|
|
No:25405 nonさんへ返信
例外処理を使う場所は良いと思いますが実装法にちょっと問題があるのかな。
以下私が気になる部分です。
配列を即値で扱っているのが気になります。enumでもつかったらどうでしょうか。
例外は例外クラスを利用して投げるようにしてください。
変数の定義位置は定義と同時に初期化できるのが理想です。(実際にはなかなか難しいですが。)
変数が必要になったら宣言してください。
2倍のポイントを手に入れた! 230ポイント を手に入れた。
|
|
|
|
|
Name: conio ..初心者(8,126ポイント)
Date: 2008/12/09(火) 22:57
No:25441
|
|
Title: Re:無題
|
|
「さっぱり分からない、全然分からない、全く分からない」
「どうかお願いします」
んー最近このようなコメントが多いような。
"さっぱり分からない"のはこちらの方です。
とりあえず、考え方としてはs-rushさんの通り、割った余りを利用すればいいでしょう。
-------------------------------------------------------------------
@余りを順次、適当な変数(sumなど)に足して行く。
A足したもの(sum)の下位桁を求める。(54なら4、15なら5、123なら3,)
B"● - 下位桁"で、付け加える値を求める。
C最初の整数にある処理を行い、最後に付け加える値を足す。
(071501にある処理を施したもの)+ 6 = 715016
-------------------------------------------------------------------
回答はあえて抽象的にしました。虫食いのところは考えて埋めてください。
227ポイント を手に入れた。
|
|
|
|
|
Name: たかぎ [URL] ..比類無きプログラマー(75,476ポイント)
Date: 2008/12/10(水) 00:13
No:25448
|
|
Title: Re:無題
|
|
> nonさん
> 例外処理はこんな使い方でいいでしょうか?
入力された数値の整合性判定の結果として例外を送出するのは、あまり望ましくないと思います。
C++の例外は非常に重いので、普通は発生しないような事象に限定して用いた方がよいでしょう。
47ポイント を手に入れた。
|
|
|
|
|
Name: s-rush ..初心者(6,460ポイント)
Date: 2008/12/10(水) 00:25
No:25449
|
|
Title: Re:無題
|
|
>たかぎさん
確かにおかしいですよね。
もう少し書きようがあると思います。
まぁたぶんこれは各桁の値を合計して、その値が10の倍数になるように、
ではないでしょうか?
私の勝手な解釈で計算法を示したんですけど、
意味のとり違いであれば、元も子もないですけど。
>化学系さん
少し補足しておきます。
nonさんのおっしゃる通り、例外処理も考えておいた方がいいと思います。
私はC++は勉強中なので、コードの意味はよくわかりませんが、
・入力した値が6桁出ない場合
・入力した値が数字でない場合(例えば文字や記号)
少なくともこの2つの例外くらいは実装しておいた方がいいでしょう。
ifやcaseを使えばできると思います。
292ポイント を手に入れた。
|
|
|
|
|
Name: たかぎ [URL] ..比類無きプログラマー(75,956ポイント)
Date: 2008/12/10(水) 01:14
No:25453
|
|
Title: Re:無題
|
|
10の倍数になるように、という解釈で作ってみました。
処理系不明なので、可能な限り規格厳密合致プログラムを目指しましたが、古い規格に準拠した処理系は無視しています。
%:include <ctype.h>
%:include <stdio.h>
%:include <stdlib.h>
int main(void)
<%
fputs("6??/u6841??/u306e??/u6570??/u3092??/u5165??/u529b??/u3057??/u3066??/u304f??/u3060??/u3055??/u3044:", stdout);
fflush(stdout);
char s<:6+1:>, lf;
if (scanf("%6??(0123456789??)%c", s, &lf) != 2 ??!??! lf != '??/n')
goto error;
int sum = 0;
for (int i = 0; i < 6; i++)
<%
if (!isdigit((unsigned char)s<:i:>))
goto error;
sum += s<:i:> - '0';
%>
printf("??/u5404??/u6841??/u306e??/u548c:%d??/n", sum);
int mod = sum % 10;
int d = mod == 0 ? 0 : 10 - mod;
printf("??/u4ed8??/u3051??/u52a0??/u3048??/u308b??/u6570??/u5b57:%d??/n", d);
printf("??/u5f97??/u3089??/u308c??/u305f??/u6570:%s%d??/n", s, d);
return EXIT_SUCCESS;
error:
fputs("??/u30c0??/u30e1??/uff01??/n", stderr);
return EXIT_FAILURE;
%>
[]や{}が入力できない環境のことも考慮しています。
409ポイント を手に入れた。
|
|
|
|
|
Name: non ..上級者(20,309ポイント)
Date: 2008/12/10(水) 12:37
No:25481
|
|
Title: Re:無題
|
|
組木紙織さん
>配列を即値で扱っているのが気になります。enumでもつかったらどうでしょうか。
#defineでなくenumですか?具体的にどうすればいいのでしょうか。ご面倒でしょうが
お教えください。
exceptionクラスについては、もう少し勉強します。
たかぎさん
>入力された数値の整合性判定の結果として例外を送出するのは、あまり望ましくないと思います。
>C++の例外は非常に重いので、普通は発生しないような事象に限定して用いた方がよいでしょう。
了解しました。
いろいろ調べると、重たいと書いてありますね。本当に必要な機能なのか、まだ理解出来ておりません。
上のたかぎさんのプログラムはさっぱりわかりません。まだまだ、道遠しですね。
116ポイント を手に入れた。
|
|
|
|
|
Name: toyo ..上級者(21,218ポイント)
Date: 2008/12/10(水) 13:07
No:25483
|
|
Title: Re:無題
|
|
>>nonさん
??/
みたいなのをtrigraphといいます
??/は\(バックスラッシュ)と同じ意味になります
キーボードから打ち込めない記号があるときに使えます
で
%:や<%は始めて見ました
調べてみたらdigraphですか
いろいろありますね
111ポイント を手に入れた。
|
|
|
|
|
Name: non ..上級者(20,357ポイント)
Date: 2008/12/10(水) 13:20
No:25484
|
|
Title: Re:無題
|
|
toyoさん
まだ、中身を調べるところまで到ってません。
それより、コンパイルするのにパラメータが必要なのかと思いますが、どうすればいいんでしょ。
普通にやるとエラーがでるし。
48ポイント を手に入れた。
|
|
|
|
|
Name: たかぎ [URL] ..比類無きプログラマー(76,425ポイント)
Date: 2008/12/10(水) 14:01
No:25485
|
|
Title: Re:無題
|
|
> 上のたかぎさんのプログラムはさっぱりわかりません。まだまだ、道遠しですね。
なぜこんな変なことをしているかというと、処理系を明確にすることが如何に大切かを分かってもらうためです。
> それより、コンパイルするのにパラメータが必要なのかと思いますが、どうすればいいんでしょ。
例えばGCCであれば、-std=c99または-std=gnu99オプションを付ければコンパイルできます。
文字コード不明ですので文字列は国際文字名表記になっています。環境がUTF-8でなければ-fexec-charsetオプションも併用してください。
具体的には、CygwinやMinGWであれば-fexec-charset=cp932を指定してください。
2倍のポイントを手に入れた! 366ポイント を手に入れた。
|
|
|
|
|
Name: 組木紙織 [URL] ..熟練のプログラマー(67,995ポイント)
Date: 2008/12/10(水) 23:57
No:25522
|
|
Title: Re:無題
|
|
nonさん
>#defineでなくenumですか?具体的にどうすればいいのでしょうか。ご面倒でしょうが
お教えください。
#defineだと色々問題が多いからね。
C++だと以下のほうがよいかな。
class Num{
enum{arraySize=7};//こっちか
// const static unsigned int arraySize =7;こっちでもよい
int n[arraySize];
public:
void set(string);
void disp(void);
};
例外は欲しいクラスを例外クラスの階層に入れてあげればよいだけです。
247ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) [URL] ..伝説なるハッカー(921,606ポイント)
Date: 2008/12/11(木) 08:20
No:25538
|
|
Title: Re:無題
|
|
トライグラフ
http://www.ncos.co.jp/products/cgi-bin/e000.cgi?64
コメントアウトした行でも、文字列の中でも通用するので
#include <stdio.h>
int main(){
int i=0; //0が入る
i++; // ++って何??/
i++;
printf("答えは??=%d",i);
return 0;
}
実行結果
答えは#1
安易に使うと危ない(知らない人が読んだら誤解する可能性がある)のと、
知らないうちに書いてしまってることがあるので、
(上の例でいうと、書いた人はiは2であり、#なんか書いた覚えが無いとか)
バグ回避の為、私はクエッションマーク2連続は意識してかかないようにしています。
昔Justyさんにこのバグで苦労したと話をお聞きしたことがありました。
ただ、VisualC++2008でコンパイルしてみたところ
「warning C4010: 単一行コメント (//) に、行連結文字があります。」
と警告してくれましたからコンパイラによっては簡単に見つけられるかもしれませんね。
299ポイント を手に入れた。
|
|
|
|
|
Name: non ..上級者(21,174ポイント)
Date: 2008/12/11(木) 09:40
No:25542
|
|
Title: Re:無題
|
|
組木紙織さん
enumの件ありがとうございます。
>enum{arraySize=7};
のarraySizeをメンバー関数内で使うのはいいのですが、外で使いたい場合、
これをpublicにしてもいいのでしょうか?
それとも、その数を出力するようなメンバー関数を作って使うようにすべきでしょうか?
たぶん後者だとは思うのですが、どうされてますか?
133ポイント を落としてしまった。
|
|
|
|
|
Name: たかぎ [URL] ..比類無きプログラマー(76,456ポイント)
Date: 2008/12/11(木) 10:41
No:25543
|
|
Title: Re:無題
|
|
> これをpublicにしてもいいのでしょうか?
> それとも、その数を出力するようなメンバー関数を作って使うようにすべきでしょうか?
これはpublicでかまいません。
もちろん、クラスの中でしか使う必要がないなら、privateやprotectedにしてもよいでしょう。
31ポイント を手に入れた。
|
|
|
|
Name: ぽんた ..ぴよぴよ(76ポイント)
Date: 2008/12/10(水) 19:28
No:25510
|
|
Title: C++で配列を使った問題なんですが
|
|
C++で999が入力されるか、入力が10回されたら、入力件数、最大値、最小値、合計値出力する。
999は最大値、最小値、合計に反映されないように作りたいのですが、行き詰ってしまいました。
#include <stdio.h>
void main (void)
{
int atai[10];
int i=0;
int seisu=0;
int count = 0 ;
int min=0 ;
int max=0 ;
int goukei = 0 ;
for(i=0;i<10;i++)
{
atai[i]=0;
}
atai[i]=seisu;
while ((count<10)&&(seisu!=999))
{
/*表示*/
printf("整数を入力してください>>");
scanf ("%d", &seisu) ;
/* 入力件数を一つふやす */
count++;
if (count==1)
/* 最小値 */
for(i=0;i<10;i++)
{
if (atai[i] < min)
{
min = atai[i] ;
}
/* 最大値 */
if ( atai[i] > max)
{
max = atai[i] ;
}
}
/* 合計値を計算する */
{
goukei+=atai[i];
}
}
/* 出力する */
printf ("入力は%d件です。\n",count);
printf ("最小値=%d\n", min);
printf ("最大値=%d\n",max);
printf ("合計=%d\n",goukei);
}
76ポイント を手に入れた。
|
|
|
|
Name: いけやん ..上級者(17,105ポイント)
Date: 2008/12/10(水) 19:50
No:25511
|
|
Title: Re:C++で配列を使った問題なんですが
|
|
条件は
>999が入力されるか、入力が10回されたら
だから
>while ((count<10)&&(seisu!=999))
ここの部分は、[&]ではなく[|]になると思う。
自分的な言い回しですか
&は「と」になり
|は「か」になると思います。
23ポイント を手に入れた。
|
|
|
|
|
Name: non ..上級者(21,049ポイント)
Date: 2008/12/10(水) 20:32
No:25512
|
|
Title: Re:C++で配列を使った問題なんですが
|
|
最初の
for(i=0;i<10;i++)
{
atai[i]=0;
}
atai[i]=seisu;
何をやっているのかわかりません。ましてforから抜けたとき、iは10になってますので
atai[10]=seisu;としており非常にまずいです。
1個目のデータをいれないと脱出するかわからないので、1個目のデータ入力と2個目以降を
分けた方がわかりやすいです。
1個目のデータの時、maxとminにデータを入れます。
流れは次のようになります。
1個目のデータの入力
maxとminに1個目のデータを入れる
while ((count<10)&&(seisu!=999))
2個目のデータの入力
maxとminの更新
合計の累計
ただし、このままでは1個目のデータが999の場合はないという考えです。
273ポイント を手に入れた。
|
|
|
|
|
Name: non ..上級者(21,151ポイント)
Date: 2008/12/10(水) 20:40
No:25513
|
|
Title: Re:C++で配列を使った問題なんですが
|
|
いけやんさんへ
>while ((count<10)&&(seisu!=999))
であっています。
whileはこの条件が成り立っている間繰り返すという意味です。
脱出条件が
>999が入力されるか、または、入力が10回されたら
ですから
ループ条件は
10回よりすくなく、かつ、999でない間になります。
102ポイント を手に入れた。
|
|
|
|
|
Name: box ..ハッカー(131,590ポイント)
Date: 2008/12/10(水) 20:46
No:25515
|
|
Title: Re:C++で配列を使った問題なんですが
|
|
他の方も言及されているとおり、「いきなり」999を入力したときにどうするか、
という点についての確認が必要でありましょう。
7ポイント を手に入れた。
|
|
|
|
|
Name: s-rush ..初心者(6,626ポイント)
Date: 2008/12/10(水) 21:55
No:25520
|
|
Title: Re:C++で配列を使った問題なんですが
|
|
最初の
for(i=0;i<10;i++)
{
atai[i]=0;
}
を見る限り、各配列に初期値0を代入しているんですよね?
では宣言の時に合わせて初期化してしまいましょう。
int atai[10]={0};
このように書いてあげれば、すべてに0が入っている状態になります。
あとは他の方がおっしゃられているように、いきなり999が入力されたときの処理を考える必要がありますね。
166ポイント を手に入れた。
|
|
|
|
|
Name: いけやん ..上級者(17,007ポイント)
Date: 2008/12/11(木) 09:09
No:25541
|
|
Title: Re:C++で配列を使った問題なんですが
|
|
nonさん
ぽんたさん
失礼しました。
nonさんご指摘
ありがとうございます。
>10回よりすくなく、かつ、999でない間になります。
10より少なく、999でない場合の両方を満たしている
その間、回れって事であってるんですね、すいませんでした。
98ポイント を落としてしまった。
|
|
|
|
Name: しょしょしょしんしゃ ..中級者(9,855ポイント)
Date: 2008/12/10(水) 11:59
No:25477
|
|
Title: 再 ABCの乱数編
|
|
C言語 乱数と文字列
学校の宿題ですが
乱数を使用して、文字列を作成するのですが
分かりません。問題は以下のとおりです。
ランダムな文字列を作成する関数void passwd()作成
1、使用できる文字はアルファベット大文字のAからZ,小文字のaからzおよび数字の2から9の合計60文字。
2、文字列の長さは7文字から10文字のランダムに決められた値とする。
3、文字列に大文字・小文字・数字すべてが入っている文字列しか生成しない。
たとえば、E4F7ukYはいいが、kuh8ghandは大文字がないので、やり直しという風です。
分かりにくい部分がありますが、よろしくお願いします。
一応、条件1、2はクリアできたのですが、条件3のやり直しする部分をどのようにするか分かりません、
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int main (void){
int nc;
char pwd[11];
int n;
char c;
int k;
char yn[2];
srand((unsigned)time(NULL));
nc = 7+rand()%4;
n = 0;
do{
k=rand()%3;
switch(k){
case 0:
c='2'+rand()%8;break;
case 1:
c='a'+rand()%26;break;
case 2:
c='A'+rand()%26;break;
}
pwd[n++] = c;
}while(n<nc);
pwd[n]='\0';
printf("生成されたパスワード:%s\n",pwd);
return 0;
}
507ポイント を手に入れた。
|
|
|
|
Name: Mist ..プログラマー(35,295ポイント)
Date: 2008/12/10(水) 12:07
No:25478
|
|
Title: Re:再 ABCの乱数編
|
|
while(1) {
パスワード作成
完成したパスワードをチェック
→OK break;
}
でいいと思いますが。
77ポイント を手に入れた。
|
|
|
|
|
Name: バグ ..ハッカー(132,973ポイント)
Date: 2008/12/10(水) 12:26
No:25480
|
|
Title: Re:再 ABCの乱数編
|
|
1:大文字から1文字を選択
2:小文字から1文字を選択
3:数字から1文字を選択
4:残り部分を大文字・小文字・数字から選択
5:シャッフル
でいいんでは?
この方法なら、文字列の判定が不要になり、その結果として、やり直す事も考慮する必要がなくなります。
101ポイント を手に入れた。
|
|
|
|
|
Name: バグ ..ハッカー(133,638ポイント)
Date: 2008/12/10(水) 13:01
No:25482
|
|
Title: Re:再 ABCの乱数編
|
|
私が書き込みしたアルゴリズムで実装すると、こんな感じでしょうか?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
/* A〜Zから1文字を取得する関数 */
char getAlphabetBig()
{
return 'A' + (char)(rand() % 26);
}
/* a〜zから1文字を取得する関数 */
char getAlphabetSmall()
{
return 'a' + (char)(rand() % 26);
}
/* 2〜9から1文字を取得する関数 */
char getNumber()
{
return '2' + (char)(rand() % 8);
}
/* A〜Z、a〜z、2〜9の中から1文字を取得する関数 */
char getAllSymbol()
{
switch (rand() % 3)
{
case 0:
return getAlphabetBig();
case 1:
return getAlphabetSmall();
default:
return getNumber();
}
}
/* 文字列をシャッフルする */
void shuffleString(char* pwd)
{
char buf = '\0';
unsigned int i;
int swap;
for (i = 0; i < strlen(pwd); ++i)
{
/* ランダムに選択された箇所の文字と入れ替える */
swap = rand() % strlen(pwd);
buf = pwd[i];
pwd[i] = pwd[swap];
pwd[swap] = buf;
}
}
int main(void)
{
char pwd[11] = {'\0', };
int i;
srand((unsigned)time(NULL));
/* 最初の3文字には大文字、小文字、数字を各1文字ずつ選択する */
pwd[0] = getAlphabetBig();
pwd[1] = getAlphabetSmall();
pwd[2] = getNumber();
/* 残りの7文字は大文字、小文字、数字の全ての中から選択する */
for (i = 3; i < 10; ++i)
{
pwd[i] = getAllSymbol();
}
/* 文字列をシャッフルする */
shuffleString(pwd);
/* 文字列の表示 */
printf("生成されたパスワード:%s\n", pwd);
}
665ポイント を手に入れた。
|
|
|
|
|
Name: lbfuvab ..中級者(11,348ポイント)
Date: 2008/12/10(水) 15:13
No:25489
|
|
Title: Re:再 ABCの乱数編
|
|
こんな感じですかね。(間違ってる可能性あり)
const char str[60]="qwertyuioplkjhgfdsazxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM23456789";
char GetBigAlpha(void){
return str[rand()%26];
}
char GetSmlAlpha(void){
return str[26+rand()%26];
}
char GetNum(void){
return str[52+rand()%8];
}
char GetRndCh(void){
return str[rand()%60];
}
int __cdecl RndCmp(void* a,void *b){
return (rand()%2)?1:-1;
}
void Password(char *buf){
int len=7+rand()%4,i=0;
buf[i++]=GetBigAlpha();
buf[i++]=GetSmlAlpha();
buf[i++]=GetNum();
for(;i<len;i++)
buf[i]=GetRndCh();
qsort(buf,(size_t)len,sizeof(char),RndCmp);
}
260ポイント を手に入れた。
|
|
|
|
|
Name: non ..上級者(20,663ポイント)
Date: 2008/12/10(水) 16:14
No:25490
|
|
Title: Re:再 ABCの乱数編
|
|
>たとえば、E4F7ukYはいいが、kuh8ghandは大文字がないので、やり直しという風です。
やり直しって指示があるなら、やり直しした方がいいでしょう。
なるべく、本人が作った部分を壊さないように作りました。
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int main (void)
{
int nc;
char pwd[11];
int n;
char c;
int k;
char yn[2];
unsigned char sw=0; //何が使われたかのスイッチ
srand((unsigned)time(NULL));
while(sw!=0x07){ // 3つのビットが1になるまで繰り返し
n=0;
nc = 7+rand()%4;
do{
k=rand()%3;
switch(k){
case 0:
sw |=0x01; // 0ビット目を1にする
c='2'+rand()%8;break;
case 1:
sw |=0x02; // 1ビット目を1にする
c='a'+rand()%26;break;
case 2:
sw |=0x04; // 2ビット目を1にする
c='A'+rand()%26;break;
}
pwd[n++] = c;
}while(n<nc);
pwd[n]='\0';
}
printf("生成されたパスワード:%s\n",pwd);
return 0;
}
290ポイント を手に入れた。
|
|
|
|
|
Name: しょしょしょしんしゃ ..中級者(9,839ポイント)
Date: 2008/12/11(木) 00:03
No:25523
|
|
Title: Re:再 ABCの乱数編
|
|
遅くなりましたが、
興味深い プログラムの例文ありがとうございました。
おかげ様
で 参考になりました。
また お願いします。
16ポイント を落としてしまった。
|
|
|
|
Name: ぴーやま ..ぴよぴよ(143ポイント)
Date: 2008/12/10(水) 04:23
No:25455
|
|
Title: C言語(文字の追加?)
|
|
初めまして。
初心者でC言語を勉強中なのですが、
課題に躓いてしまったのでこの場を借りて質問させて頂きます!
まずfor文を使って九九表を作りました。
それから3の倍数の数値の後ろに「@」を付けろ、というのですが
前には付くのですが後ろに付ける方法がわかりません…。
その方法を教えていただけないでしょうか?よろしくお願いします。
143ポイント を手に入れた。
|
|
|
|
Name: めーる ..ぴよぴよ(50ポイント)
Date: 2008/12/10(水) 09:14
No:25461
|
|
Title: Re:C言語(文字の追加?)
|
|
数値の後ろと書いてるのでprintfで3の倍数のときに%d →%d@
とすればいいのでは?単純過ぎかな・・
でも前には付けれて後ろには無理なのがよくわかりませんね。
50ポイント を手に入れた。
|
|
|
|
|
Name: conio ..初心者(8,367ポイント)
Date: 2008/12/10(水) 09:17
No:25462
|
|
Title: Re:C言語(文字の追加?)
|
|
----------------------------------------------
1 2 3@ 4 5 6@ 7 8 9@
2 4 6@ 8 10 12@ 14 16 18@
3@ 6@ 9@ 12@ 15@ 18@ 21@ 24@ 27@
4 8 12@ 16 20 24@ 28 32 36@
5 10 15@ 20 25 30@ 35 40 45@
6@ 12@ 18@ 24@ 30@ 36@ 42@ 48@ 54@
7 14 21@ 28 35 42@ 49 56 63@
8 16 24@ 32 40 48@ 56 64 72@
9@ 18@ 27@ 36@ 45@ 54@ 63@ 72@ 81@
----------------------------------------------
このような出力になれば良いということですか?
二重ループの中にif文で3の倍数か3の倍数でないかで、
表示方法の場合分けをすれば良いのでは無いでしょうか。
自分で作ったプログラムや、出力例を見せていただかないと、何とも言えませんが。
241ポイント を手に入れた。
|
|
|
|
|
Name: ぴーやま ..ぴよぴよ(394ポイント)
Date: 2008/12/10(水) 14:43
No:25487
|
|
Title: Re:C言語(文字の追加?)
|
|
皆さん、返答ありがとうございます。
---------------------------------------------
1 2 3@ 4 5# 6@ 7 8 9@
2 4 6@ 8 10# 12@ 14 16 18@
3@ 6@ 9@ 12@ 15@ 18@ 21@ 24@ 27@
4 8 12@ 16 20# 24@ 28 32 36@
5# 10# 15@ 20# 25# 30@ 35# 40# 45@
6@ 12@ 18@ 24@ 30@ 36@ 42@ 48@ 54@
7 14 21@ 28 35# 42@ 49 56 63@
8 16 24@ 32 40# 48@ 56 64 72@
9@ 18@ 27@ 36@ 45@ 54@ 63@ 72@ 81@
----------------------------------------------
課題自体の出力例はこのようになり、
3の倍数の数値の後ろに「@」
5の倍数の数値の後ろに「#」
(3と5の倍数は3を優先する)
それ以外の数値にはスペースを付ける との事です。
皆さんのヒントを得て色々と調べて試してみても、
使い方をいまいち把握していないものでエラーの連続です…。
251ポイント を手に入れた。
|
|
|
|
|
Name: conio ..初心者(8,509ポイント)
Date: 2008/12/10(水) 21:44
No:25519
|
|
Title: Re:C言語(文字の追加?)
|
|
課題の条件が増えてますね。
ですが、if文を使えば表示させることは可能です。
-------------------------------------
if(●●●)
/*3の倍数の時の表示*/
else if(○○○)
/*5の倍数の時の表示*/
else
/*それ以外*/
-------------------------------------
穴あきの部分と、日本語の部分はプログラムに変えて下さい。
そして、最初の九九の表を表示するプログラムと、上手く合わせれば完成です。
あと、printf文で
・最低○桁で表示する
この条件を付けて表示させる方法を知っておく必要があると思います。
142ポイント を手に入れた。
|
|
|
|
Name: LaL ..ぴよぴよ(676ポイント)
Date: 2008/12/10(水) 16:34
No:25492
|
|
Title: C++(std::string とconst char*と char*についてとそれらのタイプ変換について)
|
|
どうもこんにちは。いつもお世話になります(_ _)
C++初心者の者です。
宿題や仕事ではないのですが、個人的な実験で、VisualC++でC++のstringからC stringへのタイプ変換をしようといろいろ試みているのですが、うまくいきません。以下のやり方で試してみましたが、どれも駄目でした。
どうすればよいでしょうか…?
また、std::stringとconst char*の違いは何なのでしょうか?以下のコードのエラーを見て頂けるとお分かりになるかと思うのですが、最初に=とc_str()を使ったときには、stringがconst char*型なので、char*型であるC stringには変換できないとエラーが出ました。なので次はconst char*型のパラメータを受け取るstrcpy関数を試してみたのですが、今度は、stringがstd::string型なので、const char*には変換できないというエラーが出ました…。
string cplString = "aaaa";
char* cStr;
cStr =(cplString.c_str());//これだと、cannot convert from 'const char *' to 'char *' というエラー。
strcpy(cStr, cplString);//これは、cannot convert parameter 2 from 'std::string' to 'const char *'というエラー。
上二つが駄目だったので、クラス(あまりよくわかっていないのですが…)を使ってみました。これだけはコンパイルはしたのですが、実行中にstrcpyから先へ進めません…。
class cStrMaker
{
public:
cStrMaker::cStrMaker(const char* a)
{
strcpy(cStr,a);//bad pointer cStrというエラー。
}
cStrMaker::~cStrMaker(void)
{
}
private:
char* cStr;
};
std::string strStdString ("Hello!");
cStrMaker cString(strStdString.c_str ());
わかりにくい説明ですみません(_ _)
助けてくれる方がいるととても有難いです。
524ポイント を手に入れた。
|
|
|
|
Name: Mist ..プログラマー(35,409ポイント)
Date: 2008/12/10(水) 16:58
No:25493
|
|
Title: Re:C++(std::string とconst char*と char*についてとそれらのタイプ変換について)
|
|
cStrはポインタで実体がないから、strcpy(cStr,a)なんてすればメモリ破壊しています。
string cplString = "aaaa";
char* cStr;
cStr =(char*)(cplString.c_str());
一応これでいいと思うけど、このあとcStrに何かをしようというのであればその内容によってはかなり危険です。
100ポイント を手に入れた。
|
|
|
|
|
Name: 御津凪 [URL] ..熟練のプログラマー(45,054ポイント)
Date: 2008/12/10(水) 17:03
No:25494
|
|
Title: Re:C++(std::string とconst char*と char*についてとそれらのタイプ変換について)
|
|
const char* は、内部の変更が出来ない char* 型です。
つまり、 std::string の c_str() で受け取ったデータはそのまま変更することが出来ない(読み取り専用)ということです。
Mist さんの方法でコンパイルは通りますが、おっしゃっているとおり使い方によっては危険です。
77ポイント を手に入れた。
|
|
|
|
|
Name: ouh ..かけだし(2,054ポイント)
Date: 2008/12/10(水) 17:28
No:25496
|
|
Title: Re:C++(std::string とconst char*と char*についてとそれらのタイプ変換について)
|
|
char* cStr;
について new, delete は使いたくない。
だからといって
char cStr[定数];
というのも嫌。
cStr を変更したときの cplString に対する危険も避けたい。
その逆も避けたい。
ということだとすると、なんか手詰まりなような...
私もいい方法あったら知りたいです。
2倍のポイントを手に入れた! 278ポイント を手に入れた。
|
|
|
|
|
Name: GPGA ..熟練のプログラマー(55,435ポイント)
Date: 2008/12/10(水) 17:38
No:25497
|
|
Title: Re:C++(std::string とconst char*と char*についてとそれらのタイプ変換について)
|
|
>ouhさん
最初からstd::stringを使えばよいだけでは?
29ポイント を手に入れた。
|
|
|
|
|
Name: GPGA ..熟練のプログラマー(55,587ポイント)
Date: 2008/12/10(水) 17:53
No:25499
|
|
Title: Re:C++(std::string とconst char*と char*についてとそれらのタイプ変換について)
|
|
string変換先を、生ポインタでやるか、vector使うかくらいしかないですね。
// その1
class cStrMaker
{
public:
cStrMaker(const char* a) : cStr(NULL) {
cStr = new char[strlen(a) + 1];
strcpy(cStr, a);
}
~cStrMaker(void) {
delete[] cStr;
}
private:
char* cStr;
};
// その2
class cStrMaker
{
public:
cStrMaker(const char* a) : cStr(strlen(a) + 1) {
strcpy(&cStr[0], a);
}
~cStrMaker(void) {}
private:
std::vector<char> cStr;
};
152ポイント を手に入れた。
|
|
|
|
|
Name: ななし ..ぴよぴよ(353ポイント)
Date: 2008/12/10(水) 18:03
No:25500
|
|
Title: Re:C++(std::string とconst char*と char*についてとそれらのタイプ変換について)
|
|
std::string から char 配列に変換して、char 配列に手を加えた上で再度 std::string に渡すには、
std::string str("abcde");
char* p = (char*)std::malloc((str.size() + 1) * sizeof(char)); // char 配列の領域を確保
std::strcpy(p, str.c_str()); // std::string の文字列を char 配列にコピー
p[2] = 'z'; // ちょっと書き換える
str = p; // str に変更した文字列を反映
std::free(p); // char 配列の領域を解放
こんな感じでしょうか。
ただ、これをするぐらいなら直接書き換えた方が楽です。
std::string str("abcde");
str[2] = 'z';
ちなみに cStrMaker で実行時エラーになるのは、cStrMaker::cStr のポインタの指す先が存在していないからです。
malloc なり new なりで cStr の指す先を確保してやるべきでしょう。
211ポイント を手に入れた。
|
|
|
|
|
Name: LaL ..ぴよぴよ(981ポイント)
Date: 2008/12/10(水) 18:12
No:25501
|
|
Title: Re:C++(std::string とconst char*と char*についてとそれらのタイプ変換について)
|
|
返信皆さん親切なアドバイスありがとうございます(_ _)
>Mistさん。 Mistさんのキャストに、constキャストをつけて、cStr =const_cast<char*>(cplString.c_str()) のように実行してみたのですが、それだと少しは危険度が下がりますでしょうか?実はそもそも、何がどう危険なのかが知識不足の私にはよくわかっていないのですが…(汗)ダウンキャストの危険性という記事は読んできたのですが、stringをC stringに型変更するときの危険性というのが、まだよくわからないのです。
>御津凪さん。 なるほど、です。std::stringは値を変えられるので、const char*ではないのですね。私はc_strという関数についてよく理解していなかったようです。c_strはC string型を返すのではないのですね。
>ouhさん。newを使うというのは、こういうことなのでしょうか?みつけて来ました…cplusplus.comからのコピーです。
char * cstr, *p;
string str ("Please split this phrase into tokens");
cstr = new char [str.size()+1];
strcpy (cstr, str.c_str());
これだと、安全なのですか?
305ポイント を手に入れた。
|
|
|
|
|
Name: ouh ..かけだし(2,243ポイント)
Date: 2008/12/10(水) 18:13
No:25502
|
|
Title: Re:C++(std::string とconst char*と char*についてとそれらのタイプ変換について)
|
|
>GPGAさん
> 最初からstd::stringを使えばよいだけでは?
そうですよね。私もそうします。
でもスレ主さんは char* にしたいということだったものですから。
スレ主さんが new とかしたくないって言ったわけじゃないけど、
なんとなくそういうことかな?って。new 使ったり、char cStr[定数]
もありなら簡単だから質問しに来てないんじゃないかな、と思った
わけです。で、だとしたら手詰まりじゃなかな、と思いました。
※これは言い訳してるのであってGPGAさんに反論しようというつもり
ではないです。お気を悪くされたらすみません。
189ポイント を手に入れた。
|
|
|
|
|
Name: non ..上級者(20,776ポイント)
Date: 2008/12/10(水) 18:21
No:25503
|
|
Title: Re:C++(std::string とconst char*と char*についてとそれらのタイプ変換について)
|
|
中身を変更しないのなら、constにすればいいと思うのですが。。。
const char* cStr;
cStr =(cplString.c_str());
char*で指して、どうしても変更したいのでしょうか。
78ポイント を手に入れた。
|
|
|
|
|
Name: LaL ..かけだし(1,291ポイント)
Date: 2008/12/10(水) 18:29
No:25504
|
|
Title: Re:C++(std::string とconst char*と char*についてとそれらのタイプ変換について)
|
|
>GPGAさん。
コードを書いてくださってありがとうございます(_ _)私はまだまだ初心者なので、コードをきちんと理解する為にあちこち検索してシンタックスの意味を調べたりして、ちょっと時間はかかりますが、お手本のサンプルコードがあると学びやすいです。感謝です。
>ななしさん。
丁寧な解説とコードをありがとうございます(_ _)なるほど、です。そういう風にすると、string型とC string型を、双方向で交換できるのですね。コードの中でまだよくわからないところもあるので、ちょっと調べてみます。
2倍のポイントを手に入れた! 310ポイント を手に入れた。
|
|
|
|
|
Name: ouh ..かけだし(2,374ポイント)
Date: 2008/12/10(水) 18:30
No:25505
|
|
Title: Re:C++(std::string とconst char*と char*についてとそれらのタイプ変換について)
|
|
LaLさんへ
>ouhさん。newを使うというのは、こういうことなのでしょうか?
ちゃんと delete [] をするのを忘れなければそれでOKだと思います。
最初から str のあり得るサイズがあらかじめわかっているなら
char cstr[定数];
strcpy(cstr, str.c_str());
でもいいですしね。
ところで、std::string の文字列のコピーを char* に欲しい、と
いう解釈いいですか?
もしかして私は全くお門違いの解釈で書き込みをしているんでしょう
か?そうだとしたら本当にすみません。私のことは無視してください。
131ポイント を手に入れた。
|
|
|
|
|
Name: LaL ..かけだし(1,463ポイント)
Date: 2008/12/10(水) 18:34
No:25506
|
|
Title: Re:C++(std::string とconst char*と char*についてとそれらのタイプ変換について)
|
|
>ouhさん。
どうも私の質問が妙なもののせいで、すみません(_ _)
newを使えば簡単、というのもまだよくわからないくらい初心者なので…。
申し訳ないです。
>nonさん。
なるほど、です。変更しないのなら、そういうやり方もあるのですね。
一応、変更したいと思ってコードをいじくってはいたのですが、皆さんに教えてもらってやり方がわかって来ました。
172ポイント を手に入れた。
|
|
|
|
|
Name: LaL ..かけだし(1,520ポイント)
Date: 2008/12/10(水) 18:36
No:25507
|
|
Title: Re:C++(std::string とconst char*と char*についてとそれらのタイプ変換について)
|
|
>ouhさん。
ouhさんの解釈は全くその通りです。
いろいろありがとうございます。こちらこそすみません。
57ポイント を手に入れた。
|
|
|
|
|
Name: LaL ..かけだし(1,568ポイント)
Date: 2008/12/10(水) 18:44
No:25508
| 解決!
|
Title: Re:C++(std::string とconst char*と char*についてとそれらのタイプ変換について)
|
|
皆さん、本当にありがとうございました(_ _)
この件については、後は何とか自分で調べていけばわかりそうです。
48ポイント を手に入れた。
|
|
|
|
Name: ioio ..ぴよぴよ(53ポイント)
Date: 2008/12/09(火) 09:47
No:25363
|
|
Title: C言語の因数分解
|
|
C言語の問題でわからないものがあるので、お願いいたします。
問題
入力された正の整数を因数分解して表示するプログラムを作成し、実行結果を張り付けよ。
9桁以下のせいの指数ならばなんでも因数に分解できるようにせよ。
【実行例】実行時にキーボードから入力したのは051547というかずだけである。
---------------------------------------------------------------
因数に分解します。
2桁以上の整数を入力してください。(9桁以下にしてください):071504
71504= 2^4
*= 41^1
*= 109^1
--------------------------------------------------------------
このような実行例がのっています。
この入力する数字を「051547」へ変換してプログラムを組みたいと思うのですが、どなたか教えていただけませんでしょうか?
53ポイント を手に入れた。
|
|
|
|
Name: non ..上級者(18,477ポイント)
Date: 2008/12/09(火) 09:59
No:25364
|
|
Title: Re:C言語の因数分解
|
|
素因数分解の方法にはいろんな方法があります。
ioioさんは、どんな方法で素因数分解をしますか?
プログラムでなく、筆算ではどうするかを示してください。
76ポイント を手に入れた。
|
|
|
|
|
Name: ioio ..ぴよぴよ(84ポイント)
Date: 2008/12/09(火) 10:05
No:25365
|
|
Title: Re:C言語の因数分解
|
|
いろいろ調べたところ、
素因数分解するのであれば、
割った余りがゼロかどうかを判別すればよいかと思います。
31ポイント を手に入れた。
|
|
|
|
|
Name: non ..上級者(18,551ポイント)
Date: 2008/12/09(火) 10:31
No:25368
|
|
Title: Re:C言語の因数分解
|
|
それでは、最初に下で示すところまで作って、ソースを添付してください。
@標準入力から整数を入力する(nとしましょう)
Anを2で割り、割り切れるなら、商を新たなnにする。
Bnを出力する。
ここまで作れますか?
74ポイント を手に入れた。
|
|
|
|
|
Name: non ..上級者(19,276ポイント)
Date: 2008/12/09(火) 15:30
No:25395
|
|
Title: Re:C言語の因数分解
|
|
現在、クラスの作り方について勉強中です。
練習問題に使わせてもらいました。
先輩諸氏のクラスの作り方についてアドバイスがありましたら、お願いします。
例えば、一般的にはこんなクラスのメンバーがいいよとか・・・
なお、必要もないのにvectorも使ってみました。
#include <vector>
#include <iostream>
using namespace std;
class Num{
int fact;
int pow;
public:
Num(int);
void inc(void);
void disp(void);
};
Num::Num(int f)
{
fact=f;
pow=0;
}
void Num::inc(void)
{
++pow;
}
void Num::disp(void)
{
cout << '=' << fact << '^' << pow <<endl;
}
int main(void)
{
vector<Num> factor;
int n,n0;
unsigned int i,j;
cout << "整数(9桁以内)=" ;
cin >> n0 ;
n=n0;
i=2;j=0;
while(n!=1){
if(!(n % i)){
Num f(i);
do{
f.inc();
n=n/i;
}while(!(n % i));
factor.push_back(f);
j=0;
}
else
i++;
}
for(i=0;i<factor.size();++i){
i==0?(cout << n0):(cout << '*');
factor[i].disp();
}
return 0;
}
352ポイント を手に入れた。
|
|
|
|
|
Name: 組木紙織 [URL] ..熟練のプログラマー(67,518ポイント)
Date: 2008/12/09(火) 22:33
No:25438
|
|
Title: Re:C言語の因数分解
|
|
C++として気をつけることは
コンストラクタで初期化リストを使うこと
出力でfor_each()アルゴリズムを使うこと(こっちは必ずといったわけでもないですが)
ぐらいだと思います。
今回は気にしなくても問題はないですが、
Numクラスをコピー可能にする/しない
のどちらかにするかはあらかじめきちんと考えておいたほうがいいです。
状況によってはコピーコンストラクタを書く必要があったり
コピー不可にする必要がありますので。
あとはイテレーターが使えたらもっとC++らしいです。
102ポイント を手に入れた。
|
|
|
|
|
Name: non ..上級者(20,193ポイント)
Date: 2008/12/10(水) 12:09
No:25479
|
|
Title: Re:C言語の因数分解
|
|
組木紙織様
ご指導ありがとうございます。
>コンストラクタで初期化リストを使うこと
>出力でfor_each()アルゴリズムを使うこと
この2点を考慮して、作り直しました。
#include <vector>
#include <iostream>
using namespace std;
class Num{
int fact;
int pow;
public:
Num(int f):pow(0),fact(f){}
void inc(void);
void disp(void);
};
void Num::inc(void)
{
++pow;
}
void Num::disp(void)
{
cout << '=' << fact << '^' << pow <<endl;
}
int main(void)
{
vector<Num> factor;
int n,n0;
unsigned int i;
cout << "整数(9桁以内)=" ;
cin >> n0 ;
n=n0;
i=2;
while(n!=1){
if(!(n % i)){
Num f(i);
do{
f.inc();
n=n/i;
}while(!(n % i));
factor.push_back(f);
}
else
i++;
}
i=0;
for each(Num f in factor){
i++==0?(cout << n0):(cout << '*');
f.disp();
}
return 0;
}
for each はBC++5.0では使えませんでしたのでVC++2008で行いました。
コピーコントラクタとイテレータはもう少し勉強してから考えてみます。
99ポイント を手に入れた。
|
|
|
|
Name: ざこ ..入門者(3,387ポイント)
Date: 2008/12/09(火) 19:59
No:25418
|
|
Title: 構造体
|
|
#include <stdio.h>
int main(void)
{
FILE *file;
long buf;
unsigned char buf1[40];
unsigned char buf2;
short buf3;
double buf4;
short n;
file=fopen("ファイル名"."rb");
fread(&buf,sizeof(long),1,file);
printf("図面%0x\n",buf);
fread(&buf2,sizeof(char),1,file);
printf("ファイル%0x\n",buf2);
fread(&buf2,sizeof(char),1,file);
fread(&buf3,sizeof(short),1,file);
printf("ver%0x\n",buf3);
fread(&n,sizeof(short),1,file);
printf("要素数%0x\n",n);
fread(&buf3,sizeof(short),1,file);
printf("type%0x\n",buf3);
fread(&buf4,sizeof(double),1,file);
printf("始点x%7.3f\n",buf4);
fread(&buf4,sizeof(double),1,file);
printf("始点y%7.3f\n",buf4);
fread(&buf4,sizeof(double),1,file);
printf("終点x%7.3f\n",buf4);
fread(&buf4,sizeof(double),1,file);
printf("終点y%7.3f\n",buf4);
fread(buf1,sizeof(char),32,file);
fread(&buf3,sizeof(short),1,file);
printf("最大%0x\n",buf3);
fclose(file);
return 0;
}
これを構造体を使って書き直すとどうなるのでしょうか?
私の考えは・・
typedef struct{
long num;
char fl;
char res;
short ver;
short no;
short type;
double d[4];
char res2[32];
short resc;
}pftest;
int main(void)
{
FILE *file;
pftest ts;
file=fopen("ファイル名","rb");
fread(&ts,sizeof(ts),1,file);
printf("図面%0x\n",ts.num);
printf("ファイル%0x\n",ts.fl);
printf("ver%0x\n",ts.ver);
printf("要素数%0x\n",ts.no);
printf("type:%0x\n",ts.type);
printf("始点X%7.3f\n",ts.d[0]);
printf("始点Y%7.3f\n",ts.d[1]);
printf("終点X%7.3f\n",ts.d[2]);
printf("終点Y%7.3f\n",ts.d[3]);
prtinf("max%0x\n",ts.rec);
fclose(file);
return 0;
}
としてみたのですがエラーはでませんが正常に動きません。
問題が発生した為にこのプログラムを終了します とでます。
どうすればいいのでしょうか
751ポイント を手に入れた。
|
|
|
|
Name: box ..ハッカー(131,578ポイント)
Date: 2008/12/09(火) 20:27
No:25420
|
|
Title: Re:構造体
|
|
> としてみたのですがエラーはでませんが
そうですか?
> prtinf("max%0x\n",ts.rec);
少なくとも、ここでコンパイルエラーが出ます。printfの綴りが違っています。
もし、お手元にあるソースコードではコンパイルエラーが出ないのであれば、
そのソースコードをそっくりそのままコピー&ペーストしてください。
> file=fopen("ファイル名","rb");
「ファイル名」という名前のファイルが存在していますか?
fopen()の戻り値がNULLかどうか(ファイルのオープンが失敗したか成功したか)を
必ずチェックしてください。
174ポイント を手に入れた。
|
|
|
|
|
Name: non ..上級者(19,827ポイント)
Date: 2008/12/09(火) 20:39
No:25423
|
|
Title: Re:構造体
|
|
間違っているかも知れませんが、私の記憶によると、(処理系に依存すると思うけど)
4の倍数でメモリが確保されたと思います。
longは4バイトですが、次のcharは1バイトが2個で2バイト、この後に2バイトの空きが出来て、
shortは2バイトですが、次のshortとの間に2バイトの空きが出来る。
それで、連続して先頭から読み込んでも、間に隙間があるので、うまくいかないのでは。
もしくは、用意したファイルのバイト数と異なっているのでは?
145ポイント を手に入れた。
|
|
|
|
|
Name: ざこ ..入門者(3,485ポイント)
Date: 2008/12/09(火) 21:39
No:25432
|
|
Title: Re:構造体
|
|
ああほとんどコピペなんですが所々変えてるので(もっと長い文だったのですが短縮とか変更とかいろいろ)
無駄に長かったので見やすくする為変更してるんですが・・間違ったらもともこもないですね・・
以後気をつけます。
98ポイント を手に入れた。
|
|
|
|
|
Name: ざこ ..入門者(3,531ポイント)
Date: 2008/12/09(火) 21:43
No:25433
|
|
Title: Re:構造体
|
|
上のほうのプログラムだとうまくいって下の方のプログラムだとうまくいかないんです。
構造体の使い方が間違ってると思うのですが、どうでしょうか。
46ポイント を手に入れた。
|
|
|
|
|
Name: non ..上級者(20,094ポイント)
Date: 2008/12/09(火) 22:10
No:25435
|
|
Title: Re:構造体
|
|
私の意見はスルーですか。
調べるから、データをください。バイナリーエディタもダウンロードしたし。
48ポイント を手に入れた。
|
|
|
|
|
Name: box ..ハッカー(131,583ポイント)
Date: 2008/12/09(火) 22:26
No:25436
|
|
Title: Re:構造体
|
|
> 上のほうのプログラムだとうまくいって下の方のプログラムだとうまくいかないんです。
「ファイル名」という名前のファイルがありますか?
fopen()の戻り値をチェックしていますか?
5ポイント を手に入れた。
|
|
|
|
|
Name: ざこ ..入門者(3,737ポイント)
Date: 2008/12/09(火) 23:14
No:25442
|
|
Title: Re:構造体
|
|
>nonさん
そういうつもりではないんです。私の質問は上のプログラムは正常に稼動します。しかし下のプログラム、
つまり上のプログラムを構造体を使って書くと間違いなので構造体の使い方が間違ってるのかどうか
聞きたかったのです。だからcharとかshortとかの使い方はあっているはずです。
>boxさん
ファイル名の所はファイル名が入っているということです。
戻り値はまだ調べてなかったです。今試せる環境にいないので明日調べます。
>GPGA
ネットはできますので早速調べて見ます。ありがとうございました。
206ポイント を手に入れた。
|
|
|
|
|
Name: たかぎ [URL] ..比類無きプログラマー(75,547ポイント)
Date: 2008/12/10(水) 00:27
No:25450
|
|
Title: Re:構造体
|
|
処理系不明なので正確なことはわかりませんが...
元のソース構造体を用いたソースも、動作が未定義になる箇所があります。
それ以外のことについては何ともいえません。
> boxさん
> prtinf("max%0x\n",ts.rec);
> 少なくとも、ここでコンパイルエラーが出ます。
リンクエラーにはなるかもしれませんが、コンパイルエラーにはなりませんね。
# 広義のコンパイルエラーですが...。
71ポイント を手に入れた。
|
|
|
|
|
Name: レッツ ..ぴよぴよ(434ポイント)
Date: 2008/12/10(水) 01:12
No:25452
|
|
Title: Re:構造体
|
|
まず「何がしたいのか」を文頭に書かないと何がしたいのか意味がわかりづらいです。
26ポイント を手に入れた。
|
|
|
|
|
Name: GPGA ..熟練のプログラマー(55,392ポイント)
Date: 2008/12/10(水) 04:29
No:25456
|
|
Title: Re:構造体
|
|
>lbfuvabさん
nonさんには失礼かもしれないですが、初心者がnonさんの文章読んでも
その内容が、構造体の中のデータ並びのことを指しているとは気付きにくいと思います。
内容が理解できていれば、No:25442のnonさんに対する
ざこさんの返答は、あのような文章にはならないのではないでしょうか?
>ざこさん
検索ですが、「アラインメント」だとCPUのほうの説明が出てきますね。(まぁ、本来はこっちが正しいのですが)
「構造体 アラインメント」で検索してみてください。
120ポイント を手に入れた。
|
|
|
|
|
Name: toyo ..上級者(21,107ポイント)
Date: 2008/12/10(水) 07:53
No:25459
|
|
Title: Re:構造体
|
|
構造体にすると各変数の間に隙間が出来たりします。
そのため構造体にそのままファイルを読み込むには注意が必要です。
構造体の隙間をなくす方法もありますがコンパイラによって違います。
VisualC++の場合は構造体定義の部分を
#pragma pack(push,1)
typedef struct{
long num;
char fl;
char res;
short ver;
short no;
short type;
double d[4];
char res2[32];
short resc;
}pftest;
#pragma pack(pop)
のようにするとうまくいくと思います。
232ポイント を手に入れた。
|
|
|
|
|
Name: ざこ ..入門者(3,646ポイント)
Date: 2008/12/10(水) 09:58
No:25464
|
|
Title: Re:構造体
|
|
成る程、アライメントの事は初めて知りました。丁寧な解説ありがとうございます、GPGAさん,tuyuさん。
上記の#pragmaの部分を入れてみても変わらなかったです。デバッグで調べてみると
fread(&ts,sizeof(ts),1,file);
ここから先が通らないですね。やはりアライメントが問題なような気もしますが、うーん。
ちなみにVC++6.0使っています。
91ポイント を落としてしまった。
|
|
|
|
|
Name: Mist ..プログラマー(35,175ポイント)
Date: 2008/12/10(水) 10:03
No:25465
|
|
Title: Re:構造体
|
|
nonさんの指摘であっていると思いますが
printf("%d\n", sizeof(ts));
として、tsのサイズがどれだけになっているか調べられてみてはどうですか。
あと、「C言語 アライメント」、「C言語 パディング」でググってください。
パディングのなくし方は処理系に依存しますので、実行環境(OS)、開発環境(コンパイラ)を明記してください。
116ポイント を手に入れた。
|
|
|
|
|
Name: たかぎ [URL] ..比類無きプログラマー(76,059ポイント)
Date: 2008/12/10(水) 10:11
No:25466
|
|
Title: Re:構造体
|
|
> printf("%d\n", sizeof(ts));
VC++6.0なら問題ないとは思いますが、上の記述は未定義の動作につながります。
printf("%d\n", (int)sizeof(ts));
↑のようにしてやる必要があります。
51ポイント を手に入れた。
|
|
|
|
|
Name: ざこ ..入門者(3,878ポイント)
Date: 2008/12/10(水) 10:16
No:25467
|
|
Title: Re:構造体
|
|
上から順に見ていくとfread(&ts,sizeof(ts),1,file); でやはりとまります。
ハンドルされていない例外は・・ と出ます。
fread(&ts,sizeof(ts),1,file); ここにブレイクポイント入れてデバッグしてsizeof(ts)の中身を
調べました所、78となっておりピタリです。
そしてその文の下の文つまり printf("図面%0x\n",ts.num); にブレイクポイントを変更してデバッグすると
ハンドルされていない例外は・・と出てとまります。
fread(&ts,sizeof(ts),1,file); → printf("図面%0x\n",ts.num); この間で止まるようです。
OSはwindowsXP 開発環境はVC++6.0です。
232ポイント を手に入れた。
|
|
|
|
|
Name: 御津凪 [URL] ..熟練のプログラマー(44,977ポイント)
Date: 2008/12/10(水) 10:24
No:25468
|
|
Title: Re:構造体
|
|
> ハンドルされていない例外は・・ と出ます。
ファイルが開けていないとかいうオチじゃないでしょうか。
fread のところでブレイクポイントをつけて、
file の値が NULL (または0)になっていないか確認してください。
あと、アラインメント問題には直接関係しませんが、
fread(&ts,sizeof(ts),1,file);
を、
fread(&ts,1,(int)sizeof(ts),file);
としても読み込めるので、試してみてはどうでしょうか。
70ポイント を手に入れた。
|
|
|
|
|
Name: ざこ ..入門者(3,970ポイント)
Date: 2008/12/10(水) 10:34
No:25470
| 解決!
|
Title: Re:構造体
|
|
すいません、なんかファイルはちゃんと開けてたみたいなんですがそのファイルがおかしかったようです。
別のファイルだとちゃんと動きました。壊れてたのかどうかわかりませんが、とりあえず解決しました。
ありがとうございました。
2倍のポイントを手に入れた! 92ポイント を手に入れた。
|
|
|
|
Name: XOR ..ぴよぴよ(145ポイント)
Date: 2008/12/09(火) 23:45
No:25444
|
|
Title: 「サンプルプログラム実行用フォルダ」の中身
|
|
導入のところで困っています。
「サンプルプログラム実行用フォルダ」を開いて、中に入っている「DxLib.sln」というファイルを開く。
と書いてあるのですが、「DxLib.sln」というファイルが中に入っていません。
「DxLib_VC2008_and_2005用.sln」というファイルはあるのですが、開いても何も起きません。
Microsoft Visual C++ 2008 Express Editionはインストールしてあります。
初歩的な部分などを聞いてしまってすいません。
どうすればよいでしょうか?
145ポイント を手に入れた。
|
|
|
|
Name: XOR ..ぴよぴよ(187ポイント)
Date: 2008/12/10(水) 00:12
No:25447
| 解決!
|
Title: Re:「サンプルプログラム実行用フォルダ」の中身
|
|
自己解決しました。
何も気にせず、DXライブラリの設定に進んでも大丈夫でした。
42ポイント を手に入れた。
|
|
|
|
Name: ナオミチ ..ぴよぴよ(129ポイント)
Date: 2008/12/09(火) 20:16
No:25419
|
|
Title: 文字列の反転について
|
|
学校の宿題でプログラムの宿題が出て、自分なりのプログラムを作ってみました。
おかしな点があれば教えてください。
○問題
文字配列bufferに文字列をキーボードより入力し、入力された文字列を反転させて出力する。ただし、終了条件はqまたはQが入力された時とする。
・出力例
input ? abcd123
反転出力 321dcba
input ? 123456789
反転出力 987654321
input ? q
終了しました。
です。よろしくお願いします。
129ポイント を手に入れた。
|
|
|
|
Name: non ..上級者(19,859ポイント)
Date: 2008/12/09(火) 20:44
No:25424
|
|
Title: Re:文字列の反転について
|
|
ランさんのスレッド「文字列の反転について」とまったく同じです。
同一人物でないなら、同じ大学の課題です。
32ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) [URL] ..伝説なるハッカー(918,897ポイント)
Date: 2008/12/09(火) 20:54
No:25426
|
|
Title: Re:文字列の反転について
|
|
誰と誰が別人をよそおって質問しているかは普段言わないのですが、明らかにわかってしまっているので、また、
メールの連絡が頂けないのでここで言いますが、
色んな名前を使って投稿する事や、用事が済んだら投稿記事を消して何もいわずに去っていくのはやめて下さい。
コンピュータの情報がわかるので、名前を変えてもこちらでわかりますし、
消しても投稿・編集した時点で投稿記事はこちらにバックアップが残っています。
このことをいうのはもう3回目だと思います、以前私が書いたコメントは読んでいただけたでしょうか?
規約を守って利用して下さい。
87ポイント を落としてしまった。
|
|
|
|
|
Name: non ..上級者(20,046ポイント)
Date: 2008/12/09(火) 20:57
No:25427
|
|
Title: Re:文字列の反転について
|
|
すみません。ちゃんと、自分で解いてましたね。良く読まず、失礼しました。
昔、すでに回答が載せてあったものですから。
プログラム見ました。間違いはありません。
方法はいろいろあるし、これはこれでいいのではないかと思います。
ただ、大学で課題が出たというのでしたら、その目的があるはずです。
例えば、関数を学んだとかポインタを学んだとかです。それらの確認のための課題としたら
先生が出した意図を理解していないということになり、評価が低くなる可能性があります。
もし、ポインタを学んだのでしたら、先のスレッドの中に書いてある、「ポインタについて」の
スレッドに確かムンバさんのプログラムが載っているはずです。
187ポイント を手に入れた。
|
|
|
|
|
Name: ナオミチ ..ぴよぴよ(177ポイント)
Date: 2008/12/09(火) 20:59
No:25429
|
|
Title: Re:文字列の反転について
|
|
管理人さん。申し訳ございません。
終わったのを残しておくと邪魔になると思い消していました。すみません。
以後気をつけます。
48ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) [URL] ..伝説なるハッカー(919,139ポイント)
Date: 2008/12/09(火) 21:07
No:25430
|
|
Title: Re:文字列の反転について
|
|
・・・また、投稿記事が変わっていますが・・・。
むやみに編集する事もなるべくしないで欲しいと規約に書いてあります。
と言うのも、例えば今でいうとnonさんのご回答下さった記事が質問文に対して意味がわからなくなるからです。
その他にも、例えば「そのプログラムの3行目がおかしいですよ」と誰かが回答したとして、その後でそのプログラムが正しいものに変えられると
後から見た人が「いや間違ってないですよ」みたいなおかしなコメをつけたりと、やり取りがおかしくなったりする可能性があります。
投稿記事にミスがあった時などは、直後なら編集してもいいと思いますが、
既にレスがついた時などは次の投稿で訂正するなどして下さい。
162ポイント を手に入れた。
|
|
|
|
|
Name: ムンバ ..上級者(15,682ポイント)
Date: 2008/12/09(火) 23:14
No:25443
| 解決!
|
Title: Re:文字列の反転について
|
|
こんばんは。お世話になります。
ちょっと待って下さい。(激汗
nonさん
>「ポインタについて」の スレッドに確かムンバさんのプログラムが載っているはずです。
この(反転する)プログラムは「猫でもわかるC言語プログラミング」<2008年9月3日(略)発行
著者、粂井さんの書籍内に搭載されていたサンプルプログラムを、丸々コピーさせて頂いたものです。
(練習問題の模範解答内のソースではありませんので、あえて違う方法で解いてみたかったのです。^^;)
私の記載漏れです。
誤解を招く様な記載、申し訳御座いませんでした。
パスワードを入れ忘れてなければ修正できると思うので、その旨、追加してみます。
「猫でもわかる C言語プログラミング」参考書引用
もし追加できなければ管理人さん、大変お忙しい中、お手数をお掛けしますが
お時間のある時にでも、追加修正頂けたらと思います。すみません。
>こちらのトピはこれで終わりにしておきましょう。
との事なので、勝手では御座いますが「解決マーク」付けさせて頂きます。
申し訳御座いませんでした。(謝
440ポイント を手に入れた。
|
|
|
|
Name: GFD ..ぴよぴよ(114ポイント)
Date: 2008/11/29(土) 23:44
No:24765
|
|
Title: 妹紅の不死「火の鳥 -鳳翼天翔-」の作り方
|
|
私は今、色々なオリジナルスペルカードを作っていますが、妹紅の不死「火の鳥 -鳳翼天翔-」をまねたものを作ろうとしましたがどうしても、鳥の形がうまくいきませんでした。
もしお時間がありましたら、ご返答のほどよろしくお願いいたします。
114ポイント を手に入れた。
|
|
|
|
Name: Dixq (管理人) [URL] ..伝説なるハッカー(901,064ポイント)
Date: 2008/11/30(日) 02:24
No:24771
|
|
Title: Re:妹紅の不死「火の鳥 -鳳翼天翔-」の作り方
|
|
ここのHPで公開している四聖龍神録Plusのファンタズムステージに出てくる文字弾幕のように、
座標と弾のデータを読み込んで表示する方法はどうでしょう?
多分複雑な形になると手入力では難しくなると思います。
もしまずは手入力でということなら、まず弾5つでブーメランみたいな形を作ってみましょう。
{ 0, 0},//中心
{-30, 0},//左
{ 0,-30},//上
{ 30, 0},//右
{ 0, 30},//下
これで大きさ半径30のブーメランみたいな形に出来ますよね。
これ手入力で鳥の形になるようにしてみましょう。
鳥の向きは座標変換で角度を変えて発射できます。
座標回転については線形代数で計算に計算出来ます。
http://www.metro-hs.ac.jp/rs/sinohara/zahyou_rot/zahyou_rotate.htm
これが出来たら、マウスクリックで、その場所のデータを保存するようなツールを作り、
お絵かきソフトみたいなツール作ってみて、弾で絵を書いて座標データを作ってみてはどうでしょう。
697ポイント を手に入れた。
|
|
|
|
|
Name: GFD ..ぴよぴよ(105ポイント)
Date: 2008/12/01(月) 20:37
No:24864
|
|
Title: Re:妹紅の不死「火の鳥 -鳳翼天翔-」の作り方
|
|
lbfuvabさんが言うソースとはC言語のことですか?
それとDixqさんが教えてくれた作り方なんですが、出し方は理解しました。
ですが、プログラミングの書き方がまったくわかりません。申し訳ございません。
失礼ですが、できたら弾幕の出し方を教えてください。
よろしくお願い致します。
105ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) [URL] ..伝説なるハッカー(903,187ポイント)
Date: 2008/12/01(月) 21:18
No:24868
|
|
Title: Re:妹紅の不死「火の鳥 -鳳翼天翔-」の作り方
|
|
う〜んと、どの辺までできてるのか、現在の仕様がどうなってるのか、どういうプログラムで実現するのかがわからないので、適確に答えるのは難しいですが、
弾幕を作っているということは、上で示したように
{ 0, 0},//中心
{-30, 0},//左
{ 0,-30},//上
{ 30, 0},//右
{ 0, 30},//下
の座標に弾を登録することはできますよね。
まず出来る事からやってみて、つまったらどこでつまったか教えて下さい。
上の登録が出来たら、上の弾を中心から30度回転した座標に登録することを試みてみましょう。
それができたら複雑な座標で実現してみるなど、少しずつ作ってみて下さい。
もし具体的なアドバイスを希望されるならコードを提示するとか、アルゴリズムを詳しく書くなどしないと難しいと思います。
313ポイント を手に入れた。
|
|
|
|
|
Name: GFD ..ぴよぴよ(537ポイント)
Date: 2008/12/01(月) 21:41
No:24871
|
|
Title: Re:妹紅の不死「火の鳥 -鳳翼天翔-」の作り方
|
|
//アシスト作成
if(t==0){
//針弾発射
assist_way(boss.x-25, boss.y, 1, bossatan2(), PI2, 3, 2, 6, 0, 420);
assist_way(boss.x-15, boss.y+30, 1, bossatan2(), PI2, 3, 2, 6, 0, 420);
assist_way(boss.x, boss.y+60, 1, bossatan2(), PI2, 3, 2, 6, 0, 420);
assist_way(boss.x+15, boss.y+30, 1, bossatan2(), PI2, 3, 2, 6, 0, 420);
assist_way(boss.x+25, boss.y, 1, bossatan2(), PI2, 3, 2, 6, 0, 420);
se_flag[39]=1;//シャラーン音1を鳴らす
}
このように、発射位置をずらしてから撃っています。アシスタントを使っています。
ちなみに、プログラミングはSouthから学んだものです。
他はあまりやっていません。(シューティング関係のプログラミングは一通り見ました。)
最大の疑問なんですが、どうやったらこれで↓X,Y座標が求められるんですか?
423ポイント を手に入れた。
|
|
|
|
|
Name: GFD ..ぴよぴよ(0ポイント)
Date: 2008/12/01(月) 23:55
No:24877
|
|
Title: Re:妹紅の不死「火の鳥 -鳳翼天翔-」の作り方
|
|
すみません。文章が途中で消えてました。パスワードも忘れてしまい編集が出来ません。
ですので続きを書きます。
最大の疑問なんですが、どうやったらこれで↓X,Y座標を求められるんですか?
{ 0, 0},//中心
{-30, 0},//左
{ 0,-30},//上
{ 30, 0},//右
{ 0, 30},//下
125ポイント を落としてしまった。
|
|
|
|
|
Name: array [URL] ..プログラマー(39,192ポイント)
Date: 2008/12/02(火) 00:32
No:24879
|
|
Title: Re:妹紅の不死「火の鳥 -鳳翼天翔-」の作り方
|
|
Southを更新してる者です。参考にしてもらってるみたいで非常に嬉しく光栄です。
assist_wayを使ってるみたいなので、一応・・・書き忘れたので説明すると当り判定がありません。
なので、意図して当り判定を無効化したい時以外は使うのをお勧めしません。
> 最大の疑問なんですが、どうやったらこれで↓X,Y座標を求められるんですか?
> { 0, 0},//中心
> {-30, 0},//左
> { 0,-30},//上
> { 30, 0},//右
> { 0, 30},//下
多分これは座標を求めるのではなく、座標に配置するんだと思います。assist_wayを使うなら
中心{ 0, 0} =assist_way( boss.x , boss.y ・・・・が中心なら
左{-30, 0} =assist_way( boss.x - 30, boss.y ・・・・
としていけば、ブーメランの形に配置されるんじゃないかと思います。
200ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) [URL] ..伝説なるハッカー(903,965ポイント)
Date: 2008/12/02(火) 01:02
No:24881
|
|
Title: Re:妹紅の不死「火の鳥 -鳳翼天翔-」の作り方
|
|
既にarrayさんが仰っているので必要ないかもしれませんが、
X,Yを求めるのではなく、相対的な位置関係を表しています。
typedef struct{
double x,y;
}xy_t;
xy_t xy[5]={
{ 0, 0},//中心
{-30, 0},//左
{ 0,-30},//上
{ 30, 0},//右
{ 0, 30},//下
};
と、配列に入れておいたとすると
ボスの中心に十字の形に弾を上記の位置関係で配置するならば
for(i=0; i<5; i++){
assist_way( boss.x + xy[i].x, boss.y + xy[i].y, ...
}
とすれば、合計5つ、ボスの位置を基準に十字の形に配置できますよね。
この相対的な位置関係を表す座標情報を作ってやればいいわけです。
100個で表すなら100個のデータを作ってやり、for文で100回まわしましょう。
やり方はこれじゃなくてもいいのでしょうけど、参考になればどうぞ。
373ポイント を手に入れた。
|
|
|
|
|
Name: 藍 ..初心者(7,386ポイント)
Date: 2008/12/02(火) 14:54
No:24910
|
|
Title: Re:妹紅の不死「火の鳥 -鳳翼天翔-」の作り方
|
|
オリジナル弾幕を作ろうとしていたらいつの間にか鳳凰を作っていた(ぁ
弾幕の話が出るとつい作りたくなってしまうから困る
こんな感じですかねぇ 弾の画像が微妙で すっごい微妙にしか見えませんが
しかし、問題点が1つこれ動かないんですよね〜(笑
理由は簡単プログラムが違うからではなくプログラムが無いからなんですけどね。
これはただの絵です。
kazuoniさんが作られたツールを使って作ったものです。
kazuoniさんのツールでは画像の座標を出力してくれるので・・後は座標をプログラムに反映させるだけですね。
妹紅の不死「火の鳥 -鳳翼天翔-」作成がんばってください!
254ポイント を手に入れた。
|
|
|
|
|
Name: GFD ..ぴよぴよ(659ポイント)
Date: 2008/12/03(水) 23:56
No:25011
|
|
Title: Re:妹紅の不死「火の鳥 -鳳翼天翔-」の作り方
|
|
いつもお世話になっております。
Dixqさんへ
教えた通りにプログラミングを作ってみました。
それっぽく見えてみましたが、斜めや横になると鳥の形がずれてしまいました。
これは直せるんでしょうか?
度々恐れ入りますが、よろしくお願い致します。
念のためプログラムを載せておきます。
//鳥弾の構造体
typedef struct{
double x,y;
}xy_t;
xy_t xy[11]={
{ 0, 0},
{ 0, 20},
{ 0, 40},
{ 0,-20},
{ 0,-40},
{ 20,-10},
{ 40,-30},
{ 60,-50},
{-20,-10},
{-40,-30},
{-60,-50},
};
//鳥弾のアシスタント
if(t==0){
for(i=0; i<11; i++){
assist_way( boss.x+xy[i].x, boss.y+xy[i].y, 1, bossatan2(), PI2, 2, 3, 0, 0, 0);
}
}
自分的には結構当っていると思います。
arrayさんへ
arrayさんのプログラムはこんな感じでしょうか?
if(==0){
assist_way( boss.x, boss.y, 1, bossatan2(), PI2, 2, 3, 0, 0, 0);
assist_way( boss.x-30, boss.y, 1, bossatan2(), PI2, 2, 3, 0, 0, 0);
assist_way( boss.x, boss.y-30, 1, bossatan2(), PI2, 2, 3, 0, 0, 0);
assist_way( boss.x+30, boss.y, 1, bossatan2(), PI2, 2, 3, 0, 0, 0);
assist_way( boss.x, boss.y+30, 1, bossatan2(), PI2, 2, 3, 0, 0, 0);
}
もしこんな感じだと、ずれました。
間違っていたら訂正の方を、どうかよろしくお願い致します。
みなさまへ
誰でもいいので、動画の載せ方(というより作り方)を知っている人がいましたら
どうか教えてください。
今のままですと画像しか載せる事しか出来ません。
659ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) [URL] ..伝説なるハッカー(907,682ポイント)
Date: 2008/12/04(木) 01:20
No:25014
|
|
Title: Re:妹紅の不死「火の鳥 -鳳翼天翔-」の作り方
|
|
・・・と言うだけじゃ解りにくいかもしれませんので、計算してくれる関数作ってみました。
void CoordinateRotation(
double *x, double *y, const double x0, const double y0, const double angle){
double ox = *x - x0, oy = *y - y0;
*x = ox * cos( angle ) - oy * sin( angle );
*y = ox * sin( angle ) + oy * cos( angle );
*x += x0;
*y += y0;
}
*x には回転したい座標の入った変数のアドレス
*x には回転したい座標の入った変数のアドレス
x0 には回転したい中心座標の入った変数のアドレス
y0 には回転したい中心座標の入った変数のアドレス
angle には回転したい角度
を渡してください。
試しに、最初(1,1)である座標を(0,1)を中心に45°ずつ回転して座標を表示するサンプルを書いてみました。
#include <stdio.h>
#include <math.h>
#define PI 3.14159265358979323846
void CoordinateRotation(
double *x, double *y, const double x0, const double y0, const double angle){
double ox = *x - x0, oy = *y - y0;
*x = ox * cos( angle ) - oy * sin( angle );
*y = ox * sin( angle ) + oy * cos( angle );
*x += x0;
*y += y0;
}
int main(){
int i;
double x = 1, y = 1;
double boss_x = 0, boss_y = 1;
for(i=0; i<9; i++){
printf("%3d°回転 : (%5.2f,%5.2f)\n",45*i,x,y);
CoordinateRotation( &x, &y, boss_x, boss_y, PI/4 );
}
return 0;
}
実行結果
0°回転 : ( 1.00, 1.00)
45°回転 : ( 0.71, 1.71)
90°回転 : ( 0.00, 2.00)
135°回転 : (-0.71, 1.71)
180°回転 : (-1.00, 1.00)
225°回転 : (-0.71, 0.29)
270°回転 : (-0.00, 0.00)
315°回転 : ( 0.71, 0.29)
360°回転 : ( 1.00, 1.00)
325ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) [URL] ..伝説なるハッカー(907,841ポイント)
Date: 2008/12/04(木) 03:42
No:25019
|
|
Title: Re:妹紅の不死「火の鳥 -鳳翼天翔-」の作り方
|
|
動画の撮り方ですが、DxtoryやDxrecなどを使って撮影されると良いでしょう。
撮った動画はそのままでは重過ぎるので、ムービーメーカなど適当な動画編集ソフトで編集します。
後は100MBまでにおさえてニコニコやyoutubeにアップロードすればみんなに見せることが出来ます。
ニコニコに高画質でアップするには色々工夫がいるので、興味があれば
検索して調べてみて下さい。
159ポイント を手に入れた。
|
|
|
|
|
Name: yu ..入門者(3,165ポイント)
Date: 2008/12/04(木) 23:14
No:25106
|
|
Title: Re:妹紅の不死「火の鳥 -鳳翼天翔-」の作り方
|
|
横から入ってきて申し訳ないのですが、
一点から弾を発射し、管理者様があげてくれた動画のように、
どんどん弾の速度が上がり、絵が見えてくるようにするには
どのように弾の角度と速度を決めているのでしょうか?
その座標と中心座標の距離と角度ですか?
自分は管理者様の絵、文字の弾幕を初めて見たとき興味が湧いて、
今、このように作り方を説明していましたので
とても興味があり質問させていただきました。
新しく投稿したほうがよかったですかね・・・
すみません m(_ _;)m
178ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) [URL] ..伝説なるハッカー(910,295ポイント)
Date: 2008/12/04(木) 23:35
No:25107
|
|
Title: Re:妹紅の不死「火の鳥 -鳳翼天翔-」の作り方
|
|
>yuさん
ありがとうございます。
じゃ、ちょっと館の方今から作ってみようと思います。
少々お待ち下さいm(_ _)m
ご質問の回答としては、そうです、中心座標との角度です。
中心から広がっているように見える弾は、実は最初から全て座標が違う場所にあります。
それが1ピクセル未満なので、同じにみえるだけです。
大きな文字や絵の座標データも全て-1〜1で表現しています。
double型は非常に小さい値まで正確に表現できるので、例えば非常に細かい値の座標
(0.1,0.1)
にある座標でも45°、と言った具合にきちんと中心との角度が計算できるんですね。
後は、中心との距離によってスピードを変化させてやれば、外にあるのは速く、中心に近いのはゆっくり広がるので、その形を維持したまま広がるのです。
例えば(0.1,0.1)にある座標データの弾は、(1,1)にある座標データの弾の1/10のスピードで広がれば形を維持できますね。
質問は細かい事きにせずジャンジャンしてくださって大丈夫です。
トピも気軽に立てて下さい。
207ポイント を手に入れた。
|
|
|
|
|
Name: yu ..入門者(3,258ポイント)
Date: 2008/12/04(木) 23:53
No:25108
|
|
Title: Re:妹紅の不死「火の鳥 -鳳翼天翔-」の作り方
|
|
なるほど〜
座標の値が小さすぎて
画像を表示する位置が同じになるんですね・・・
すごいですね〜
自分では、いつまで経ってもこのようなものは
頭で作り方が浮かばないと思います・・・。
わざわざ館で説明をしていただき
本当にありがとうございます。
93ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) [URL] ..伝説なるハッカー(910,876ポイント)
Date: 2008/12/05(金) 00:56
No:25109
|
|
Title: Re:妹紅の不死「火の鳥 -鳳翼天翔-」の作り方
|
|
・・・と言っておいてごめんなさい・・・。
先日OSを再インストールしたんですが、そのプログラムのバックアップ取ってなくて消してしまったようです(汗
と言う事で、すぐには作れそうにないので、作ったツールだけUPします。
http://dixq.net/zip/bbs/tool.zip
「作成」フォルダに「漢字データ作成ツール.exe」があるのでそれを起動します。
すると龍鱗と書かれた画像が表示されますね。
ウィンドウの大きさは自由に変形できるので、画面いっぱい大きくします。
弾座標を作りたいところで一度クリックします。
すると赤線がひっぱられるので、任意の位置でもう一度クリックします。
するとその時の直線上に弾が連続で表示されます。
こうして裏にある画像に沿って弾をおいていきます。
その場に一つだけ弾をおきたい時はダブルクリックすればOKです。
こんな感じになっていきますので、この文字の書き順の通りに書いていきます。
Zキーを押すと一度だけ操作を元に戻せます。
弾を置いた順番が書き順になるので、後から違う場所を補正する事はで来ません。
一筆で作って下さい。
出来たらEscを押すと終了します。
同時にoutput.datが出来ます。
font.pngはこの下地ですので、この画像を変えることでどんな文字も作れます。
何も参考にせずにかけるなら画像は必要ありません。
どんなデータが出来たか確認するには、
作ったdatファイルを「確認」フォルダにうつし、確認.exeを起動すると確認出来ます。
じゃ、ちょっと館のコードで実行できるようにしてみます。
581ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) [URL] ..伝説なるハッカー(911,070ポイント)
Date: 2008/12/05(金) 01:33
No:25111
|
|
Title: Re:妹紅の不死「火の鳥 -鳳翼天翔-」の作り方
|
|
ごめんなさい、ちょっとやることがあるので、あまり説明とかかけませんでした;
こちらに実行できる形にしたサンプル置いておきますのでよければ見て下さい。
http://dixq.net/zip/bbs/Ryujin_sample.zip
龍神録の館と同じ構造です。
void boss_shot_bulletH012()
に漢字弾幕を作っておきました。
漢字データは
#define FONT_REM_MAX 1000
typedef struct{
int n;
double x,y;
}fontp_t;
fontp_t fontp[1][FONT_REM_MAX];
こうして用意した構造体に最大1000個まで登録出来ます。
先ほどのツールでは弾の登録は1000個が限界です。
ごめんなさい、詳しいアルゴリズムは
void boss_shot_bulletH012() の
プログラムコードをご覧下さい^^;
194ポイント を手に入れた。
|
|
|
|
|
Name: yu ..入門者(3,404ポイント)
Date: 2008/12/05(金) 23:10
No:25174
|
|
Title: Re:妹紅の不死「火の鳥 -鳳翼天翔-」の作り方
|
|
ありがとうございます。m(_ _)m
かなり参考になっています。
気になった点は
typedef struct{
int n;
double x,y;
}fontp_t;
の
n の部分です。
これには何が入っていますか?
上記に書いてある書き順ですか?・・・
龍鱗.dat 内を見れないので分かりませんでした;
今度、自分でbmpから値を抜き出して弾幕化してみます。
自分でどこまでできるか分かりませんが・・・
146ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) [URL] ..伝説なるハッカー(911,992ポイント)
Date: 2008/12/05(金) 23:20
No:25176
|
|
Title: Re:妹紅の不死「火の鳥 -鳳翼天翔-」の作り方
|
|
n は書き順です。
好きなように設定出来るように番号が付けられるようになっていますが、
この時点では特に配列要素番号と変わりありません。
ただ、配列要素番号1以降にnが0だとそれは弾情報が無い事をあらわします。
なお、文字弾幕はこのように自分で座標データを一つ一つ作って表現しています。
書き順が関係するのでどうしても画像から一発で変換というわけにいかなかったのです。
一方、絵弾幕は書き順が関係ないので、BMPファイルから一発変換しています。
なので、漢字弾幕と絵弾幕はデータの作り方が違うんですよね。
そして、
龍燐.datから読み込んで構造体に入ったデータはデバッグすることで自動変数にて確認できます。
212ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) [URL] ..伝説なるハッカー(912,097ポイント)
Date: 2008/12/05(金) 23:27
No:25177
|
|
Title: Re:妹紅の不死「火の鳥 -鳳翼天翔-」の作り方
|
|
あ、、古い判定式が残ってました。
boss_shot_bulletH012()関数内の
if(fontp[fnum][i].x<=-1 || (fontp[fnum][i].x==0 && fontp[fnum][i].y==0 && fontp[fnum][i+1].x==0 && fontp[fnum][i+1].y==0))break;
これじゃオーバーフローするので、i番目の弾情報があるかどうかは、さっき言った、iが0より大きいとき、nが0かどうかで判定して下さい。
(例)
if( i!=0 && fontp[fnum][i].n==0 ) break;
105ポイント を手に入れた。
|
|
|
|
|
Name: yu ..入門者(4,200ポイント)
Date: 2008/12/05(金) 23:31
No:25178
|
|
Title: Re:妹紅の不死「火の鳥 -鳳翼天翔-」の作り方
|
|
>龍燐.datから読み込んで構造体に入ったデータはデバッグすることで自動変数にて確認できます。
そうでした。orz
エラーが出たらいつも調べているのですが・・・。
忘れていました。すみません;
そして、質問した後でしたが、
if(t%5==0){
if((k=search_boss_shot())!=-1){
boss_shot.bullet[k].col = 9;
boss_shot.bullet[k].x = boss.x+fontp[0][i].x*100;
boss_shot.bullet[k].y = boss.y+fontp[0][i].y*100;
boss_shot.bullet[k].knd = 4;
boss_shot.bullet[k].angle= 0;
boss_shot.bullet[k].flag = 1;
boss_shot.bullet[k].cnt = 0;
boss_shot.bullet[k].spd = 0;
boss_shot.bullet[k].state= 0;
boss_shot.bullet[k].eff= 1;
i++;
}
のように試してみたら
書き順通りに弾が配置されました。
自分で確かめればわかったことを質問して申し訳ないです。m(_ _;)m
2倍のポイントを手に入れた! 796ポイント を手に入れた。
|
|
|
|
|
Name: GFD ..ぴよぴよ(800ポイント)
Date: 2008/12/06(土) 00:08
No:25181
|
|
Title: Re:妹紅の不死「火の鳥 -鳳翼天翔-」の作り方
|
|
ご返事が遅くなり申し訳ございません。
しばらく休んでいる間に、話がずれてきてると思いますので、要点をまとめます。
Dixqさんのありがたい解説により、不死「火の鳥 -鳳翼天翔-」がもう少しで出来そうです。
ですが、弾の位置が固定されても、鳥の形が向きを変えてくれないので苦戦しています。
Dixqさんの教えて頂いた角度のプログラムを使ってみましたが、鳥の形のアシスタントに、
角度のプログラムを合わせる事が出来ません。
たびたび申し訳ございませんが、よろしくお願い致します。
P.S
もしかしたらDixqさんは、龍神録の館でこのプログラムに似たような弾幕を考えていますか?
263ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) [URL] ..伝説なるハッカー(912,774ポイント)
Date: 2008/12/06(土) 00:24
No:25182
|
|
Title: Re:妹紅の不死「火の鳥 -鳳翼天翔-」の作り方
|
|
>yuさん
いえいえ、注釈も入ってないコード投げ渡したような形になってすみませんm(_ _;)m
イメージコンバートエンジンなんて偉そうな名前付けてますけど、
なんてことないアルゴリズムで簡単に出来るので気軽に挑戦してみてください。
とりあえずビットマップから各ピクセルの色情報取ってくるプログラムが出来たら、
ビットマップの色情報を2値化します。
R+G+Bにおいて、0+0+0が真っ黒、255+255+255が真っ白、だから128+128+128位を閾値にすればいいと思います。
キレイな仕上がりにする為に、予めもとの画像を二値化しておくことをおすすめします。
後は、白地に黒で線画を書き
(絵は緑青黒羽さん制作:http://murakumo2nd.web.fc2.com/index.htm)
こんな画像を用意し、黒いピクセルに弾座標をおいていきます。
・・が!全ての黒のピクセルに弾をおくととんでもなく密集してしまうので、
今おこうとしている座標から半径5ピクセル以内に登録した座標がなければ登録・・と言った具合に
調整しながらおきます。
この半径は任意に変更できるようにした方が調整しやすいでしょう。
制作結果
>GFDさん
考え方、そして計算してくれる関数も示しましたので後アドバイスをしてしまうと
もうマンマ答えになってしまいそうです。
答えをお教えすることは簡単なのですが、それでは今後の為にならないかもしれません・・。
今どの辺がわかりませんか?
座標の回転については理解できましたか?
「(2,2)の座標を(4,3)を基準に67°回転したらいくらになるか」と言われたら答えられますか?
解らないところを潰していけば正解に繋がってくると思います。
677ポイント を手に入れた。
|
|
|
|
|
Name: Dixq (管理人) ..伝説なるハッカー(918,786ポイント)
Date: 2008/12/09(火) 18:32
No:25412
|
|
Title: Re:妹紅の不死「火の鳥 -鳳翼天翔-」の作り方
|
|
すごくコアなネタなんですが、
四聖龍神録Plusのオマケ弾幕、リリア・アイシャの弾幕で、弾幕の色が「緑→青→黒→白」と変化しますよね。
最後の色「白」についてですが、
上の画像の中央にあるように、アイシャの白い弾幕は実は小さな白い「羽」なんです。
つまり「緑→青→黒→羽」と変化しているんです。
何を意味しているかというと、この絵を描いてくれた人は・・・。
107ポイント を手に入れた。
|
|
|
|
|
Name: 藍 ..初心者(7,557ポイント)
Date: 2008/12/09(火) 20:37
No:25421
|
|
Title: Re:妹紅の不死「火の鳥 -鳳翼天翔-」の作り方
|
|
なんという隠れ設定
とりあえずDixqさんが
イメージコンバートエンジンなんて偉そうな名前付けてますけど、
なんてことないアルゴリズムで簡単に出来るので気軽に挑戦してみてください。
とあったので、チャレンジしてみましたー
なかなか作るのが楽しかったです!
89ポイント を手に入れた。
|
|
|
|
|
Name: GFD
Date: 2008/12/15(月) 20:30
No:247651229340652
| 解決!
|
Title: Re:妹紅の不死「火の鳥 -鳳翼天翔-」の作り方
|
|
Dixqへ
何とか理解しようとしましたが、お手上げでした。
なので、友達にこのことを聞いてみると、以下のようなプログラミングを作ってくれました。
//指定座標2を中心に指定座標1を角度で回転させる関数x用-追加19
double x_Rotation(
double x, double y, const double x0, const double y0, const double angle){
double re_x;//x返す用-追加19
double ox=x-x0, oy=y-y0;//指定座標1と指定座標2の距離を調べる
//ここで指定角度で座標を回転させる↓
re_x=ox*cos(angle)-oy*sin(angle);//x座標の計算
//指定位置1から出すための調整↓
re_x+=x0;//x座標を調整
return re_x;//計算した値を返す-追加19
}
このプログラミングを使うと、見事に向きを変えてくれました。
これで「火の鳥 -鳳翼天翔-」が何とか出来上がりました。
大変長い間ありがとうございました。
今、自分は色々とスペルカードを作っているので、また疑問の壁にぶち当たり、わからなくなって
質問することがあると思いますが、その時もどうぞよろしくお願い致します。
|
|
|
|
|