簡単な野球のプログラムを作っているのですが。。。

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

簡単な野球のプログラムを作っているのですが。。。

#1

投稿記事 by プーコ » 18年前

管理人様、いつもご丁寧にありがとうございます。
以前の1000試合の問題は解決しました!!!!(^^)ありがとうございます!!
作っているうちに楽しくなってきました。。
盗塁を実行させるために何かいい案はないでしょうか??
盗塁も確率で済ませることができるかどうか、悩んでます。。。

管理人

Re:簡単な野球のプログラムを作っているのですが。。。

#2

投稿記事 by 管理人 » 18年前

あ、題名が「簡単な」に変わっている^^;

盗塁に関して、どこまで本格的に作るかですが、現在の得点によったり、その選手の足の速さによったり、次の打者の打率によったりして変わるのではないでしょうか。

最低限でいいのでしたら、選手の足の速さだけは設定してはいかがでしょうか。

「実況!パワフルプロ野球」ってご存知でしょうか?もし本格的に作るのならそういうゲームをモデルに作ってみてはいかがでしょう。

選手にそれぞれステータスが設定されてますよね。
構造体で選手一人一人のデータを設定して、その都度計算すればいいのではないでしょうか。
例えば、盗塁しようとしている選手の足の能力を48とし、捕手の肩の能力を52とします。
数値が高い方が能力が高いとしていたら、4ほど捕手の方が有利だということになります。つまりアウトになる確率が高い。
この数値に依存した確率を計算してやればよいシミュレートが出来そうだと思います。

前回のトピでDXライブラリでサンプルを作ってみましたが、DXライブラリを使ってシミュレートしてみると視覚的にも面白くなると思います。

管理人

Re:簡単な野球のプログラムを作っているのですが。。。

#3

投稿記事 by 管理人 » 18年前

走者の走力と、捕手の肩の力を受け取ると、盗塁が成功する確率を計算するプログラムを作ってみました。
この関数は

・やっぱゲームの確率は曲線を描かないと面白くない
・起こることに100%など無い

という事から、sin波を使った確率を計算する関数です。
-90度~90度は増加することを利用して、確率を求めています。
sin波を+1してやると、
-90度になるにつれ、限りなく0に近づき、90度になるにつれ、限りなく2に近づきます。

走者の能力、捕手の能力は、それぞれ1~100で設定することとします。

差分 = 走 - 肩;

を計算する事で、能力差が-99~99で求まります。これを100で割って、90度をかければ
-99~90が

-90度~90度の数値になります。
後は求まったsin波のy座標を+1してやり、2で割れば最大値1の確率が求まります。

数学的なプログラムは簡単なプログラムでも解りづらくなるので、日本語で書いてみました。
(全角に対応したコンパイラならこのままでコンパイルは通ります)

かえって見難くなってたりして・・・。
#include <stdio.h>
#include <math.h>

#define 90度 3.141592/2

double 確率計算(int 走,int 肩){
	int 差分 = 走 - 肩;
	double 位置= 90度 * (差分/100.0);

	return (sin(位置)+1)/2;
}

int main(){
	int i;
	for(i=1;i<=100;i+=3)
		printf("[走%3d-肩%3d]  確率 = %f\n",i,101-i,確率計算(i,101-i));
}

実行結果

[走  1-肩100]  確率 = 0.000062
[走  4-肩 97]  確率 = 0.003020
[走  7-肩 94]  確率 = 0.010389
・・・(略)
[走 49-肩 52]  確率 = 0.476447
[走 52-肩 49]  確率 = 0.523553
・・・(略)
[走 97-肩  4]  確率 = 0.996980
[走100-肩  1]  確率 = 0.999938
捕手の肩の能力がいい場合は盗塁出来る確率は低く、
走者の走る能力がいい場合は盗塁出来る確率は高くなっています。
お互い50-50の時は、(sin(0度)+1)/2ですから、0.5つまり50%になります。

管理人

Re:簡単な野球のプログラムを作っているのですが。。。

#4

投稿記事 by 管理人 » 18年前

構造体で選手の能力を格納すれば効率よく計算できると思いますよ。
実際には初期化関数で初期化するのではなく、ファイルに選手データを作っておいて、そこから読み込むようにすれば汎用的に成ると思います。
typedef struct{
	char 名前[32];
	double 打率;
	int 力;
	int 走;
	int 肩;
	int 守;
}states_t;

states_t 選手1,選手2;

void 初期化(){

	strcpy(選手1.名前, "イチロー");
	選手1.打率=0.306;
	選手1.力=90;
	選手1.走=70;
	選手1.肩=60;
	選手1.守=75;

	strcpy(選手2.名前, "松井");
	選手2.打率=0.286;
	選手2.力=40;
	選手2.走=80;
	選手2.肩=65;
	選手2.守=65;

}
 
 
それともしよろしければお聞かせ願いたいのですが、
プーコさんはDXライブラリでゲームをお作りなんでしょうか。
それとも野球の詳細なシミュレートを計算し、選手データから今年の勝敗予想をするようなプログラムをお作りなのでしょうか?
私は根っからゲームの方ばかりですが、後者の方もおもしろそうですね。
ただそうなると正確な選手データと、試合を再現するための緻密で膨大な分析が必要そうですね。

プーコ

Re:簡単な野球のプログラムを作っているのですが。。。

#5

