計算式のバトルについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ルート

計算式のバトルについて

#1

投稿記事 by ルート » 8年前

コード:

#include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
 
int GetRandom(int min,int max);
 
int main(void)
 {
 int a,b,c,answer;
 int my=30,teki=50;
 char name[64],sama[]="";

 printf("プレイヤー名を入力してください---");
 gets(name);
  printf("%s\n");

while( my && teki ) {
 a = GetRandom(0,9);
 b = GetRandom(0,9);
 c = a + b;
 
if(c>10){ /*10以上は表示しないようにしたい*/
	
 continue;
 }
 
  
  
  printf("\t[%s_hp:%d]\t\t\t\t\t\t[teki_hp:%d] \n",strcat(name,sama), my,teki
  );
  printf("\t\t\t teki:「このもんだいをといてみろ」\n");
   printf("\t\t\t\t\t %d+%d=",a,b);

 scanf("%d",&answer);
 

 if(c==answer){
	 printf("\t\t\t\t tekki:「よくといたな」\n""\n"
		 "\t\t\t\t yusya:「かんたんさ!」\n""\n");} else{
		 printf("\t\t\t\t yusya:「むずかしすぎる!!」\n""\n"
			 "\t\t\t\t teki:「そうだろ!」\n""\n");
	 }

if(c==answer) {
 teki=teki-answer;
 my=my+answer;
 } 
else{
 my=my-answer;
}
if(my<=0){
	break;
}


if(teki<=0){
	 break;
}


 }
 
if( teki<=0) printf( "\t\t\t teki: 「お前の勝ちだ・・・」\n" );
if(my<=0) printf("\t\t\t teki:「お前の負けだ!」\n");
 

return 0;
 }

int GetRandom(int min,int max)
 {
 static int flag=0;
 
if(flag==0){
 srand((unsigned int)time(NULL));
 flag=1;
 }
 
return min+(int)(rand()*(max-min+1.0)/(1.0+RAND_MAX));
 }
載せてある、コードはコンソールアプリで作ったものなのですが、
これをDXライブラリを使って表示したいと思っています。
DXライブラリでは、scanf関数や、gets関数は使えるのでしょうか?
また、キーボードが、押されたかということを確かめる関数がDXライブラリにあるのはわかっているのですが、
押したキーの文字を表示させるにはどのようにしたら、よいのでしょうか?

ルート

Re: 計算式のバトルについて

#2

投稿記事 by ルート » 8年前

追記
今載せたプログラムは出された問題を間違えるとHPがーされるようにしてあるのですが、
そのーされる値が、scanfで入力した値なので、ーされるときは、正解の値を引くようにしたいのですが、
どうすればよいでしょか?

non
記事: 1097
登録日時: 9年前

Re: 計算式のバトルについて

#3

投稿記事 by non » 8年前

ルート さんが書きました:追記
今載せたプログラムは出された問題を間違えるとHPがーされるようにしてあるのですが、
そのーされる値が、scanfで入力した値なので、ーされるときは、正解の値を引くようにしたいのですが、
どうすればよいでしょか?
正解の値は、なんという変数に入っているかわかりますか?
その値を引けばいいでしょう。
non

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

Re: 計算式のバトルについて

#4

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

数値ならKeyInputNumber()で入力して、表示はDrawString系を使って下さい。

こっちをチェック ↓
「DXライブラリ置き場 リファレンスページ」
http://homepage2.nifty.com/natupaji/DxLib/dxfunc.html
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

hss12
記事: 40
登録日時: 8年前

Re: 計算式のバトルについて

#5

投稿記事 by hss12 » 8年前

インデントをこのくらいやってもらえませんでしょうか。読みにくいです。

コード:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int GetRandom(int min, int max);

int main(void)
{
	int a, b, c, answer;
	int my=30, teki=50;
	char name[64], sama[]="";

	printf("プレイヤー名を入力してください---");
	gets(name);
	printf("\n");

	while( my && teki ){
		a = GetRandom(0,9);
		b = GetRandom(0,9);
		c = a + b;

		if(c>10){ /*10以上は表示しないようにしたい*/
			continue;
		}

		printf("\t[%s_hp:%d]\t\t\t\t\t\t[teki_hp:%d] \n", strcat(name, sama), my, teki);
		printf("\t\t\t teki:「このもんだいをといてみろ」\n");
		printf("\t\t\t\t\t %d+%d=", a, b);

		scanf("%d", &answer);

		if(c==answer){
			printf("\t\t\t\t tekki:「よくといたな」\n\n"
				   "\t\t\t\t yusya:「かんたんさ!」\n\n");
		}else{
			printf("\t\t\t\t yusya:「むずかしすぎる!!」\n\n"
				   "\t\t\t\t teki:「そうだろ!」\n\n");
		}

		if(c==answer){
			teki-=c;
			my+=c;
		}else{
			my-=c;
		}

		if(my<=0){
			printf("\t\t\t teki:「お前の負けだ!」\n");
			break;
		}

		if(teki<=0){
			printf( "\t\t\t teki:「お前の勝ちだ・・・」\n");
			break;
		}
	}

	return 0;
}

