初心者です。サンプル改造で質問です。

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

初心者です。サンプル改造で質問です。

#1

投稿記事 by G桜花 » 13年前

DXライブラリを使っています。
http://homepage2.nifty.com/natupaji/DxL ... m.html#N21
こちらのサンプルプログラムを改造して
学習プログラムを作ろうとしています。
一問一答形式で
ログが残って入力中の文字もでるこのプログラムを改造し作ろうと思いました。
一応われなりにいろいろ変えてみましたがエラーは出ないのにデバッグすると起動後入力領域と文字出力領域の線も引かずにプログラムが強制的に落とされます。
どこが原因なのか全くわかりません教えてください。
コードは以下↓です。
#include "DxLib.h"
#include <string.h>
#define CHAT_LINENUM 20 // チャット中の文字列を表示する行数#define MAX_STRLENGTH 80 // チャットで1行で入力できる文字数
#define INPUT_LINE 21 // チャットで入力領域となる画面上の行位置
#define FONT_SIZE 16 // フォントのサイズ

int InputHandle ; // 入力ハンドル
int StringY ; // 文字列表示領域の次に文字列を表示する時の行位置

char ScreenString[ CHAT_LINENUM ][ MAX_STRLENGTH + 1 ] ; // 画面に表示中のチャット文字列


int ScreenStringAdd( char *AddString ) ; // チャット文字列を追加する
int ScreenStringDraw( void ) ; // チャットの現在の状態を画面に表示する


int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
ChangeWindowMode( TRUE );
SetWindowPos( GetMainWindowHandle() , HWND_TOPMOST, 0, 0, 300, 300, (SWP_SHOWWINDOW |SWP_NOSIZE) );
char Key ;

// DXライブラリ初期化
if( DxLib_Init() == -1 )
{
return -1 ;
}

// 入力領域と文字出力領域との境界線を引く
DrawLine( 0 , CHAT_LINENUM * FONT_SIZE , 640 , CHAT_LINENUM * FONT_SIZE , GetColor( 255 , 255 , 255 ) ) ;
// 文字列入力ハンドルを作成する
InputHandle = MakeKeyInput( 80 , FALSE , FALSE , FALSE ) ;

// 作成した入力ハンドルをアクティブにする
SetActiveKeyInput( InputHandle ) ;

/*
// どちらのキーが押されるか監視する
{
while( !ProcessMessage() )
{
if( CheckHitKey( KEY_INPUT_Z ) )
{
Key = 'Z' ;
break ;
}
if( CheckHitKey( KEY_INPUT_X ) )
{
Key = 'X' ;
break ;
}
}
}
*/
int i;
char q[100][255];
char ans[100][255];
FILE *fin;
if ((fin = fopen("test.txt", "r ")) == NULL){
ScreenStringAdd("開かないぞゴラァ");
}
for (i = 0; i<100; i++) {
fgets(q,100,fin); // 一行ずつ読み込む
fgets(ans,100,fin);
}


char buff[256];
ScreenStringAdd("表示される日本語の英語表記を入力してください。\n文字は全て小文字でスペースなどを含まないでください。");
for(int i = 0 ; i < 100 ; i++)
{
ScreenStringAdd(">");//問題

// 文字列入力
{
// 文字列の入力が終っている場合は送信する
if( CheckKeyInput( InputHandle ) == 1 )
{
int StrLength ;

// 入力された文字列を取得する
GetKeyInputString( buff, InputHandle ) ;
// 自分のとこにも表示する
ScreenStringAdd( buff ) ;

// 入力文字列を初期化する
SetKeyInputString( "" , InputHandle ) ;

// 再度インプットハンドルをアクティブにする
SetActiveKeyInput( InputHandle ) ;
}
// 画面に入力中の文字列を描画する
DrawBox( 0 , INPUT_LINE * FONT_SIZE + 2 , 640 , 480 , 0 , TRUE ) ;
DrawKeyInputString( 0 , INPUT_LINE * FONT_SIZE + 2 , InputHandle ) ;
DrawKeyInputModeString( 640 , 480 ) ;
}
//fgets(buff,100,stdin);//文字を受け取る
buff[strlen(buff) - 1] = '\0';//改行(\n)を消去
ans[strlen(ans) - 1] = '\0';//改行(\n)を消去
ScreenStringAdd(ans);
ScreenStringAdd(buff);
if(strcmp(buff,ans) ==0)//比較
ScreenStringAdd("Good!!");//正解
else{
ScreenStringAdd("Bad…");//はずれ
ScreenStringAdd(ans);
}
}
DxLib_End() ; // DXライブラリ使用の終了処理

return 0 ; // ソフトの終了
}