投稿記事 by プーコ » 18年前

管理人様、
私は後者の方です!!勝敗予想と言うことではないのですが、確率上で野球をしてみるとおもしろいかと
思ったのです!!(^^)
以前、試合を繰り返すと勝敗結果が偏ると言いましたが、あの問題が解決していませんでした(TT)
添付してみようとしましたが、テキストエディタで作ったプログラムは添付できませんでした(TT)

プーコ

Re:簡単な野球のプログラムを作っているのですが。。。

#6

投稿記事 by プーコ » 18年前

プログラムが大きいのでここに分割して載せてみます(^^)
#include <stdio.h>

#include <stdlib.h>

#include <time.h>

int main()

{

	int g,team,e,o,s[2],b[4],dajun[2],y,x,z;

	float ran0,P[2][9][5];

	srand((unsigned)time( NULL ));

	/*イニング数、アウト数、得点、打順,ベースの状況(b[0]:本塁。b[1]:一塁。b[2]:二塁。b[3]:三塁)の初期設定*/

	e=0;team=0;o=0;s[1]=0;s[0]=0;dajun[0]=1;dajun[1]=1;b[1]=0;b[2]=0;b[3]=0;b[0]=1,g=1,y=0,x=0,z=0;

	
	P[0][0][0]=0.2400;	P[0][0][1]=0.2800;	P[0][0][2]=0.3000;	P[0][0][3]=0.3100;	P[0][0][4]=0.3600;

	P[0][1][0]=0.2400;	P[0][1][1]=0.2800;	P[0][1][2]=0.3000;	P[0][1][3]=0.3100;	P[0][1][4]=0.3600;

	P[0][2][0]=0.2400;	P[0][2][1]=0.2800;	P[0][2][2]=0.3000;	P[0][2][3]=0.3100;	P[0][2][4]=0.3600;

	P[0][3][0]=0.2400;	P[0][3][1]=0.2800;	P[0][3][2]=0.3000;	P[0][3][3]=0.3100;	P[0][3][4]=0.3600;

	P[0][4][0]=0.2400;	P[0][4][1]=0.2800;	P[0][4][2]=0.3000;	P[0][4][3]=0.3100;	P[0][4][4]=0.3600;

	P[0][5][0]=0.2400;	P[0][5][1]=0.2800;	P[0][5][2]=0.3000;	P[0][5][3]=0.3100;	P[0][5][4]=0.3600;

	P[0][6][0]=0.2400;	P[0][6][1]=0.2800;	P[0][6][2]=0.3000;	P[0][6][3]=0.3100;	P[0][6][4]=0.3600;

	P[0][7][0]=0.2400;	P[0][7][1]=0.2800;	P[0][7][2]=0.3000;	P[0][7][3]=0.3100;	P[0][7][4]=0.3600;

	P[0][8][0]=0.2400;	P[0][8][1]=0.2800;	P[0][8][2]=0.3000;	P[0][8][3]=0.3100;	P[0][8][4]=0.3600;

	
	
	P[1][0][0]=0.2400;	P[1][0][1]=0.2800;	P[1][0][2]=0.3000;	P[1][0][3]=0.3100;	P[1][0][4]=0.3600;

	P[1][1][0]=0.2400;	P[1][1][1]=0.2800;	P[1][1][2]=0.3000;	P[1][1][3]=0.3100;	P[1][1][4]=0.3600;

	P[1][2][0]=0.2400;	P[1][2][1]=0.2800;	P[1][2][2]=0.3000;	P[1][2][3]=0.3100;	P[1][2][4]=0.3600;

	P[1][3][0]=0.2400;	P[1][3][1]=0.2800;	P[1][3][2]=0.3000;	P[1][3][3]=0.3100;	P[1][3][4]=0.3600;

	P[1][4][0]=0.2400;	P[1][4][1]=0.2800;	P[1][4][2]=0.3000;	P[1][4][3]=0.3100;	P[1][4][4]=0.3600;

	P[1][5][0]=0.2400;	P[1][5][1]=0.2800;	P[1][5][2]=0.3000;	P[1][5][3]=0.3100;	P[1][5][4]=0.3600;

	P[1][6][0]=0.2400;	P[1][6][1]=0.2800;	P[1][6][2]=0.3000;	P[1][6][3]=0.3100;	P[1][6][4]=0.3600;

	P[1][7][0]=0.2400;	P[1][7][1]=0.2800;	P[1][7][2]=0.3000;	P[1][7][3]=0.3100;	P[1][7][4]=0.3600;

	P[1][8][0]=0.2400;	P[1][8][1]=0.2800;	P[1][8][2]=0.3000;	P[1][8][3]=0.3100;	P[1][8][4]=0.3600;


char name[2][16]={"表 川崎","裏 宗則"};
printf("ーーーーーーーーーーーーー \n\n\n\n\n");
for(g=1;g<=1000;g++)
{
dajun[0]=1;dajun[1]=1;
printf("%d試合目です!!\n\n",g);

for(e=0;e<9;e++)
{
printf("=============================%d回====================================\n\n\n",e+1);
for(team=0;team<2;team++)
{
if(e==8&&team==1&&s[1]>s[0])
{
printf("ここまでの得点が%sの方が高いため、9回裏の%sの攻撃はありません!\n\n",name[team],name[team]);
break;
}
else
{
printf("%d回の%sの攻撃です!!\n",e+1,name[team]);
while(o<3)
{

for(dajun[team];dajun[team]<=9;dajun[team]++)
{
ran0 = rand()/(RAND_MAX+1.0);
if(0.0<ran0&&ran0<P[team][dajun[team]][1])/*ヒット*/
{
/*ランナーなしの時の動き*/
if(b[1]==0&&b[2]==0&&b[3]==0&&b[0]==1)
{
printf(" %d番打者 ヒットです!ランナー一塁!\n",dajun[team]);
b[1]=1;b[2]=0;b[3]=0;b[0]=1;
}
/*ランナー一塁のときの動き*/
else if(b[1]==1&&b[2]==0&&b[3]==0&&b[0]==1)
{
printf(" %d番打者 ヒットです!ランナー一塁二塁!!\n",dajun[team]);
b[1]=1;b[2]=1;b[3]=0;b[0]=1;
}
/*ランナー一塁二塁のときの動き*/
else if(b[1]==1&&b[2]==1&&b[3]==0&&b[0]==1)
{
printf(" %d番打者 ヒットです!満塁!!ランナー満塁!!\n",dajun[team]);
b[1]=1;b[2]=1;b[3]=1;b[0]=1;
}
/*ランナー満塁の時の動き*/
else if(b[1]==1&&b[2]==1&&b[3]==1&&b[0]==1)
{
printf(" %d番打者 ヒットです!一点追加!!なおもランナー満塁!\n",dajun[team]);
b[1]=1;b[2]=1;b[3]=1;b[0]=1;
s[team]=s[team]+1;
}
/*ランナー一塁三塁の時の動き*/
else if(b[1]==1&&b[3]==1&&b[2]==0&&b[0]==1)
{
printf(" %d番打者 ヒットです!一点追加でランナー一塁二塁!\n",dajun[team]);
b[1]=1;b[2]=1;b[3]=0;b[0]=1;
s[team]=s[team]+1;
}
/*ランナー二塁三塁のときの動き*/
else if(b[2]==1&&b[3]==1&&b[1]==0&&b[0]==1)
{
printf(" %d番打者 ヒットです!一点追加でランナー一塁三塁!\n",dajun[team]);
b[1]=1;b[2]=0;b[3]=1;b[0]=1;
s[team]=s[team]+1;
}
/*ランナー二塁のとき*/
else if(b[1]==0&&b[2]==1&&b[3]==0&&b[0]==1)
{
printf(" %d番打者 ヒットです!ランナー2塁3塁!!\n",dajun[team]);
b[1]=0;b[2]=1;b[3]=1;b[0]=1;
}
/*ランナー三塁のとき*/
else if(b[1]==0&&b[2]==0&&b[3]==1&&b[0]==1)
{

printf(" %d番打者 ヒットです!一点追加でランナー一塁!!\n",dajun[team]);
b[1]=1;b[2]=0;b[3]=0;b[0]=1;
s[team]=s[team]+1;
}
}

プーコ

Re:簡単な野球のプログラムを作っているのですが。。。

#7

投稿記事 by プーコ » 18年前

else if(P[team][dajun[team]][1]<ran0&&ran0<P[team][dajun[team]][2])/*ツーベースヒット*/

{
/*ランナーなしの時の動き*/
if(b[1]==0&&b[2]==0&&b[3]==0&&b[0]==1)
{

printf(" %d番打者 ツーベースヒットです!!ランナー二塁!!\n",dajun[team]);
b[1]=0; b[2]=1; b[3]=0; b[0]=1;
}
/*ランナー一塁のときの動き*/
else if(b[1]==1&&b[2]==0&&b[3]==0&&b[0]==1)
{
printf(" %d番打者 ツーベースヒットです!ランナー2塁3塁!!\n",dajun[team]);
b[1]=0; b[2]=1;b[3]=1;b[0]=1;
}
/*ランナー一塁二塁のときの動き*/
else if(b[1]==1&&b[2]==1&&b[3]==0&&b[0]==1)
{
printf(" %d番打者 ツーベースヒットです!一点追加!!ランナー二塁三塁!!\n",dajun[team]);
b[1]=0; b[2]=1;b[3]=1; b[0]=1;
s[team]=s[team]+1;
}
/*ランナー満塁の時の動き*/
else if(b[1]==1&&b[2]==1&&b[3]==1&&b[0]==1)
{
printf(" %d番打者 ツーベースヒットです!2点追加!!なおもランナー二塁三塁!\n",dajun[team]);
b[1]=0; b[2]=1; b[3]=1; b[0]=1;
s[team]=s[team]+2;
}
/*ランナー一塁三塁の時の動き*/
else if(b[1]==1&&b[3]==1&&b[2]==0&&b[0]==1)
{
printf(" %d番打者 ツーベースヒットです!1点追加でランナー2塁3塁!\n",dajun[team]);
b[1]=0;b[2]=1; b[3]=1;b[0]=1;
s[team]=s[team]+1;
}
/*ランナー二塁三塁のときの動き*/
else if(b[2]==1&&b[3]==1&&b[1]==0&&b[0]==1)
{
printf(" %d番打者 ツーベースヒットです!2点追加でランナー2塁!\n",dajun[team]);
b[1]=0;b[2]=1;b[3]=0; b[0]=1;
s[team]=s[team]+2;
}
/*ランナー二塁のとき*/
else if(b[1]==0&&b[2]==1&&b[3]==0&&b[0]==1)
{
printf(" %d番打者 ツーベースヒットです!一点追加でランナー2塁!!\n",dajun[team]);
b[1]=0;b[2]=1;b[3]=0; b[0]=1;
s[team]=s[team]+1;
}
/*ランナー三塁のとき*/
else if(b[1]==0&&b[2]==0&&b[3]==1&&b[0]==1)
{

printf(" %d番打者 ツーベースヒットです!一点追加でランナー2塁!!\n",dajun[team]);
b[1]=0;b[2]=1;b[3]=0; b[0]=1;
s[team]=s[team]+1;
}
}

else if(P[team][dajun[team]][2]<ran0&&ran0<P[team][dajun[team]][3])/*スリーベースヒット*/

{
/*ランナーなしの時の動き*/
if(b[1]==0&&b[2]==0&&b[3]==0&&b[0]==1)
{

printf(" %d番打者 スリーベースヒットです!!!ランナー三塁!!\n",dajun[team]);
b[1]=0; b[2]=0; b[3]=1; b[0]=1;
}
/*ランナー一塁のときの動き*/
else if(b[1]==1&&b[2]==0&&b[3]==0&&b[0]==1)
{
printf(" %d番打者 スリーベースヒットです!!!一点追加!なおもランナー三塁!\n",dajun[team]);
b[1]=0;b[2]=0;b[3]=1;b[0]=1;
s[team]=s[team]+1;

}
/*ランナー一塁二塁のときの動き*/
else if(b[1]==1&&b[2]==1&&b[3]==0&&b[0]==1)
{
printf(" %d番打者 スリーベースヒットです!!!二点追加!!なおもランナー三塁!\n",dajun[team]);
b[1]=0;b[2]=0;b[3]=1;b[0]=1;
s[team]=s[team]+2;

}
/*ランナー満塁の時の動き*/
else if(b[1]==1&&b[2]==1&&b[3]==1&&b[0]==1)
{
printf(" %d番打者 スリーベースヒットです!3点追加!!なおもランナー3塁!\n",dajun[team]);
b[1]=0;b[2]=0;b[3]=1;b[0]=1;
s[team]=s[team]+3;
}
/*ランナー一塁三塁の時の動き*/
else if(b[1]==1&&b[3]==1&&b[2]==0&&b[0]==1)
{
printf(" %d番打者 スリーベースヒットです!2点追加でランナー3塁!\n",dajun[team]);
b[1]=0;b[2]=0;b[3]=1;b[0]=1;
s[team]=s[team]+2;
}
/*ランナー二塁三塁のときの動き*/
else if(b[2]==1&&b[3]==1&&b[1]==0&&b[0]==1)
{
printf(" %d番打者 スリーベースヒットです!2点追加でランナー3塁!\n",dajun[team]);
b[1]=0;b[2]=0;b[3]=1;b[0]=1;
s[team]=s[team]+2;
}
/*ランナー二塁のとき*/
else if(b[1]==0&&b[2]==1&&b[3]==0&&b[0]==1)
{
printf(" %d番打者 スリーベースヒットです!一点追加でランナー3塁!!\n",dajun[team]);
b[1]=0;b[2]=0;b[3]=1;b[0]=1;
s[team]=s[team]+1;
}
/*ランナー三塁のとき*/
else if(b[1]==0&&b[2]==0&&b[3]==1&&b[0]==1)
{

printf(" %d番打者 スリーベースヒットです!一点追加でランナー3塁!!\n",dajun[team]);
b[1]=0;b[2]=0;b[3]=1;b[0]=1;
s[team]=s[team]+1;
}
}

プーコ

Re:簡単な野球のプログラムを作っているのですが。。。

#8

投稿記事 by プーコ » 18年前

else if(P[team][dajun[team]][3]<ran0&&ran0<P[team][dajun[team]][4])/*HR*/

{
/*ランナーなしの時の動き*/
if(b[1]==0&&b[2]==0&&b[3]==0&&b[0]==1)
{

printf(" %d番打者 HRです!!!!一点追加!!\n",dajun[team]);
b[1]=0;b[2]=0;b[3]=0;b[0]=1;
s[team]=s[team]+1;
}
/*ランナー一塁のときの動き*/
else if(b[1]==1&&b[2]==0&&b[3]==0&&b[0]==1)
{
printf(" %d番打者 HRです!!!二点追加!!\n",dajun[team]);
b[1]=0;b[2]=0;b[3]=0;b[0]=1;
s[team]=s[team]+2;

}
/*ランナー一塁二塁のときの動き*/
else if(b[1]==1&&b[2]==1&&b[3]==0&&b[0]==1)
{
printf(" %d番打者 HRです!!!!三点追加です!!ランナーなくなりました!\n",dajun[team]);
b[1]=0;b[2]=0;b[3]=0;b[0]=1;
s[team]=s[team]+3;

}
/*ランナー満塁の時の動き*/
else if(b[1]==1&&b[2]==1&&b[3]==1&&b[0]==1)
{
printf(" %d番打者 HRです!4点追加!!ランナーなくなりました!\n",dajun[team]);
b[1]=0;b[2]=0;b[3]=0;b[0]=1;
s[team]=s[team]+4;
}
/*ランナー一塁三塁の時の動き*/
else if(b[1]==1&&b[3]==1&&b[2]==0&&b[0]==1)
{
printf(" %d番打者 HRです!3点追加でランナーなくなりました!!\n",dajun[team]);
b[1]=0;b[2]=0;b[3]=0;b[0]=1;
s[team]=s[team]+3;
}
/*ランナー二塁三塁のときの動き*/
else if(b[2]==1&&b[3]==1&&b[1]==0&&b[0]==1)
{
printf(" %d番打者 HRです!3点追加でランナーなくなりました!\n",dajun[team]);
b[1]=0;b[2]=0;b[3]=0;b[0]=1;
s[team]=s[team]+3;
}
/*ランナー二塁のとき*/
else if(b[1]==0&&b[2]==1&&b[3]==0&&b[0]==1)
{
printf(" %d番打者 HRです!二点追加でランナーなくなりました!!\n",dajun[team]);
b[1]=0;b[2]=0;b[3]=0;b[0]=1;
s[team]=s[team]+2;
}
/*ランナー三塁のとき*/
else if(b[1]==0&&b[2]==0&&b[3]==1&&b[0]==1)
{

printf(" %d番打者 HRです!二点追加でランナーなくなりました!!\n",dajun[team]);
b[1]=0;b[2]=0;b[3]=0;b[0]=1;
s[team]=s[team]+2;
}

}

else if(P[team][dajun[team]][4]<ran0&&ran0<P[team][dajun[team]][5])/*四死球*/

{
/*ランナーなしの時の動き*/
if(b[1]==0&&b[2]==0&&b[3]==0&&b[0]==1)
{

printf(" %d番打者 四死球です!!!!!ランナー一塁!!\n",dajun[team]);
b[1]=1;b[2]=0;b[3]=0;b[0]=1;
}
/*ランナー一塁のときの動き*/
else if(b[1]==1&&b[2]==0&&b[3]==0&&b[0]==1)
{
printf(" %d番打者 四死球です!!!!!ランナー一塁二塁!!\n",dajun[team]);
b[1]=1;b[2]=1;b[3]=0;b[0]=1;
}
/*ランナー一塁二塁のときの動き*/
else if(b[1]==1&&b[2]==1&&b[3]==0&&b[0]==1)
{
printf(" %d番打者 四死球です!満塁!!ランナー満塁!!\n",dajun[team]);
b[1]=1;b[2]=1;b[3]=1;b[0]=1;
}
/*ランナー満塁の時の動き*/
else if(b[1]==1&&b[2]==1&&b[3]==1&&b[0]==1)
{
printf(" %d番打者 四死球です!一点追加!!なおもランナー満塁!\n",dajun[team]);
b[1]=1;b[2]=1;b[3]=1;b[0]=1;
s[team]=s[team]+1;
}
/*ランナー一塁三塁の時の動き*/
else if(b[1]==1&&b[3]==1&&b[2]==0&&b[0]==1)
{
printf(" %d番打者 四死球です!ランナー満塁!\n",dajun[team]);
b[1]=1;b[2]=1;b[3]=1;b[0]=1;
}
/*ランナー二塁三塁のときの動き*/
else if(b[2]==1&&b[3]==1&&b[1]==0&&b[0]==1)
{
printf(" %d番打者 四死球です!ランナー満塁!\n",dajun[team]);
b[1]=1;b[2]=1;b[3]=1;b[0]=1;
}
/*ランナー二塁のとき*/
else if(b[1]==0&&b[2]==1&&b[3]==0&&b[0]==1)
{
printf(" %d番打者 四死球です!ランナー2塁1塁!!\n",dajun[team]);
b[1]=1;b[2]=1;b[3]=0;b[0]=1;
}
/*ランナー三塁のとき*/
else if(b[1]==0&&b[2]==0&&b[3]==1&&b[0]==1)
{
printf(" %d番打者 四死球です!ランナー一塁3塁!!\n",dajun[team]);
b[1]=1;b[2]=0;b[3]=1;b[0]=1;
}

}

プーコ

Re:簡単な野球のプログラムを作っているのですが。。。

#9

投稿記事 by プーコ » 18年前

else /*アウト*/

{
o=o+1;
/*ランナーなしの時の動き*/
if(b[1]==0&&b[2]==0&&b[3]==0&&b[0]==1)
{
printf(" %d番打者 アウト!%dアウトです!!\n",dajun[team],o);
b[1]=0;b[2]=0;b[3]=0;b[0]=1;
}
/*ランナー一塁のときの動き*/
else if(b[1]==1&&b[2]==0&&b[3]==0&&b[0]==1)
{
printf(" %d番打者 アウト!%dアウトです!!\n",dajun[team],o);
b[1]=1;b[2]=0;b[3]=0;b[0]=1;

}
/*ランナー一塁二塁のときの動き*/
else if(b[1]==1&&b[2]==1&&b[3]==0&&b[0]==1)
{
printf(" %d番打者 アウト!%dアウトです!!\n",dajun[team],o);
b[1]=1;b[2]=1;b[3]=0;b[0]=1;

}
/*ランナー満塁の時の動き*/
else if(b[1]==1&&b[2]==1&&b[3]==1&&b[0]==1)
{
printf(" %d番打者 アウト!%dアウトです!!\n",dajun[team],o);
b[1]=1;b[2]=1;b[3]=1;b[0]=1;
}
/*ランナー一塁三塁の時の動き*/
else if(b[1]==1&&b[3]==1&&b[2]==0&&b[0]==1)
{
printf(" %d番打者 アウト!%dアウトです!!\n",dajun[team],o);
b[1]=1;b[2]=1;b[3]=0;b[0]=1;
}
/*ランナー二塁三塁のときの動き*/
else if(b[2]==1&&b[3]==1&&b[1]==0&&b[0]==1)
{
printf(" %d番打者 アウト!%dアウトです!!\n",dajun[team],o);
b[1]=0;b[2]=1;b[3]=1;b[0]=1;
}
/*ランナー二塁のとき*/
else if(b[1]==0&&b[2]==1&&b[3]==0&&b[0]==1)
{
printf(" %d番打者 アウト!%dアウトです!!\n",dajun[team],o);
b[1]=0;b[2]=1;b[3]=0;b[0]=1;
}
/*ランナー三塁のときの動き*/
else if(b[1]==0&&b[2]==0&&b[3]==1&&b[0]==1)
{
printf(" %d番打者 アウト!%dアウトです!!\n",dajun[team],o);
b[1]=0;b[2]=0;b[3]=1;b[0]=1;
}
}
if(dajun[team]==9)
{
dajun[team]=0;
}
if(o==3)
{
dajun[team]=dajun[team]+1;
break;
}
}
}
}
printf(" 3アウトになりました! チェンジです!!\nこの回までの%sの得点は%d点です!!\n\n\n\n",name[team],s[team]);
o=0;
b[1]=0;
b[2]=0;
b[3]=0;
b[0]=1;
}
}

if(s[0]>s[1])
{
printf("試合終了です!!\n%d対%dで%sの勝利です!!\n",s[0],s[1],name[0]);
x=x+1;
s[0]=0,s[1]=0;
}
else if(s[1]>s[0])
{
printf("試合終了です!!\n%d対%dで%sの勝利です!!\n",s[1],s[0],name[1]);
s[0]=0,s[1]=0;
y=y+1;
}
else
{
printf("試合終了です!!\n%d対%dで引き分けです!!\n",s[0],s[1]);
s[0]=0,s[1]=0;
z=z+1;
}
}
printf("=================================\n\n通算成績\n川崎%d勝 宗則%d勝 %d引き分け\n\n\n\n\n\n",x,y,z);
return 0;

}

