トップ «前の日記(2004-04-14) 最新 次の日記(2004-04-16)» 編集

日々の破片

著作一覧

2004-04-15

_ rjb

LinuxだとJNI_GetDefaultJavaVMInitArgs がSEGVと書いていたが、JNI_GetDefaultVMInitArgsに与える引数を間違えていた。

JDK1_1InitArgsを使っていたが、実際には、JavaVMInitArgsを使用する。

Solarisで、-Xusealtsigsを与えるためにいろいろ調べたら、結局、JavaVMInitARgsのJavaVMOption *optionsメンバに設定するらしいとわかったからだ。

で、JavaVMInitArgsを利用するように修正したら、Linuxでも通るようになった。では、JDK1_1InitArgsってのは一体どこで使えるんだろう?

追記:寝ぼけてるようだ。1_1なんだからJDK1.1用で、Java2(1.2)以降は、JavaVMInitArgsになったということだろう(データメンバが少ないので逆に考えてしまったらしいが、万能のoptionsメンバが追加されてるわけだし)。

_ あわや読まずに捨てるところ

なんか、最近やたらめったら「アドレス変更しました(音符マーク)」というサブジェクトのspamが来る。とにかく来る。連続5個くらい来たりする。

という状況の中で、「サイト移転のお知らせ」というのが来たので、即効削除しようとしてふと一瞬出た文面がそれまでと調子が違うので、あわてて手を止めた。Fe2+さんからのRuby256倍勝手に正誤表の移転のお知らせだった。危なかった。

で、思い出したが、ここまでspamがガンガン来ると、もう、「常識ではsubjectはASCIIで書くべきですな」とは言えないし(「アドレス変更しました」はとりあえず置いておいて)、用件だけ手短にってのもあまりうまくなさそうだな。

_ なんとなくやってみたが

プロのコード、アマのコード(4/23アンカー変更) 面倒な部分は再利用
import java.io.*;
public class Gcp {
    private static final String te[] = {"グー", "チョキ", "パー"};
    private int win;
    private int loose;
    private int fair;
    private BufferedReader reader;
    private final Result[][] state;
 
    public Gcp () throws IOException {
	reader = new BufferedReader(new InputStreamReader(System.in));
	state = new Result[3][3];
	state[0][0] = state[1][1] = state[2][2] = new Fair();
	state[0][1] = state[1][2] = state[2][0] = new Win();
	state[0][2] = state[1][0] = state[2][1] = new Loose();
    }
    private abstract class Result {
	void execute(int you, int com) {
	    System.out.print(" コンピュータ:" + te[com] + 
			       ",プレイヤー:" + te[you] + ":");
	}
    }
    private class Win extends Result {
	void execute(int you, int com) {
	    super.execute(you, com);
	    System.out.println("あなたの勝ちです!");
	    win++;
	}
    }
    private class Loose extends Result {
	void execute(int you, int com) {
	    super.execute(you, com);
	    System.out.println("あなたの負けです!");
	    loose++;
	}
    }
    private class Fair extends Result {
	void execute(int you, int com) {
	    super.execute(you, com);
	    System.out.println("引き分けです!");
	    fair++;
	}
    }
 
    public void execute(int count) {
         win = loose = fair = 0;
	for (int i = 0; i < count; i++) {
	    int you = read();
	    int com = (int)(Math.random() * 2 + 1);
	    state[you][com].execute(you, com);
	}
	System.out.println("プレイヤーの勝敗数:" + win + "勝" +
			   loose + "負" + fair + "引き分け");
    }
 
    private int read() {
	for (;;) {
	    System.out.print("あなたの手(0:グー、1:チョキ、2:パー)");
	    String s;
	    try {
		s = reader.readLine();
	    } catch (IOException e) {
		continue;
	    }
	    if (s.length() > 0) {
		if (s.equals("q")) { // バックドア
		    System.exit(1);
		}
		try {
		    int n = Integer.parseInt(s);
		    if (n >= 0 && n <= 2) return n;
		} catch (NumberFormatException e) {
		}
	    }
	}
    }
 
