ウィリアムのいたずらの、まちあるき、たべあるき

ウィリアムのいたずらが、街歩き、食べ物、音楽等の個人的見解を主に書くブログです(たま~にコンピューター関係も)

ルールがいろいろあるときのプログラミング方法

2013-05-30 17:00:26 | 開発ネタ
昨日、話になったので、ちょっとメモメモ。

例えば、野球のように、いろいろなルールがあり、
順番に1回から作っていくと、大変なとき
(13回で引き分けとすると、13回分作らないといけない)
どうやってプログラミングするかという話。

こういうときは、状態遷移図を描いて考えると思います。

つまり、状態遷移図をかいて、プログラミングとしては

初期状態

終了状態になるまで、以下の処理を実行する

| 現在ステータスにおける処理

*-状態のチェック&次の状態セット

終了状態処理

という具合になると思います。具体的にプログラム例を出して・・




■御題

野球のルールを以下のように表しました。

表か、裏か。

で、それぞれ、終了条件があると・・
抜けていたり、おかしかったりするかもしれないけど、
とにかくこれを基に考えましょう(野球のシミュレーターを作りたいわけではないので)。




■プログラミング-ルールベースの一般系

mainの部分は、こんなかんじ
public class Game {

	public static void main(String[] args) {
		//	初期処理
		BaseBall b = new BaseBall();
		b.init_set();
		
		//	試合中
		while(b.sts != BaseBall.STS_END)
		{
			//	ゲーム実行
			b.game();

			//	次の状態評価・値セット
			b.hyoka();
		}

		//	試合終了処理
		b.owari();
	}

}

Gameというクラスにしている。これは、野球に限らず、基本的に変わらない部分、
init_setで初期化をして、
終了条件まで
  game()をして(業務だと、ステータスに応じた処理をして)
  hyoka()で、評価、次の状態をセットし
owari()で終了処理




■プログラミング-野球特化部分

で、野球に特化したクラスを書く。
こんなかんじ

import java.util.*;


public class BaseBall {

public static final int STS_OMOTE = 0;
public static final int STS_URA = 1;
public static final int STS_END = 2;

int kai = 0;
int sts = 0; // 表0、裏1、試合終了2
int out_count = 0;
int ten = 0;
int senko_ten = 0;
int koko_ten = 0;
Random rnd = new Random(); // 乱数:ゲームに使う

ArrayList<String> senko = new ArrayList<String>();
ArrayList<String> koko = new ArrayList<String>();

public void init_set()
{
kai = 1; // 1回
sts = STS_OMOTE; // 表
out_count = 0; // ノーアウト
ten = 0; // 今の回は無得点
senko_ten = 0;
koko_ten = 0;
}

public void game()
{
// 点が入ったか?
if ( rnd.nextInt(2) >= 1 )
{
ten++;
}
else // 点が入らないときは、アウトになったものとする

{
out_count ++;
}
}

public void hyoka()
{
switch(sts)
{
case STS_OMOTE: // 表のとき
if ( (out_count == 3) && ( kai == 9 ) && (senko_ten+ten < koko_ten ) )
{
senko.add(String.valueOf(ten));
senko_ten += ten;
koko.add(String.valueOf("X"));
sts = STS_END;
break;
}
else if ( (out_count == 3) )
{
senko.add(String.valueOf(ten));
senko_ten += ten;
sts = STS_URA;
out_count = 0; // ノーアウト
ten = 0; // 今の回は無得点
break;
}
break;
case STS_URA: // 裏のとき
if ( (out_count == 3) && ( kai == 13 ) )
{
koko.add(String.valueOf(ten));
koko_ten += ten;
sts = STS_END;
break;
}
else if ( (out_count == 3) && ( kai <= 8 ) )
{
koko.add(String.valueOf(ten));
koko_ten += ten;
sts = STS_OMOTE;
out_count = 0; // ノーアウト
ten = 0; // 今の回は無得点
kai++; // 回数は上がる
break;
}
else if ( (out_count == 3) && ( kai >= 9 ) && ( kai <= 12 ) && (senko_ten == koko_ten+ten ))
{
koko.add(String.valueOf(ten));
koko_ten += ten;
sts = STS_OMOTE;
out_count = 0; // ノーアウト
ten = 0; // 今の回は無得点
kai++; // 回数は上がる
break;
}
else if ( (out_count == 3) && ( kai >= 9 ) && ( kai <= 12 ) && (senko_ten != koko_ten+ten ))
{
koko.add(String.valueOf(ten));
koko_ten += ten;
sts = STS_END;
break;
}
else if ( ( kai >= 9 ) && ( kai <= 12 ) && (senko_ten < koko_ten+ten ))
{
koko.add((String.valueOf(ten)+"X"));
koko_ten += ten;
sts = STS_END;
break;
}
break;
}
}

public void owari()
{
System.out.println("--------------------------------------");
for(int i = 0 ; i < senko.size();i++)
{
System.out.print(senko.get(i) + " | ");
}
System.out.println(senko_ten);
System.out.println("--------------------------------------");
for(int i = 0 ; i < koko.size();i++)
{
System.out.print(koko.get(i) + " | ");
}
System.out.println(koko_ten);
System.out.println("--------------------------------------");

}
}


BaseBallで
init_setは初期化。これは別にいい
owariも、結果表示。これは、別にいいと思う

game()のところで、処理を書いている。
今回のイベントは、アウトになるか、点が入るかしか
関係ないので、どっちかがおきるように書いた。
もうちょっとまじめにシミュレートするのであれば、
ここをいっぱい書く。

そしてhyoka()
hyokaの書き方は、以下のとおり

1.状態遷移図の状態ごとに、switch文でわける。
  今回は、表と裏なので、ステータスが、STS_OMOTEとSTS_URAのケースに
  わかれている

2.その状態から、「外に出て行く線」の条件をif文で並べる

3.if文の中は、ステータスに遷移するステータスをセットして、
  遷移時の初期化をする。

今回3を明示していないけど、これを明示すると、
ほぼ自動的に、状態遷移図から、プログラムが起こせる
ということは、業務ルールを状態遷移図で表現すれば、
プログラムが起こせるということになる。
この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« 日本のSIerがグローバル展開... | トップ | 期限切れ後のWinXPは、ネット... »
最新の画像もっと見る

開発ネタ」カテゴリの最新記事