プーコ

Re:簡単な野球のプログラムを作っているのですが。。。

#10

投稿記事 by プーコ » 18年前

2チームとも全員私の好きな川崎選手にしてみました!!チーム名も(笑)
全部つなげるとコンパイラで実行できます!!
全員同じ確率なので、1000試合繰り返すと、大体同じくらい勝つと思うのですが、
プログラムのどこを修正すれば良いかわかりません!(TT)
できたと思ったのですが(TT)

管理人

Re:簡単な野球のプログラムを作っているのですが。。。

#11

投稿記事 by 管理人 » 18年前

うわぉ、長い。
コードを投稿する時は、プレタグで囲んでください。
今回は私が全部修正しました。
<pre>から</pre>で囲んでコードを書くと字下げされます。

パッと見ですが、まず
else if(P[team][dajun[team]][4]<ran0&&ran0<P[team][dajun[team]][5])/*四死球*/
のところ、使ってはいけない[5]を使っています。
[1]からじゃなく[0]から始まるべきでは?

プーコ

Re:簡単な野球のプログラムを作っているのですが。。。

#12

投稿記事 by プーコ » 18年前

管理人様、そこも間違いでしたね(TT)
いじっていて気づいたのですが、打順の繰り返しのところなのですが、
試合の最初にdajun[0]=0;dajun[1]=0;と設定しました。
で、if(dajun[team]==8)
{
dajun[team]=0;
}
という風に繰り返すようにしています。
で、表示を printf("%d番打者なんたらです。"dajun[team]+1);
の様に表しました。
しかし、実行結果を見ると、表示されているのが9番の次は2番打者になってしまいます。
dajun[team]=0;に戻しているのになぜ2番打者からになってしまうのでしょうか?