int GetRandom(int min,int max)
{
	static int flag=0;

	if(flag==0){
		srand((unsigned int)time(NULL));
		flag=1;
	}

	return min+(int)(rand()*(max-min+1.0)/(1.0+RAND_MAX));
}

ルート

Re: 計算式のバトルについて

#6

投稿記事 by ルート » 8年前

コード:

#include "DxLib.h"

 
 
 int WINAPI WinMain( HINSTANCE , HINSTANCE,LPSTR , int  )
 {

 DxLib_Init(),ChangeWindowMode(TRUE),SetDrawScreen(DX_SCREEN_BACK);   //ウィンドウモード変更、初期化、裏画面設定

 int a,b,c,ans;
 int my=30,teki=50;
 int white;

while( my && teki && ProcessMessage() == 0 && ScreenFlip()==0  && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) {

white=GetColor(255,255,255);
SRand(10);
 a = GetRand(10);
 b = GetRand(10);
 c = a + b;
 
if(c>10){ /*10以上は表示しないようにしたい*/
	
 continue;
 }
 
  DrawFormatString(0,0,white,"[yusya_hp:%d]", my);
  DrawFormatString(200,0,white,"[teki_hp:%d] ",teki);
  DrawString(200,200," teki:「このもんだいをといてみろ」",white);

   DrawFormatString(200,350,white,"%d+%d=",a,b);

   ans = KeyInputNumber( 0 , 310 , 10, 0 , FALSE ) ;

 if(c==ans){
	 DrawString(200,400,"tekki:「よくといたな」",white);
	 DrawString(200,500,"yusya:「かんたんさ!」",white);
	 } else{
	 DrawString(200,400, "yusya:「むずかしすぎる!!」",white);
	 DrawString(200,500, "teki:「そうだろ!」",white);
	 }

if(c==ans) {
 teki=teki-ans;
 my=my+ans;
 } 
else{
 my=my-c;
}
if(my<=0){
	break;
}


if(teki<=0){
	 break;
}


 }
 
if( teki<=0) DrawString(200,400, "teki: 「お前の勝ちだ・・・」",white );
if(my<=0)    DrawString(200,500,"teki:「お前の負けだ!」",white);
 

return 0;
 }

一応リファレンス見ながら打ってみたのですが、
実行結果成功なのですが、windowだけ表示されて中身が表示されません。
どこか、間違っているのでしょうか?
後、初歩的な質問になるのですが、どうしてwhile文は一つにまとめた方がいいのですか?
複数あったらなにかへんなことでも、起こるのでしょうか?

non
記事: 1097
登録日時: 9年前

Re: 計算式のバトルについて

#7

投稿記事 by non » 8年前

>中身が表示されません。
一番の問題は SRand(10);の場所

>どうしてwhile文は一つにまとめた方がいいのですか?
14行目の処理を常に一定間隔で行いたいから
non

naohiro19
記事: 256
登録日時: 9年前
住所: 愛知県

Re: 計算式のバトルについて

#8

投稿記事 by naohiro19 » 8年前

コード:

DxLib_Init(),ChangeWindowMode(TRUE),SetDrawScreen(DX_SCREEN_BACK); 
ではWindows 7やVIsta環境ではデスクトップ画面がおかしくなります。

コード:

ChangeWindowMode(TRUE),DxLib_Init(),SetDrawScreen(DX_SCREEN_BACK); 
あと

コード:

DxLib_End();
を入れなければパソコン自体が重くなって再起動を余儀なくされるので忘れずに。
DXライブラリを使用しているソフトはすべてソフトを 終了させる前にこの関数を呼ぶ必要があります
 同時に、DXライブラリはソフトのウインドウの制御も しているので、この関数を呼び出した後はなるべくすぐにプログラムを 終了させなければなりません

ルート

Re: 計算式のバトルについて

