添削をお願いします

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

添削をお願いします

#1

投稿記事 by KSGK » 10年前

C++とDXLIBで時計を作りました。
短くできる点、いらない点などを教えてください。

それと、コードの半分くらいのところにある、時計の針の/180.0のところを/180とすると、針が動かなくなります。
なぜでしょうか。

コード:

#include "DxLib.h"
#include <math.h>

DATEDATA Date;
int Cr = GetColor(255,255,255);
int Cr2 = GetColor(0,0,0);
double PI = 3.141592653589793;

//3大処理
int ProcessLoop(){
	if(ProcessMessage()!=0)return -1;
	if(ClearDrawScreen()!=0)return -1;
	return 0;
}


void Watch(){	 
	
	 DrawCircle( 320 , 240 , 200 , Cr,FALSE ) ; //
	 DrawCircle( 320 , 240 , 205 , Cr,FALSE ) ;//時計のまわり
	 
	 int num=0;
	 for (double i = 0; i<=11; i++){
	 DrawFormatString(cos((-90+i*30)*PI/180)*170-3 + 320 ,sin((-90+i*30)*PI/180)*170-3 + 240 , Cr , "%d", num++ );//文字
	 }
	 
	 DrawLine(320,240 ,320+cos((Date.Sec-15)*6/180.0*PI)*180,240+sin((Date.Sec-15)*6/180.0*PI)*180,Cr,1);//秒針  180.0を180にすると動かなくなる
	 
	 DrawLine(320,240 ,320+cos((Date.Min-15)*6/180.0*PI+((Date.Sec)*6/180.0*PI)/60)*160,240+sin((Date.Min-15)*6/180.0*PI+((Date.Sec)*6/180.0*PI)/60)*160,Cr,3);//分針 
	 
	 DrawLine(320,240 ,320+cos((Date.Hour-3)*30/180.0*PI+((Date.Min)*6/180.0*PI)/12)*120,240+sin((Date.Hour-3)*30/180.0*PI+((Date.Min)*6/180.0*PI)/12)*120,Cr,5);//時針
     
	 DrawCircle( 320 , 240 , 3 , Cr, TRUE ) ;  //
	 DrawCircle( 320 , 240 , 2 , Cr2, TRUE ) ;//中心
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow){
	ChangeWindowMode(TRUE);
	if(DxLib_Init() == -1 )return -1;
			
		while(ProcessLoop()==0){
			
			GetDateTime( &Date ) ;// 現在時刻を得る
			DrawFormatString( 5, 7, Cr, "%d年%d月%d日%d時%d分%d秒", Date.Year,Date.Mon,Date.Day,Date.Hour,Date.Min,Date.Sec) ;//時刻
			Watch();
			
		}
		DxLib_End();
        return 0;
}
※製作主 :Dixq
 サークル名:RemicalSoft
 サイト名 :サンプルプログラミングの館
 こちらの太鼓の鉄人のサンプルを参考にさせていただきました。ありがとうございました


 

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 添削をお願いします

#2

投稿記事 by みけCAT » 10年前

読んで考えてみようと思いますが、とりあえず
ゼリー さんが書きました:それと、コードの半分くらいのところにある、時計の針の/180.0のところを/180とすると、針が動かなくなります。
なぜでしょうか。
C++では、整数同士の演算は小数点以下が切り捨てられ、整数で結果が返るからです。
まだ実行していませんが、例えば29秒から30秒になる時に動きませんか?
【追記】実行しました。秒針は44秒から45秒になる時に動きました。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
KSGK
記事: 9
登録日時: 10年前

Re: 添削をお願いします

#3

投稿記事 by KSGK » 10年前

なるほど、180だと
(Date.Sec-15)*6/180
までが整数になってしまうということですね。
式の中に一つでも少数が入っていればいいと思っていました。

回答ありがとうございます。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 添削をお願いします

#4

投稿記事 by みけCAT » 10年前