管理人

Re:簡単な野球のプログラムを作っているのですが。。。

#13

投稿記事 by 管理人 » 18年前

ちょっと今用事中なので、また家に帰ったらお書きしますm(_ _;)m

管理人

Re:簡単な野球のプログラムを作っているのですが。。。

#14

投稿記事 by 管理人 » 18年前

お書きになったプログラムをなるべく壊さないように(といってもかなり変更しましたが)書き換えました。
最低でもforで短縮出来る手続きは短縮したほうがよく、関数化できるところは関数化したほうがいいと思います。
今回は1ゲームしか行いませんから、100ゲームの結果がみたければ、forを変更してください。

詳しくは注釈を見ていただきたいのですが、わかりにくいところは、下で説明します。
わからないところがあれば遠慮なく聞いてください。
なるべく、変更点を少なくかつ、即席で作ったのであってるかどうかわかりませんが、とりあえず実行結果はよさそうなので。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int g,team,e,out,s[2],b[6],dajun[2],y,x,z;
double ran0,P[2][9][6];
char name[2][16]={"川崎","宗則"};
char hit_name[6][16]={"ヒット","二塁打","三塁打","本塁打","四球 ","アウト",};
char rui_name[3][16]={" 一塁 "," 二塁 "," 三塁 "};

//前のプログラムでP[0][0][0]から大量に初期化していた奴をforに置き換えただけ
void ini(){
    int i,j,t;
    double arr[6]={0.20, 0.15, 0.15, 0.10, 0.10, 0.30};
    for(t=0;t<2;t++)
        for(j=0;j<9;j++)
            for(i=0;i<6;i++)
                P[t][j]=arr;
}