    public static void main(String[] args) throws Exception {
	Gcp gcp = new Gcp();
	gcp.execute(5);
    }
}
添削結果:
1.コメントがありませんね
プログラムのどこにもコメントが付けられていませんね。プログラムを読みにくいと感じました。
(追記:× この程度の行数のまとまりを読めないのはだめ。ただし各メソッドやフィールド、クラスにJavadocは付けるべきでしょう。)
(更に追記:そうだ、コメントをつけましょうというのを見るたびに感じる違和感ってのは、単純なことなのだ。あなたがプロなら、読む相手もプロなのだ。プロをなめるな、ということだ。アマはプロの能力を知らないから文章による解説が必須だと考えてしまう。大丈夫、あなたの先輩や同僚はあなたと同等かそれ以上のプロだから、まともなコードを書けば、必ずそれを理解するってことだ)
2.おやおや実装継承ですか?
たかだか1行の出力くらい、バーといきましょう。せこいですよ。
(追記:微妙。状態表示をスーパークラス、結果表示をサブクラスというメッセージ表示の責務分割と考えれば合理的。それにこれ以上の継承=スパゲッティ化はありえないはず。取り得る数を考えればせっかく実装継承可能な言語なんだから使わなければ無駄。7項を参照)
3.おやおや3文字変数ですか?
comってcomponent object modelですか? それともcommunication portですか? さっぱり意味がわかりませんね。せめて、computerPlayerにしてください。
(追記:微妙。正直最初comとは何かわからなかったが、youの対照だということはわかるから、ゲームの言い回しとしてはありなのかも。これはオリジナルから持ってきた)
4.おやおや1文字変数も使ってますね
iではなく、kaisuのほうが良いでしょう。sではなくyomiTottaMojiretsuにしたほうが適切ですね。
(追記:×。これがスコープが短く、初期化時が明確なので意味の失いようが無い例。特にkaisuはともかくyomi……はダメな例。なお、英語ローマ字混じりは避けるべきなので、kaisuならKati、Make……、Win、Loseならcountかな)
5.0,1,2は定数にしたほうが良いでしょう
0をGOO、1をCHOKI、2はPAAとすべきですね。
(追記:○。特に最初の配列の初期化時)
6.バックドアとはなんですか?
デバッグ中はともかく、ちゃんと削除しましょう。(うむ、これは文句なく正しい)
(追記:○。もちろん)
7.詰めが甘いですね
わざわざ、win, looselose(次項を参照) ...なんていうフィールドを作っていますが不要ですね。Resultのフィールドとしてint countを置いて、実装継承しているのだから、Result#executeでカウントアップすれば済みますね。
(追記:○。最後の結果表示でwin.getCount(), lose.getCount()...とすれば良い)
8.誤った綴りを使っていますね
looseじゃなくてloseですよ。素直にKati, Make, Aikoとすれば、こういう間違いは防げますね。っていうか、どおりでなんでlooseがlostになるんだ? と思ったはずだ(で、辞書見て、「単語が存在する」のを確認してそこで終ったところがバカですね)。
ご指摘感謝。
(追記:○。心より恥じるってやつですね。)
#追記:ネタ的(微妙)なものに×、正しいものに○を付けた
9(追加).メソッド名がいい加減すぎです。
なんでもexecuteはいかがなものでしょうか? せめて、Resultについてはjudgeなどにすべきですね。
(○。そうだな)
10(追加).ところで、根本的に間違えていますね
comさんが0を出すことってありえるか考えてみたらどうですか?
(○。確かに、その通り……
11(追加).「面倒な部分は再利用」とか言っていますが、「再利用」ってそんなにいいですかね?
つまりコピペは悪ということですね。
(int)(Math.random() * 3)。「1.0より小さい正の符号付doubleを返す」
(○。うむ、心より恥じる。っていうか、ちゃんと添削しといてくれよ。)

_ この時、何が起きている?

i686 Win32 J2se1.4.2では、
public class K {
    public static void main(String[] args) {
        double k = 0.9999999999999999;
        System.out.println("result=" + ((int)(k * 3))); // -> 2
        double j = 0.99999999999999999;
        System.out.println("result=" + ((int)(j * 3))); // -> 3
    }
}
となるけど、代入時点で既にjは1.0になっているのか。
本日のツッコミ(全19件) [ツッコミを入れる]
_ anon (2004-04-15 06:57)

looseじゃなくてloseですよ

_ Saisse (2004-04-15 10:06)

「グー、チョキ、パーをオブジェクト化してStrategyを適用してください。」は難しすぎですか?

_ arton (2004-04-15 10:07)

難しいかどうかはわかりませんが、勝ち負け判定してカウントすることがプログラムの目的となっています。グーチョキパーは、勝敗に比べると着目価値がありません。

_ arton (2004-04-15 10:17)

Strategy you = te.lookup(read());<br>ちょっと考えたけど<br>Strategy com = te.lookup(rand...);<br>Result.Display(you.battle_with(com));<br>かな? というか、グーチョキパーそれぞれをストラテジにするって変な気がするな(必ず対で出てくるし)。<br>取り得る状態が決定している場合は、ステートを使うべきだと思うが、逆にどう、ストラテジパターンを適用するのかちょっと知りたいところ。

_ Saisse (2004-04-15 10:23)

勝ち負け判定の処理が複雑な気がしたので、オブジェクト化したグーチョキパーに任せれば、重要なカウント処理も単純になるかな?と思いました。

_ arton (2004-04-15 10:30)

カウントは、勝ちオブジェクト、引き分けオブジェクト、負けオブジェクトの属性だし、勝ち負け判定はチャートのルックアップだからこれ以上単純化は不可能だと思いますが。<br>#3人じゃんけんならチャートが3次元になる。

_ Saisse (2004-04-15 10:52)

ステートとストラテジーの違いは状態を多様化するのか処理を多様化するのかの違いで、インターフェースを多様化するという意味では同じパターンで、名前が違うだけですよね(この理解が間違っているかも知れませんが)。<br><br>グーチョキパーは勝ち負け判定を多様化するのが目的なのでストラテジーの方を使いました。<br><br>実装としてはTeをスーパクラスにGoo,Choki,Paaを定義<br>result = myTe.judge(yourTe);<br>のような感じだと思います。

_ Saisse (2004-04-15 11:17)

まともなコードを書けばコメントは不要というのには大賛成です。まともなコードを書いていればコメントはコードに書いてあることを日本語化するだけの役割しか持たなくなるはずですので。

_ arton (2004-04-15 13:04)

名前が違うだけと言われるとすごく抵抗を感じるけど、確かに見てくれはほとんど同じですね(実際、どっちか微妙なものもあるし)。<br>状態遷移テーブルのルックアップや、State next = currentState.next(newInput);のように比較的機械的に取得可能なのがステートで、Strategy stg = createStragety(newInput);のように、取得に独自の判定が必要なのがストラテジかな、とか漠然に感じています。

_ arton (2004-04-15 13:18)

漠然「と」感じているのに、決定したときは明確な意志があるのはなぜだろう? 後、閉じている(ステート)、開いている(ストラテジ)なんだけど、意味わからないな、これでは。

_ Saisse (2004-04-15 13:52)

そういわれれば、ステートは静的なストラテジは動的なイメージがあるかも知れません。

_ arton (2004-04-15 14:51)

で、思ったんですが、グーチョキパーはエンティティとして考えて(ストラテジとして考えるには同時に2つ実体化されるのがどうしても気になる)、ここからストラテジを引っ張ってくる(この場合は勝負オブジェクトがステートじゃなくてストラテジ)というのはどうでしょう?<br>Te yours = Gcp.getTe(read());<br>Te comps = Gcp.getTe(Math.rand()...); // Teは勝敗判定を持つ<br>Strategy result = yours.battle(comps); // Strategyの実体は上のステート<br>result.show(); // 上のexecute/judge

_ arton (2004-04-15 15:00)

しかし、好き嫌いでいくと、あまり好きではないな(状態遷移表引っ張るのが好きだからってのはあるかも)

_ Saisse (2004-04-15 15:12)

ステートかストラテジかはおいておいて、僕が意図したコードはそんな感じです。考え方も実装もこちらの方が簡単かな?と。

_ Saisse (2004-04-15 15:40)

あれ?嫌いなんですね。こういうコード。僕は自分がアホなので、アホでも解るコードが好きらしいです(考えることが少なくてすみますし)。

_ るいも (2004-04-15 21:14)

「// InputStreamReaderクラスのインスタンスを生成する。」こういうコメント嫌い。

_ るいも (2004-04-15 22:10)

(int)(Math.random() * 2 + 1); わははチョキさえ出してれば負けないぞ!

_ るいも (2004-04-15 23:19)

あ、10に書いてありましたね。すんません。

_ arton (2004-04-16 00:36)

違いますよ。るいもさんの書き込みを見て書き足したんです。「確かにその通り」の部分がリンクになってます。


2003|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|04|05|06|07|08|09|10|11|12|

ジェズイットを見習え