// チャット文字列を追加する
int ScreenStringAdd( char *AddString )
{
// 格納する行を一つ進める
StringY ++ ;

// もし表示領域下いっぱいに来ていた場合はスクロールさせる
if( StringY == CHAT_LINENUM )
{
int i ;

for( i = 1 ; i < CHAT_LINENUM ; i ++ )
lstrcpy( ScreenString[ i - 1 ] , ScreenString[ i ] ) ;

ScreenString[ i - 1 ][ 0 ] = '\0' ;

StringY -- ;
}

// 文字列を格納する
lstrcpy( ScreenString[ StringY ] , AddString ) ;

// 画面の内容を描画する
ScreenStringDraw() ;

// 終了
return 0 ;
}

// チャットの現在の状態を画面に表示する
int ScreenStringDraw( void )
{
int i ;

// 文字列表示域を黒で塗りつぶす
DrawBox( 0 , 0 , 640 , CHAT_LINENUM * FONT_SIZE , 0 , TRUE ) ;

// すべてのチャット文字列を描画する
for( i = 0 ; i < CHAT_LINENUM ; i ++ )
DrawString( 0 , i * FONT_SIZE , ScreenString[ i ] , GetColor( 255 , 255 , 255 ) ) ;

// 終了
return 0 ;
}


よろしくお願いします。
ちなみにcode /codeとすると

コード:

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

#define CHAT_LINENUM		20	// チャット中の文字列を表示する行数
#define MAX_STRLENGTH		80	// チャットで1行で入力できる文字数
#define INPUT_LINE		21	// チャットで入力領域となる画面上の行位置
#define FONT_SIZE		16	// フォントのサイズ

int InputHandle ;			// 入力ハンドル
int StringY ;				// 文字列表示領域の次に文字列を表示する時の行位置

char ScreenString[ CHAT_LINENUM ][ MAX_STRLENGTH + 1 ] ;	// 画面に表示中のチャット文字列


int ScreenStringAdd( char *AddString ) ;	// チャット文字列を追加する
int ScreenStringDraw( void ) ;			// チャットの現在の状態を画面に表示する


int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
						LPSTR lpCmdLine, int nCmdShow )
{
	ChangeWindowMode( TRUE );
	SetWindowPos( GetMainWindowHandle() , HWND_TOPMOST, 0, 0, 300, 300, (SWP_SHOWWINDOW |SWP_NOSIZE) ); 
	char Key ;

	// DXライブラリ初期化
	if( DxLib_Init() == -1 )
	{
		return -1 ;
	}

	// 入力領域と文字出力領域との境界線を引く
	DrawLine( 0 , CHAT_LINENUM * FONT_SIZE , 640 , CHAT_LINENUM * FONT_SIZE , GetColor( 255 , 255 , 255 ) ) ;
	// 文字列入力ハンドルを作成する
	InputHandle = MakeKeyInput( 80 , FALSE , FALSE , FALSE ) ;

	// 作成した入力ハンドルをアクティブにする
	SetActiveKeyInput( InputHandle ) ;

/*
	// どちらのキーが押されるか監視する
	{
		while( !ProcessMessage() )
		{
			if( CheckHitKey( KEY_INPUT_Z ) )
			{
				Key = 'Z' ;
				break ;
			}
			if( CheckHitKey( KEY_INPUT_X ) )
			{
				Key = 'X' ;
				break ;
			}
		}
	}
*/
	int i; 
	 char q[100][255];
	 char ans[100][255];
	 FILE *fin;
	 if ((fin = fopen("test.txt", "r ")) == NULL){
		 ScreenStringAdd("開かないぞゴラァ");
	 }
	 for (i = 0; i<100; i++) {
			 fgets(q[i],100,fin); /* 一行ずつ読み込む */
			 fgets(ans[i],100,fin); 
	 }

	
	 char buff[256];
	  ScreenStringAdd("表示される日本語の英語表記を入力してください。\n文字は全て小文字でスペースなどを含まないでください。");
	 for(int i = 0 ; i < 100 ; i++)
	 {
		 ScreenStringAdd(">");//問題

		 // 文字列入力
		{
			// 文字列の入力が終っている場合は送信する
			if( CheckKeyInput( InputHandle ) == 1 )
			{
				int StrLength ;

				// 入力された文字列を取得する
				GetKeyInputString( buff, InputHandle ) ;
				// 自分のとこにも表示する
				ScreenStringAdd( buff ) ;

				// 入力文字列を初期化する
				SetKeyInputString( "" , InputHandle ) ;

				// 再度インプットハンドルをアクティブにする
				SetActiveKeyInput( InputHandle ) ;
			}
			// 画面に入力中の文字列を描画する
			DrawBox( 0 , INPUT_LINE * FONT_SIZE + 2 , 640 , 480 , 0 , TRUE ) ;
			DrawKeyInputString( 0 , INPUT_LINE * FONT_SIZE + 2 , InputHandle ) ;
			DrawKeyInputModeString( 640 , 480 ) ;
		}
		 //fgets(buff,100,stdin);//文字を受け取る
		 buff[strlen(buff) - 1] = '\0';//改行(\n)を消去
		 ans[i][strlen(ans[i]) - 1] = '\0';//改行(\n)を消去
		 ScreenStringAdd(ans[i]);
		  ScreenStringAdd(buff);
		 if(strcmp(buff,ans[i]) ==0)//比較
			 ScreenStringAdd("Good!!");//正解
		 else{
			  ScreenStringAdd("Bad…");//はずれ
			  ScreenStringAdd(ans[i]);
		 }
	 }
	 DxLib_End() ;			// DXライブラリ使用の終了処理

	return 0 ;			// ソフトの終了
}