//走者をptで受け取った分だけ移動させる
int move_player(int pt){
    int i,j,score=0;
    for(j=0;j<pt;j++){
        for(i=3;i>=0;i--){
            b[i+1]=b;
            b=0;
        }
        if(b[4]==1){
            score++;
            b[4]=0;
        }
    }
    return score;
}

//塁にいる選手を描画
void disp_rui(){
    int i;
    printf("[");
    for(i=1;i<4;i++){
        if(b==1)
            printf("%s",rui_name[i-1]);
        else
            printf("   ");
    }
    printf("]");
}

/*ベースの状況(b[0]:本塁。b[1]:一塁。b[2]:二塁。b[3]:三塁。b[4]:本塁)*/
int main(){
    int score,i;
    double p;
    srand((unsigned)time( NULL ));

    ini();//設定

    for(g=1;g<=1;g++){//
        dajun[0] = 0;    dajun[1] = 0;    s[0]=0;        s[1]=0;//初期化

        printf("%d試合目\n",g);

        for(e=0;e<9;e++){
            printf("=============================%d回====================================\n",e+1);

            for(team=0;team<2;team++){
                if(e==8&&team==1&&s[1]>s[0]){
                    printf("ここまでの得点が%sの方が高いため、9回裏の%sの攻撃はありません!\n",name[team],name[team]);
                    break;
                }
                else{
                    printf("%d回の%sの攻撃\n",e+1,name[team]);
                    out=0;
                    b[1]=0;    b[2]=0;    b[3]=0;//走者の初期化

                    while(out<3){
                        b[0]=1;//打席に立たせる
                        ran0 = (rand()%1000)/1000.0;
                        for(p=0,i=0;i<6;i++){//6種類のPによる確率で分岐。あった所でif文に入る
                            if(p<=ran0 && ran0<p+P[team][dajun[team]]){
                                    printf("   %2d番打者   %s ", dajun[team]+1, hit_name);
                                    if(i<4){//四球、アウトじゃなければ
                                        score = move_player(i+1);//i=0はヒット、=1は二塁打、=2は三塁打、=3はHRを表すので、進めるマスはi+1
                                        s[team] += score;//前関数から返って来たスコアを加算する。
                                        disp_rui();//塁にいる走者を描画
                                        if(score>0)//今得点が入ったら
                                            printf(" %d点追加",score);
                                    }
                                    else
                                        disp_rui();
                                    if(i==5)//アウトなら
                                        out++;
                                    break;
                            }
                            p+=P[team][dajun[team]];//6種類のPの確率をforでまわすため加算
                        }
                        printf("\n");
                        dajun[team] = (++dajun[team])%9;//数字を9で割った余りは8になる。つまり足して9になれば0になる。よってループ出来る。
                    }
                }
                printf("  3アウトチェンジ\n  ** %s[%d] : %s[%d] **\n",name[0],s[0],name[1],s[1]);
            }
        }
        if(s[0]>s[1]){
            printf("試合終了\n%d : %dで%sの勝利\n\n",s[0],s[1],name[0]);
            x++;
        }
        else if(s[1]>s[0]){
            printf("試合終了\n%d : %dで%sの勝利\n\n",s[1],s[0],name[1]);
            y++;
        }
        else{
            printf("試合終了\n%d : %dで引き分け\n\n",s[0],s[1]);
            z++;
        }
    }
    printf("=================================\n\n");
    printf("通算成績\n川崎%d勝        宗則%d勝        %d引き分け\n\n\n",x,y,z);
    return 0;
}

 
 