#9

投稿記事 by ルート » 8年前

コード:

if(c==ans){
	 DrawString(200,400,"tekki:「よくといたな」",white);

	 DrawString(200,500,"yusya:「かんたんさ!」",white);
	 } else{
	 DrawString(200,400, "yusya:「むずかしすぎる!!」",white);
	 DrawString(200,500, "teki:「そうだろ!」",white);
	 }
nonさんの言うとおりSRand(10);をループの外に表示されました。
コードを修正していたりして、また、わからないことがあったので、
わかるかたお願いします。

上のコードは入力値がCと=もしくは!=の場合文が表示しているようにしているのですが、
一応、表示されるには、表示されるのですが、すぐ消えてしまうので、すぐ消えないようにしたいのですが。

hss12
記事: 40
登録日時: 8年前

Re: 計算式のバトルについて

#10

投稿記事 by hss12 » 8年前

インデントがまだそろっていませんがこれもプログラミングのテクニックなので習得してください。
読みにくく回答する人が読む気がなくなり回答が来ない、
バグが発生しやすくなり、また見つけにくいなどのデメリットがあります。
例えば

コード:

main
{
	インデント
	←ここより左には書いてはいけない	
	if( ){
		インデント
		←ここより左には書いてはいけない
	}←閉じた場合この位置
	←次はここから書く
}←閉じた場合この位置
とりあえず、プログラムに対して気になるところでは
既出ですが
ChangeWindowMode(TRUE) //ウィンドウモードに変更

DxLib_Init() //初期化
より先に書いてください。

whileの中の my && teki は何なのでしょうか
(my>0) && (teki>0) と書けば下のほうに書いてある break を書かなくてすむと思うのですが。

white=GetColor(255,255,255); はwhileより上に書いてください
何度も色を代入する必要なないです。1回でいいですよね。
SRand(10); もそうですが
その前にコンソールのランダムはtimeで初期化してランダムにしてましたが
DXライブラリのGetRand() はこの処理を自動的にやってくれるので
そもそもSRand() を書く必要がありません。
逆にSRand(10) なんて書いてしまうとランダムではなくなってしまいます。

また、10以上にしたくないのならcontinue などしなくても
b = GetRand(9-a);
でどうでしょう。このほうが処理が速いと思います。