とりあえず改良してみました。
  • どうせ使っていないWinMain関数の引数の名前はいらない
  • 文字を描画するところで、せっかくiがあるのだからわざわざnumで別に数える必要はない
    また、ループ変数に実数型を使うことは不自然であり、(今回のように整数ならほぼ問題ないが)誤差による不都合の原因にもなる
  • PIが実数なので、/180.0*PIの代わりに*PI/180とすると、(ほぼ)同じ計算結果で文字数が削れる
  • そもそもPI/180が大量にあるので、変数に入れる
  • 円周率と度数をラジアンに変換するための定数は定数にする
  • 日付と色はグローバル変数にしない(これは好み?)
  • 時計の中心座標が何回も出てくるので変数にする
  • 文字を描画するところだけ中心座標が後ろにあったので、前に統一する

コード:

#include "DxLib.h"
#include <math.h>

const double PI = 3.141592653589793;
const double d2r = PI/180;

//3大処理
int ProcessLoop(){
	if(ProcessMessage()!=0)return -1;
	if(ClearDrawScreen()!=0)return -1;
	return 0;
}


void Watch(const DATEDATA& Date,int Cr,int Cr2){
	int cx = 320;
	int cy = 240;	 
	
	DrawCircle( cx , cy , 200 , Cr,FALSE ) ; //
	DrawCircle( cx , cy , 205 , Cr,FALSE ) ;//時計のまわり
	 
	for (int i = 0; i<=11; i++){
		double charAngle = (-90+i*30)*d2r;
		DrawFormatString(cx+cos(charAngle)*170-3 ,cy+sin(charAngle)*170-3 , Cr , "%d", i );//文字
	}
 
	double secAngle = (Date.Sec-15)*6*d2r;
	DrawLine(cx,cy ,cx+cos(secAngle)*180,cy+sin(secAngle)*180,Cr,1);//秒針

	double minAngle = (Date.Min-15)*6*d2r+((Date.Sec)*6*d2r)/60;
	DrawLine(cx,cy ,cx+cos(minAngle)*160,cy+sin(minAngle)*160,Cr,3);//分針 

	double hourAngle = (Date.Hour-3)*30*d2r+((Date.Min)*6*d2r)/12;
	DrawLine(cx,cy ,cx+cos(hourAngle)*120,cy+sin(hourAngle)*120,Cr,5);//時針

	DrawCircle( cx , cy , 3 , Cr, TRUE ) ;  //
	DrawCircle( cx , cy , 2 , Cr2, TRUE ) ;//中心
}

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
	ChangeWindowMode(TRUE);
	if(DxLib_Init() == -1 )return -1;

	DATEDATA Date;
	int Cr = GetColor(255,255,255);
	int Cr2 = GetColor(0,0,0);

	while(ProcessLoop()==0){
		
		GetDateTime( &Date ) ;// 現在時刻を得る
		DrawFormatString( 5, 7, Cr, "%d年%d月%d日%d時%d分%d秒", Date.Year,Date.Mon,Date.Day,Date.Hour,Date.Min,Date.Sec) ;//時刻
		Watch(Date, Cr, Cr2);
		
	}
	DxLib_End();
	return 0;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
KSGK
記事: 9
登録日時: 10年前

Re: 添削をお願いします

#5

投稿記事 by KSGK » 10年前

針を書くところがさっぱりしてよかったです。気になっていました。

よく出てくる数は変数にしたほうが、ミスも減ってコードも短く見やすくなっていいということですね。

PIを最初に持ってくれば、整数*少数/整数になり、切り捨てられることが無いですね。なるほど。

winmain関数の引数はサンプルにあったのでとりあえず書いてしまいました。いらなかったのですね、

丁寧な回答ありがとうございました。勉強になりました。

アバター
KSGK
記事: 9
登録日時: 10年前

Re: 添削をお願いします

#6

投稿記事 by KSGK » 10年前

解決するのをわすれていました

アバター
Dixq (管理人)
管理人
記事: 1662
登録日時: 14年前
住所: 北海道札幌市
連絡を取る:

Re: 添削をお願いします

#7

投稿記事 by Dixq (管理人) » 10年前

DXライブラリを使ってプログラムを書く際は裏画面処理をするのが基本です。
http://dixq.net/g/h_11.html
こちらにやってはいけないことをまとめていますので参考にしてください。

アバター
KSGK
記事: 9
登録日時: 10年前

Re: 添削をお願いします

#8

投稿記事 by KSGK » 10年前

裏画面処理をするようにできました。
次に作るものでは画像も使うつもりなので、特に4つ目の注意には気を付けます。

ありがとうございました。

閉鎖

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