管理人

Re:簡単な野球のプログラムを作っているのですが。。。

#15

投稿記事 by 管理人 » 18年前

実行結果例

1試合目
=============================1回====================================
1回の川崎の攻撃
    1番打者   三塁打 [       三塁 ]
    2番打者   アウト [       三塁 ]
    3番打者   本塁打 [         ] 2点追加
    4番打者   四球  [         ]
    5番打者   二塁打 [    二塁    ]
    6番打者   ヒット [ 一塁     三塁 ]
    7番打者   ヒット [ 一塁  二塁    ] 1点追加
    8番打者   アウト [ 一塁  二塁    ]
    9番打者   三塁打 [       三塁 ] 2点追加
    1番打者   二塁打 [    二塁    ] 1点追加
    2番打者   アウト [    二塁    ]
  3アウトチェンジ
  ** 川崎[6] : 宗則[0] **
1回の宗則の攻撃
    1番打者   ヒット [ 一塁       ]
    2番打者   二塁打 [    二塁  三塁 ]
    3番打者   二塁打 [    二塁    ] 2点追加
    4番打者   アウト [    二塁    ]
    5番打者   二塁打 [    二塁    ] 1点追加

・・・・略






まず、move_player関数です。

int move_player(int pt){
    int i,j,score=0;
    for(j=0;j<pt;j++){//pt分進める
        for(i=3;i>=0;i--){//三塁からホームベースまで
            b[i+1]=b;//1つずつ進める
            b=0;//コピー元は削除
        }
        if(b[4]==1){//もし1周まわっていたら
            score++;//スコアを加算
            b[4]=0;//本塁にいる走者を削除
        }
    }
    return score;//スコアを返す
}

