2009年8月9日日曜日

第 5 章 野球シミュレーション 1

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class Chap5_baseball : System.Web.UI.Page
{
string DataFolderURL = "~/Chap5/Data/";
string DataFolder;
DataSet Team_1, Team_2;
DataTable ScoreTable;

protected void Page_Load(object sender, EventArgs e)
{
DataColumn column;
DataRow row;

DataFolder = Server.MapPath(DataFolderURL);

//スコア掲示板用のテーブルを作る
ScoreTable = new DataTable("スコアボード");

//チーム名用のカラムを作る
column = new DataColumn();
column.DataType = System.Type.GetType("System.String");
column.ColumnName = "チーム";
column.Caption = "チーム";
ScoreTable.Columns.Add(column);

//イニング用のカラムを作る
for (int i = 1; i <= 9; i++)
{
column = new DataColumn();
column.DataType = System.Type.GetType("System.Int32");
column.ColumnName = i.ToString();
column.Caption = i.ToString();
ScoreTable.Columns.Add(column);
}

//トータルスコア用のカラムを作る
column = new DataColumn();
column.DataType = System.Type.GetType("System.Int32");
column.ColumnName = "計";
column.Caption = "計";
ScoreTable.Columns.Add(column);

row = ScoreTable.NewRow();
ScoreTable.Rows.Add(row);
row = ScoreTable.NewRow();
ScoreTable.Rows.Add(row);

//スコアボードを表示
ScoreBord.DataSource = ScoreTable;
ScoreBord.DataBind();

//チームを表す DataSet を作成する
Team_1 = new DataSet();
Team_2 = new DataSet();
}

protected void Start_Click(object sender, EventArgs e)
{
string record;

// ドロップダウンリストで選択されたチームを読み込む
Team_1.ReadXml(DataFolder + DropDownList1.SelectedValue + ".xml");
Team_2.ReadXml(DataFolder + DropDownList2.SelectedValue + ".xml");

//野球の試合のシミュレーション計算をおこなう
SimBaseball simBaseball = new SimBaseball();
simBaseball.PlayAll(Team_1, Team_2, ScoreTable, out record);

//結果を表示
ScoreBord.DataSource = ScoreTable;
ScoreBord.DataBind();
ResultLog.Text = record;
}

protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
//選択されたチームのメンバを表示する
Team_1.ReadXml(DataFolder + DropDownList1.SelectedValue + ".xml");
Member_1.DataSource = Team_1.Tables["選手"];
Member_1.DataBind();
}
protected void DropDownList2_SelectedIndexChanged(object sender, EventArgs e)
{
//選択されたチームのメンバを表示する
Team_2.ReadXml(DataFolder + DropDownList2.SelectedValue + ".xml");
Member_2.DataSource = Team_2.Tables["選手"];
Member_2.DataBind();
}
}










using System;
using System.Data;
using System.Configuration;
using System.Text;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