// チャット文字列を追加する
int ScreenStringAdd( char *AddString )
{
	// 格納する行を一つ進める
	StringY ++ ;

	// もし表示領域下いっぱいに来ていた場合はスクロールさせる
	if( StringY == CHAT_LINENUM )
	{
		int i ;

		for( i = 1 ; i < CHAT_LINENUM ; i ++ )
			lstrcpy( ScreenString[ i - 1 ] , ScreenString[ i ] ) ;

		ScreenString[ i - 1 ][ 0 ] = '\0' ;

		StringY -- ;
	}

	// 文字列を格納する
	lstrcpy( ScreenString[ StringY ] , AddString ) ;

	// 画面の内容を描画する
	ScreenStringDraw() ;

	// 終了
	return 0 ;
}

// チャットの現在の状態を画面に表示する
int	ScreenStringDraw( void )
{
	int i ;

	// 文字列表示域を黒で塗りつぶす
	DrawBox( 0 , 0 , 640 , CHAT_LINENUM * FONT_SIZE , 0 , TRUE ) ;

	// すべてのチャット文字列を描画する
	for( i = 0 ; i < CHAT_LINENUM ; i ++ )
		DrawString( 0 , i * FONT_SIZE , ScreenString[ i ] , GetColor( 255 , 255 , 255 ) ) ;

	// 終了
	return 0 ;
}

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

Re: 初心者です。サンプル改造で質問です。

#2

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

ちゃんとウィンドウ処理と描画を行うには、裏画面をつかわない場合はひとつの方法としてWaitTimer()を区切りとして定期的に呼び出す必要があります。
そうしないと画面には何も反映されません。このプログラムにはそれが無いのが一番大きな問題です。
他にも問題があるのですが、とりあえずWaitTimer()を入れてみてください。

【補足】
王道としてはSetDrawScreen( DX_SCREEN_BACK );で裏画面処理をして、
・ProcessMessage(); メッセージ処理を行います。
・ClearDrawScreen(); 画面のクリアを行います。
・ScreenFlip(); 裏画面を表画面に反映します。
の3つの処理を呼び出すのが良いと思います。

「1.9章 ゲームプログラムの骨格の完成」
http://dixq.net/g/01_09.html
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

G桜花
記事: 2
登録日時: 13年前

Re: 初心者です。サンプル改造で質問です。

#3

投稿記事 by G桜花 » 13年前

ソフト屋さん解答ありがとうございます。
URLのページにあります
while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){

の中に処理を書けばいいという情報通りにしたところ起動して線を引いて・・・
そして勝手に私が入力してないのに判定を始めてしまいました。
そして回答も何も入ってない変数を表示させようとした時に出る
フフフフフフフ
という文字が出てきました。
まったくもってどうすればいいのかわかりません
WaitTimer(3000);というのを導入しようとして先ほどのwhile文をのけて
DxLib_End() ;の一行前につけましたが応答停止してしまいます。何が問題なのでしょうか?

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

Re: 初心者です。サンプル改造で質問です。

#4

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

クイックリファレンスを見て欲しいのですが、WaitTimer(3000);だと3000msで3秒間停止します。
http://homepage2.nifty.com/natupaji/DxL ... other.html
それとetDrawScreen( DX_SCREEN_BACK );でwhile( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){の処理とWaitTimer(3000);の1つのプログラムには混ぜて書かないでください。最初の投稿にWaitTimer(100);程度を入れるだけで良いです。

それと初心者には、
InputHandle = MakeKeyInput( 80 , FALSE , FALSE , FALSE ) ;
系の入力は難しいので「KeyInputString」をオススメします。
http://homepage2.nifty.com/natupaji/DxL ... .html#R5N9
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

閉鎖

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