ビットシフトの方がいいと思いますが、どうしても配列でやりたければこのようにしてはいかがでしょうか。
ptに受け取った分だけ塁を進める関数です。

b[0]:打席、b[1]:一塁、b[2]二塁、b[3]三塁、b[4]本塁

で定め、「四塁」にあたる本塁も定めます。本塁にたどり着くと得点になります。
一つずつみてやれば難しくありませんから注釈を見てください。
一つずつマスを進めているだけです。


次に現在塁にいる人を描画する関数です。

void disp_rui(){
    int i;
    printf("[");
    for(i=1;i<4;i++){
        if(b==1)
            printf("%s",rui_name[i-1]);
        else
            printf("   ");
    }
    printf("]");
}

これも特に難しくなく、ただ特定のbに人がいればそのrui_nameを表示しているだけです。

今回かなり短縮させたのは、6種類の確率を計算する部分で

if(p<=ran0 && ran0<p+P[team][dajun[team]]){
}
p+=P[team][dajun[team]];//6種類のPの確率をforでまわすため加算

これをまわしています。
これにより、範囲が
[0]~[1]、[1]~[2]、[2]~[3]。。。。
とする事が出来ます。

後はこの部分です。

dajun[team] = (++dajun[team])%9;

0 を9で割った余りは0
1 を9で割った余りは1
2 を9で割った余りは2
3 を9で割った余りは3
4 を9で割った余りは4
5 を9で割った余りは5
6 を9で割った余りは6
7 を9で割った余りは7
8 を9で割った余りは8
9 を9で割った余りは0
10を9で割った余りは1
11を9で割った余りは2
12を9で割った余りは3