/// <summary>
/// 野球の試合のシミュレータ
/// </summary>
public class SimBaseball
{
/// <summary>
/// コンストラクタ
/// </summary>
public SimBaseball()
{
}

/// <summary>
/// 野球の一試合をシミュレートする
/// </summary>
/// <param name="Team_T">先攻のチーム</param>
/// <param name="Team_B">後攻のチーム</param>
/// <param name="ScoreTable">スコア表 (出力)</param>
/// <param name="Record">試合の記録 (出力)</param>
public void PlayAll(DataSet Team_T, DataSet Team_B, DataTable ScoreTable, out string Record)
{
// ベース上のランナーの配列 0: 一塁、 1: 二塁、 2: 三塁
Player[] runner = new Player[3];
// 試合経過記録用の変数
StringBuilder record = new StringBuilder("");
// シミュレーション計算用の乱数
Random rnd = new Random();

DataRow score_T, score_B;
int outCount, basehit;
int score;

// 先攻と後攻のチームを生成する
Team team_T, team_B;

team_T = new Team(Team_T);
team_B = new Team(Team_B);

// スコア表を初期化する
ScoreTable.Rows.Clear();
score_T = ScoreTable.NewRow();
score_T["チーム"] = team_T.TeamName;
score_T["計"] = 0;
ScoreTable.Rows.Add(score_T);
score_B = ScoreTable.NewRow();
score_B["チーム"] = team_B.TeamName;
score_B["計"] = 0;
ScoreTable.Rows.Add(score_B);

// 1回から9回まで試合をシミュレートする
for (int inning = 1; inning <= 9; inning++)
{
// 記録にイニング毎の区切りを追加
record.AppendLine("--- " + inning + "回表 ---");

// イニングの初期化
outCount = 0;
for (int i = 0; i < 3; i++)
runner[i] = null;
score = 0;

// スリーアウトになるまでバッテイングを繰り返す
while (outCount < 3)
{
// バッテイングをおこなう
basehit = team_T.Butter.Hitting(rnd);
if (basehit == 0)
{
// アウト。アウトカウントを増やす。
outCount++;
record.AppendLine(team_T.Butter.Name + ": アウト!");

}
else
{
// 記録を書き足す
switch (basehit)
{
case 1:
record.AppendLine(team_T.Butter.Name + ": ヒット!");
break;
case 2:
record.AppendLine(team_T.Butter.Name + ": 二塁打!");
break;
case 3:
record.AppendLine(team_T.Butter.Name + ": 三塁打!");
break;
case 4:
record.AppendLine(team_T.Butter.Name + ": ホームラン!!");
break;
}
// ランニングを行う
score += Running(team_T.Butter, runner, basehit);

}
// 次のバッターに変更
team_T.NextButter();
}
// イニング終了。スコアボードの得点を更新する。
score_T[inning.ToString()] = score;
score_T["計"] = (int)score_T["計"] + score;

// 記録にイニング毎の区切りを追加
record.AppendLine("--- " + inning + "回裏 ---");

// イニングの初期化
for (int i = 0; i < 3; i++)
runner[i] = null;
outCount = 0;
score = 0;

// スリーアウトになるまでバッテイングを繰り返す
while (outCount < 3)
{
// バッテイングをおこなう
basehit = team_B.Butter.Hitting(rnd);
if (basehit == 0)
{
// アウト。アウトカウントを増やす。
outCount++;
record.AppendLine(team_B.Butter.Name + ": アウト!");
}
else
{
// 記録に書き足す。
switch (basehit)
{
case 1:
record.AppendLine(team_B.Butter.Name + ": ヒット!");
break;
case 2:
record.AppendLine(team_B.Butter.Name + ": 二塁打!");
break;
case 3:
record.AppendLine(team_B.Butter.Name + ": 三塁打!");
break;
case 4:
record.AppendLine(team_B.Butter.Name + ": ホームラン!!");
break;
}
// ランニングを行う
score += Running(team_B.Butter, runner, basehit);

}
// 次のバッターに変更
team_B.NextButter();
}
// イニング終了。スコアボードの得点を更新する
score_B[inning.ToString()] = score;
score_B["計"] = (int)score_B["計"] + score;
}
//記録を戻す。
Record = record.ToString();

}

/// <summary>
/// ベースランニングをシミュレートするメソッド
/// </summary>
/// <param name="Butter">打者</param>
/// <param name="Runner">塁上にいる選手の配列</param>
/// <param name="Base">何塁打かを表す数字。1がシングルヒット。4がホームラン。</param>
/// <returns>得点</returns>
private int Running(Player Butter, Player[] Runner, int Base)
{
int score = 0;

if (Base == 1)
{
// シングルヒットの場合、ベースを一つずつ進める
if (Runner[2] != null)
score++;
Runner[2] = Runner[1];
Runner[1] = Runner[0];
Runner[0] = Butter;
}
else
{
// 二塁打以上の場合、ランナーは全員返る。
for (int i = 0; i < 3; i++)
{
if (Runner[i] != null)
{
score++;
Runner[i] = null;
}
}
if (Base == 4)
score++;
else
Runner[Base - 1] = Butter;
}
//得点を返す
return score;
}

}

/// <summary>
/// 野球チームを表すクラス
/// </summary>
public class Team
{
/// <summary>
/// チーム名
/// </summary>
private string teamName;
/// <summary>
/// 現在の打順のバッター
/// </summary>
private int currentButter;
/// <summary>
/// 選手リスト。1番バッターから順に配列に並べる
/// </summary>
private Player[] playerList = new Player[9];

// プロパティ アクセサ

/// <summary>
/// チーム名
/// </summary>
public string TeamName
{
get { return teamName; }
}

/// <summary>
/// 現在の打順のバッター
/// </summary>
public Player Butter
{
get { return playerList[currentButter]; }
}

/// <summary>
/// コンストラクタ。チームメンバのリストを生成する。
/// </summary>
/// <param name="teamDS">チームのデータを含む DataSet</param>
public Team(DataSet teamDS)
{
teamName = (string)teamDS.Tables["チーム"].Rows[0]["チーム名"];

// 選手リストを作成する
for (int order = 0; order < 9; order++)
{
playerList[order] = new Player(teamDS.Tables["選手"].Rows[order]);
}
currentButter = 0;
}

/// <summary>
/// 打順を次のバッターに進めるメソッド
/// </summary>
public void NextButter()
{
currentButter++;
if (currentButter >= 9)
currentButter = 0;
}
}

/// <summary>
/// 選手を表すクラス
/// </summary>
public class Player
{
// 内部フィールド値
private string name;
private double daritsu;

// プロパティ アクセサ
public string Name
{
get { return name; }
}

public double Daritsu
{
get { return daritsu; }
}

// コンストラクタ
public Player(DataRow dataRow)
{
name = (string)dataRow["名前"];
daritsu = Convert.ToDouble((string)dataRow["打率"]);
}

/// <summary>
/// バッテイングをおこなうメソッド
/// </summary>
/// <param name="rnd">シミュレーション計算用の乱数</param>
/// <returns>バッテイングの結果。
/// 0: アウト, 1: 一塁打... , 4: ホームラン
/// </returns>
public int Hitting(Random rnd)
{
if (rnd.NextDouble() > daritsu)
return 0;

double rndDbl = rnd.NextDouble();
if (rndDbl < 0.05)
return 4;
else if (rndDbl < 0.10)
return 3;
else if (rndDbl < 0.30)
return 2;
else
return 1;
}
}










終了。

0 コメント:

コメントを投稿