DrawString(200,500,・・・
と書いていますがウィンドウサイズが標準で640×480なのではみ出して表示されません。

teki=teki-ans

teki-=ans
と書けます。動作は変わらないですが短く書けます。

また無駄なif文が多いのでまとめたほうが良いでしょう。


文字がすぐ消えてしまうのは ClearDrawScreen() を書いたからではありませんか?
これを書いたら消えます。しかし、書かないと文字がどんどん重なってしまうので
とりあえず WaitKey(); を使ってみてはどうでしょう。何かキーを押すまで待機になります。

ということで書いてみました。
入力した数字が分からなくなるのでそれの表示
文字の表示位置の調整
WaitKey(); を書いたのでその上にScreenFlip(); を書きました。
このプログラムだとKeyInputNumberのところで止まってしまうので
裏画面処理する必要はない気もしますが。
if文のまとめ方、インデントの仕方も参考にしてください。

コード:

#include "DxLib.h"

int WINAPI WinMain( HINSTANCE , HINSTANCE,LPSTR , int  )
{
	ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更,初期化,裏画面設定

	int a, b, c, ans;
	int my=30, teki=50;
	int white = GetColor(255,255,255);

	while( (my>0) && (teki>0) && !ProcessMessage() && !ClearDrawScreen() && !CheckHitKey(KEY_INPUT_ESCAPE) ){

		a = GetRand(9);
		b = GetRand(9-a);
		c = a + b;

		DrawFormatString(0, 0, white, "[yusya_hp:%d]", my);
		DrawFormatString(200, 0, white, "[teki_hp:%d] ", teki);
		DrawString(10, 50, "teki:「このもんだいをといてみろ」", white);
		DrawFormatString(50, 100, white, "%d+%d=", a, b);

		ans = KeyInputNumber( 90 , 100 , 10, 0 , FALSE );
		DrawFormatString(90, 100, white, "%d", ans);

		if(c==ans){
			DrawString(10, 150, "tekki:「よくといたな」", white);
			DrawString(10, 200, "yusya:「かんたんさ!」", white);
			teki-=c;
			my+=c;
		}
		else{
			DrawString(10, 150, "yusya:「むずかしすぎる!!」", white);
			DrawString(10, 200, "teki:「そうだろ!」", white);
			my-=c;
		}

		if(my<=0){
			DrawString(10, 250, "teki:「お前の負けだ!」", white);
		}

		if(teki<=0){
			DrawString(10, 250, "teki: 「お前の勝ちだ・・・」", white );
		}

		DrawString(10, 300, "PUSH ANY KEY", white );

		ScreenFlip(); //表示
		WaitKey(); //キー入力待ち
	}

	DxLib_End(); //終了処理
	return 0;
}

ルート

Re: 計算式のバトルについて

#11

投稿記事 by ルート » 8年前

そうすれば、文も表示されるんですね。
それを参考にいろいろ変えていきたいと思います。

後、windowに表示している画像や文を単体で消す方法は可能でしょうか?
例えば、画像が数枚描画されたとして、そのうちの一枚だけを消すというのは、可能でしょうか?
ClearDrawScreen()だと必要なものも消えてしまうのでなにかないでしょうか?

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

Re: 計算式のバトルについて

#12

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

>後、windowに表示している画像や文を単体で消す方法は可能でしょうか?
>例えば、画像が数枚描画されたとして、そのうちの一枚だけを消すというのは、可能でしょうか?
>ClearDrawScreen()だと必要なものも消えてしまうのでなにかないでしょうか?

フレームバッファ・ダブルバッファを利用している場合のDirectXの方式の制限なので諦めるしか無いですね。それを止めると描画時に書き換えが見えたり、チラついて見えたりして見栄えがよく有りませんので基本的に毎回全部表示することが必要です。一部を残して書き換えるのが楽だと思われるかも知れませんが、同時に残したいものを残せない&残って欲しくないものが残るバグの温床になる可能性が高いです。

それと前の質問に問題があったので参考プログラムを紹介してあります。参考にして下さい。
「メイン画面の作り方について・・・・ • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/viewtopic.php?f=3&t=9659

[追記]
>そうすれば、文も表示されるんですね。
>それを参考にいろいろ変えていきたいと思います。
hss12さんも、書いている通り「とりあえずWaitKey(); を使ってみてはどうでしょう。何かキーを押すまで待機になります。」とWaitKey();は一時的な措置なので本格的なゲーム・プログラムには取り入れないようにお願いします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ルート

Re: 計算式のバトルについて

#13

投稿記事 by ルート » 8年前

WaikKey();は確認用でしたね。
忘れてました・・・・・

if文とかint CheckHitKey( int KeyCode ) ;関数を使って試してみましたが、
やっぱり流れてしまいますね;;

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

Re: 計算式のバトルについて

#14

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

前のトピック話題で取り扱っているstateの考え方である状態遷移を使う必要があります。
ゲームでは重要な考え方なので前のトピックで「応用できるほど理解されていますか?」って話をしました。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ルート

Re: 計算式のバトルについて

#15

投稿記事 by ルート » 8年前

コード:


#include "DxLib.h"
int Key[256]; // キーが押されているフレーム数を格納する

enum {
    STATE_TEKI, //敵の文
	STATE_ZIBUN,  //敵の文
};

// キーの入力状態を更新する
int gpUpdateKey()
{
    char tmpKey[256]; // 現在のキーの入力状態を格納する
    GetHitKeyStateAll( tmpKey ); // 全てのキーの入力状態を得る
    for( int i=0; i<256; i++ ){ 
        if( tmpKey[i] != 0 ){ // i番のキーコードに対応するキーが押されていたら
            Key[i]++;     // 加算
        } else {              // 押されていなければ
            Key[i] = 0;   // 0にする
        }
    }
    return 0;
}

//*******************************
//画像のロード
//*******************************
int grf[9];
void g_load()
{
grf[0]=LoadGraph("敵フェイス.png");
grf[1]=LoadGraph("自分フェイス.png");
grf[2]=LoadGraph("文字フェイス.png");
grf[3]=LoadGraph("技選択.png");
grf[4]=LoadGraph("廊下_閉まり1.png");

}
//********************************
//敵の文
//********************************
int teki()
{
     DrawString(10, 150, "teki:「よくといたな」", GetColor(255,255,255));
    if(Key[KEY_INPUT_RETURN]==1)  return TRUE;    //エンターが押されたらTRUE
    return FALSE;   //エンターが押されなければFALSE
}

//********************************
//自分の文
//********************************
int zibun()
{
    DrawString(10, 200, "yusya:「かんたんさ!」", GetColor(255,255,255)); 
    if(Key[KEY_INPUT_RETURN]==1) return 0;  
    return STATE_ZIBUN;    //エンターが押されなければF状態継続
}

 int WINAPI WinMain( HINSTANCE , HINSTANCE,LPSTR , int  )
 {

 ChangeWindowMode(TRUE),SetWindowSize(1000,600),DxLib_Init(),SetDrawScreen(DX_SCREEN_BACK);   //ウィンドウモード変更、初期化、裏画面設定
 
 g_load();

 int a, b, c, ans;
    int my=30, teki=50;
    int white = GetColor(255,255,255);
	int state=STATE_TEKI;
 
    while( (my>0) && (teki>0) && !ProcessMessage() && !ClearDrawScreen() && !CheckHitKey(KEY_INPUT_ESCAPE)&& gpUpdateKey()==0 )
	{
	// すべてのキーの状態を得る
		
DrawGraph(0,0,grf[4],TRUE);
DrawGraph(0,330,grf[0],TRUE);
DrawGraph(310,330,grf[1],TRUE);
DrawGraph(220,330,grf[3],TRUE);



 a = GetRand(10);
 b = GetRand(10);
 c = a + b;
 
if(c>10){ /*10以上は表示しないようにしたい*/
	
 continue;
        }
 
  DrawFormatString(515,370,white,"[yusya_hp:%d]", my);               //自分のHP表示座標
  
  DrawFormatString(105,370,white,"[teki_hp:%d] ",teki);              //敵のHP表示座標
  DrawString(170,10," teki:「このもんだいをといてみろ」",white);    //言葉の表示座標

  DrawFormatString(300,40,white,"%d+%d=",a,b);                     //問題の表示座標

   ans = KeyInputNumber( 350,40, 10, 0 , FALSE ) ;
   
 

     if(c==ans){
     teki=teki-ans;
     my=my+ans;
     switch(state){
	case STATE_TEKI:  //敵の文
	      if( teki() ){
		    state=STATE_ZIBUN;
			}
			break;

	case STATE_ZIBUN:
	       state=zibun();
           break;

		            }

		  
          DrawGraph(250,400,grf[2],TRUE);
	      DrawString(270, 410, "PUSH ANY KEY", white ); 
	      ScreenFlip(); //表示
    
	            }

     if(c!=ans){
       my=my-c;
        
              DrawString(10, 150, "yusya:「むずかしすぎる!!」", white);
			  DrawString(10, 200, "teki:「そうだろ!」", white);
              DrawGraph(250,400,grf[2],TRUE);
              DrawString(27, 410, "PUSH ANY KEY", white );
              ScreenFlip(); //表示
			  }                            
      if( teki<=0) {
    DrawString(200,400, "teki: 「お前の勝ちだ・・・」",white );
	DrawGraph(250,400,grf[2],TRUE);
    DrawString(27, 410, "PUSH ANY KEY", white );
    ScreenFlip(); //表示
    WaitKey(); //キー入力待ち
	         }

if(my<=0){
    DrawString(200,500,"teki:「お前の負けだ!」",white);
	DrawGraph(250,400,grf[2],TRUE);
    DrawString(27, 410, "PUSH ANY KEY", white );
    ScreenFlip(); //表示
    WaitKey(); //キー入力待ち
	      }

  }
 

 DxLib_End();
return 0;
 }
 
こんな感じで打ってみたのですが↓みたいなエラーが出ました。これは、なんですか?
cpp(105): error C2064: 0 引数を取り込む関数には評価されません。

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

Re: 計算式のバトルについて

#16

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

何度も指摘されていますがインデントがすごく汚いです。まず、それを直して下さい。
それとこの場合はtekiに関してはコンパイラは文脈上変数なのか関数名なのか判断できません。同じ名前を付ける場合は名前の付け方に気をつけてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

naohiro19
記事: 256
登録日時: 9年前
住所: 愛知県

Re: 計算式のバトルについて

#17

投稿記事 by naohiro19 » 8年前

ゲームプログラムにおいてWait系やSleep系で止めることは致命的ですので極力使わないようにしてください(参照)。

ルート

Re: 計算式のバトルについて

#18

投稿記事 by ルート » 8年前

今回は、文字表示のプログラムはあきらめます。
またの機会に時間があれば、やりたいと思います。
というのも、コンテストに出すソフトを作っていて、そんなに時間がなくなってきたからです。
いろいろ参考になったこともあったので
ありがとうございました。

閉鎖

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