つまり割った余りと言うのはループするので、

たした結果が9以上になろうとすると0に戻るため、このような書き方でループできます。

他に何かわからない箇所があれば聞いてください。

管理人

Re:簡単な野球のプログラムを作っているのですが。。。

#16

投稿記事 by 管理人 » 18年前

250万回計算した結果

通算成績
川崎1222478勝        
宗則1221830勝
      55692引き分け
 
妥当な結果になったのではないでしょうか。

プーコ

Re:簡単な野球のプログラムを作っているのですが。。。

#17

投稿記事 by プーコ » 18年前

管理人様、こんなすごいものをありがとうございます!!(^^)
さすがに神ですね!!しかも250万試合とは!
私は、関数の作りかたは分かるのですが、あまり関数を用いてコードを書かないので、
敬遠してきました(TT)
しかし、管理人様の解説が大変分かりやすかったです!!
こちらの方が見やすいですし、なによりコードが短くて良いですね!!!!(^^)
しかし、今はニチーム分まったく同じ打者だから良いのですが、
全員違う率の打者にするにはどうすればよいのでしょうか?

管理人

Re:簡単な野球のプログラムを作っているのですが。。。

#18

投稿記事 by 管理人 » 18年前

前にも書いたとおり、選手データをファイルから読み込む形にすれば、楽になると思います。
こんなデータが書かれたテキストファイルを用意します。

イチロー
312

松井
287

前田
301

選手名と打率が書かれています。
fopen関数でファイルを開き、fgets関数で1行ずつデータを読み込みます。
ここでは、読みにくくならないように最小限の処理しかしていません。
きっと打率以外にも欲しいデータはあるでしょうし、
行わなければならないエラー処理もやらずにあります。

理解したのち、任意に追加してください。

説明は注釈を見てください。

1行ずつ読み込む時、今何行目を読み込んでいるかiでカウントし、その行によってswitch文で処理分岐させます。
jはその組をカウントしてあります。今回はデータが3組ありますね。

「0行目はなまえ、1行目は打率、2行目は何もかかれていない」

という書式のデータ組であることに注目してください。

名前は改行コードが最後に入っているので、除去して使ってください。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct{
	char name[64];
	int state[1];
}states_t;

#define BUF 64
#define MAX 10

int main(){
	int i=0,j=0,t;
	FILE *fp;
	states_t states[MAX];
	char st[BUF];

	if ( (fp = fopen("dat.txt", "r") ) ==NULL ){//ファイルを開けて、エラーが起これば
		printf("ファイルオープンエラー");
		return 0;
	}

	while( fgets(st, BUF , fp) && j<MAX){//1行読み込みが成功中 かつ j組個が最大値より少ない
		switch(i){
			case 0://0行目
				strcpy(states[j].name, st);//stをnameにコピー
				break;
			case 1://1行目
				states[j].state[i-1] = atoi(st);//文字列を数値に変換して代入
				break;
			case 2://2行目
				if(st[0]!='\n'){//何も書かれていないはずの行なので、最初が改行じゃなければ
					printf("データの書式が間違っています。");//エラー
					return 0;
				}
				break;
		}
		i = (++i) % 3;//3つヒトまとまりのループをさせる
		if(i==0)//3つ数えると元に戻るからi==0の時カウントすると組がカウント出来る
			j++;
    }

	for(t=0;t<j;t++)
		printf("%s - %d \n", states[t].name, states[t].state[0]);

	return 0;
}
 
 

閉鎖

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