メモ的な何か

技術的な私のメモになる予定です。

Oracle ROWNUMの使い方

あんまりブログ更新できず、アクセス数もゼロ行進・・・
今回は大きいものじゃないですが、この前仕事でOracle SQL のROWNUMの使い方って特殊って思ったのでまとめてこうと思います。

私の環境はOracle Database Express Edition 11g Release 2VMWare Player上のCentOS7で動かしてる感じで、それをWin上のOracle SQL Developerからアクセスできるようにしました。
ぶっちゃけいうとの環境構築に手間取った感ある・・・

テストテーブルはこんな感じ
数値と名前が入っているシンプルなテーブルです。
f:id:rui_phone:20141012111024p:plain

今回はこのテーブルを数値の小さい順に並べた時の3~5番目を取得するようにしてみたいと思います。
OracleのROWNUMは単純にテーブルの表示順からの位置数を持っていると思っていましたので、以下のように書いて実行しました。
f:id:rui_phone:20141012113359p:plain

実行結果を見た通り、この状態では何も取得されません。
なぜ表示されないかというとROWNUMには1件目(ROWNUM=1)が取得結果に含まれないと正しく表示できないという問題があります。
なので1~5番目とすれば取得は可能です。
f:id:rui_phone:20141012134836p:plain

しかし順番がORDER BYしているにも関わらず、順番がソートされていません。
これは先にROWNUMが処理されてからORDER BYが処理されているため発生します。
この二つの問題を解決するには以下の方法をとらなければなりません。
二段階に分けて進めていきます。
まず以下のSQLを見てください。
f:id:rui_phone:20141012140345p:plain

先にテストテーブルをソートし、それを副問合せとし、そのテーブルに対してROWNUMのカラムを追加しています。
ソートしたものに対してきちんとROWNUMが振れていることがわかると思います。
しかしこのままですと1件目を含めないと取得結果が表示できません。
そこで次のSQLで解決します。
f:id:rui_phone:20141012141437p:plain

先ほどのSQLを副問合せとし、ROWNUMのカラムに対して3~5番目を表示する条件を与えます。
これによって、当初求めたかった「数値の小さい順に並べた時の3~5番目を取得」を達成できました!

大したことを行うような条件ではないのに副問合せを二重で行わなければならないというのが、なんいうか意外でした。

追記:Javaでオブジェクト指向とリバーシ作成


Javaでオブジェクト指向とリバーシ作成2 - メモ的な何か
前回で一応リバーシ作成は完結しましたが、残っていたパネルへの表示がうまくいってない(更新がボード部分と同時になっていたため、ボードの描画中にいったん消えてしまうようだった)ことを修正しましたのでメモしておきます。

修正方法は修正前は以下のようになっているところを
  JFrame -- JPanel(ボード表示) -- JLabel(文字表示)

修正後では以下のように修正しました
  JFrame -- JPanel(ボード表示)
      |_ JPanel(文字表示)

パネルで描画処理を行っているので、別々のパネルを用意し単純に描画を分けました。(ラベルからパネルにしたのは応用が利くと思ったので)

記述方法は文字表示用のパネルクラスを用意しました。
ConsolPanel.java

package reversi;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;

import javax.swing.JPanel;

@SuppressWarnings("serial")
public class ConsolPanel extends JPanel {
	private static final int PANEL_WIDTH = 800;
	private static final int PANEL_HEIGHT = 50;

	private String str;

	public ConsolPanel() {
		setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
		setBackground(Color.BLACK);

	}

	public void setString(String str) {
		this.str = str;
	}

	@Override
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		g.setColor(Color.WHITE);
		if (str != null) {
			g.drawString(str, 10, 20);
		}
	}
}

文字列をセットして描画を呼べば表示されます。
これをフレームでインスタンス化します。

ReversiFrame.java

	public ReversiFrame() {
		setTitle("リバーシ");

		setLayout(new BorderLayout());

		ConsolPanel consolPanel = new ConsolPanel();
		ReversiPanel panel = new ReversiPanel(consolPanel);

		Container contentPane = getContentPane();
		contentPane.add(panel, BorderLayout.NORTH);
		contentPane.add(consolPanel, BorderLayout.SOUTH);

		pack();
	}

こんな感じで2つのパネルの配置とボードのパネルに文字表示用のパネルを渡して、ゲームマスターの文字表示が行えるようにしました。

最終的な画面も貼っておきます(あまり変わってないですがw)
f:id:rui_phone:20140927155228p:plain

ソースはGitHubにPush済みです。
かつjarのアップロードもしました!ダブルクリックで実行できると思います!
先攻黒が自動プレイヤーになってます。(動作確認はJavaSE-1.7で行ってます)

ruihub/java_reversi · GitHub

これにてリバーシは(たぶん)完です!

Javaでオブジェクト指向とリバーシ作成2

前回の記事ではクラスの操作の分析まで行いました。

このあとはこの分析をもとにクラス図を作成します。

4、クラス図を作成する

クラス図の作成は今回astah communityというツールを使用しました。私はなんでもエクセルで作成する慣習には反対派なので、なるべくツールを使えるところは使っていこうと思います。

このツールはクラス図からJavaクラスを生成できたりいろいろ便利なのですが、今回はオブジェクト指向の考えをつかむことが目的なので細かい機能は使っていきません。何か機会があるときにおぼえられればと思ってます。

作成したクラス図が以下になります。

f:id:rui_phone:20140923225035j:plain

前回の記事のクラス操作の分析で描いたように矢印側がメソッドを持つことになりますのでそこに注意してクラス名の下の下の段にメソッドを書いていきます。(引数、戻り値はサボりました・・・)

クラス間のつながりはクラス同士の関係性を書いています。これでどのクラスがどのクラスと関係(操作を行うか)があるかがわかります。

また操作にある名詞の中から状態として持つべきものをフィールドとしてクラス名の下の段に記入します。

このクラス図を見れば必要なクラスとそのクラスにあるメソッドとフィールドがわかるのでプログラムがみえてきました。

本ではさらにシーケンス図の作成も行ってました。シーケンス図とはクラスを横に縦を時間とし、操作を記入していくものです。クラスのフローチャートみたいなものだと思ってます。今回は複雑じゃないし、サボります。

ここで他の処理はクラス、メソッドにしないとか、GUIの処理はどうするかとかの疑問がでてくると思います。これが大きなポイントだと思うんですが、この時のクラスの分析に実際のリバーシと関係がないことについては分析に含めないのが肝心です。そうすることでわかりやすくなりますし、表示しなくてもリバーシはPCの中で行えます。

5、プログラムを作成する。

ここはもうクラス図を見て各々実装なのですが、一応どのように作っていったかを書こうと思います。

私の場合はまずコンソールに以下のようなコンソールで出力するようなプログラムを書きました。上で書いたように先のクラスだけで十分にリバーシできてます!
手動の入力ではなく、自動で石を置くプレイヤーを作成しています。(GUIではクリック入力やります)
見てもらえばわかるようmain文はシンプルです。(GUIの時はMain.javaは使いません)

f:id:rui_phone:20140923233923p:plain

今度はこれを拡張していきGUIをつけていきます。

フレーム、パネル等はこのサイトを参考にさせてもらいました。

GUI化のポイントとしては表示するものを考えることです。

リバーシの場合はマス(ボード)と石になりますので、そこにそのオブジェクトの状態の表示用メソッドを用意します。

Board.java

	public void draw(Graphics g) {
		for (int i = 0; i < BOARD_SIZE; i++) {
			for (int j = 0; j < BOARD_SIZE; j++) {
				masus[i][j].draw(g);
			}
		}
	}


Masu.java

	public void draw(Graphics g) {
		g.setColor(backgroundColor);
		g.fillRect(gX, gY, gSize, gSize);
		g.setColor(frameColor);
		g.drawRect(gX, gY, gSize, gSize);

		if (stone != null) {
			stone.draw(g, (int) (gSize * stoneCoefficient), gX + (gSize / 2),
					gY + (gSize / 2));
		}
	}


Stone.java

	public void draw(Graphics g, int size, int x, int y) {
		g.setColor(color);
		g.fillOval(x - size / 2, y - size / 2, size, size);
	}

Board.javaのdrawを呼ぶことで石、マスの表示を行えることがわかります。
このBoard.javaをパネル(ウィンドの中身部分)の表示メソッドで読んでいます。

ReversiPanel.java

	@Override
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		board.draw(g);
		try {
			Thread.sleep(500);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}


またBoard.javaではボードの変化をパネルに伝えるためにパネルの表示メソッド(update)を呼べるようにしています。

Board.java

	public void out() {
		if (panel != null) {
			panel.update(panel.getGraphics());
		}
		System.out.println(this);

	}

またここで標準出力も行っており、表示部分を一つに絞っております。

またGUIではマウスでの入力用としてPlayerクラスを拡張したMyPlayerクラスを作成しております。
このクラスで実装したメソッドをパネルで呼ぶことによって、入力値をMyPlayerに伝え、クリックした場所に石を置けるようにしております。

MyPlayer.java

	public void clickOnStone(int x, int y) {
		if (inputState) {
			mauseX = x;
			mauseY = y;
			inputFlag = true;
		}
	}

ReversiPanel.java

	@Override
	public void mouseClicked(MouseEvent arg0) {
		// TODO 自動生成されたメソッド・スタブ
		if (firstPlayer instanceof MyPlayer) {
			((MyPlayer) firstPlayer).clickOnStone(arg0.getX(), arg0.getY());
		}
		if (secondPlayer instanceof MyPlayer) {
			((MyPlayer) secondPlayer).clickOnStone(arg0.getX(), arg0.getY());
		}
		update(getGraphics());
	}

またゲームマスターが誰の順番などを示しているので(コンソールでも)、これも表示できたらと思います。
そのためゲームマスターにはパネルにあるLabel(Labekで表示するようにしました)に対して出力するメソッドを持たせています。

Master.java

	public void out(String str) {
		if (label != null) {
			label.setText(str);

		}
		System.out.println(str);
	}


これでGUIの出力も完成しました!(実はLabelの表示は不安定なので要改修)
f:id:rui_phone:20140924010354p:plain

ここで注目してほしいのはコンソールからGUIを加えてもクラスの継承とメソッド、フィールドの追加で済んだということだと思います。
完璧ではないにしろオブジェクト指向の一つである拡張性が実現できたんではないかと思います。


ruihub/java_reversi · GitHub
ソースはGitHubにあげてます。ソースだけでクラスファイルとかもあげれたらあげる・・・


以上でリバーシの作成は終了しますが今後もオブジェクト指向考えながら設計してくつもりです。
ソース、考え方にご指導いろいろもらえると助かります!
取れあえず改修できたらブログ更新するかもです(笑)

初記事 Javaでオブジェクト指向とリバーシ作成

お初の記事となります。

主に技術系(プログラミング)メインで自分のメモ代わりに書いてきたいと思います。

 

早速本題なのですが、今回Javaリバーシ(オセロっすね)を作成してみました。

私、C言語が長いので(できるとは言ってない)Javaわかりません。オブジェクト指向もっとわかりません。

なんで今回はオブジェクト指向的な考え方でJavaを使ってリバーシを作成してトレーニングな感じです。

 

まず初めにいつもどおり何も考えず いきなりコード書き始めます。もちろん撃沈です(Cでもこれしてたからダメなんですね)

「オブジェクトって現実にあるもんだから白黒の石、ボード、マス?あとプレイヤーとか必要だ。あれ、GUIつけたいのに描画とかするオブジェクトっていなくね?ターンってオブジェクト」「石を置くってメソッドってプレイヤーが持ってんの?ボードが持ってんの?」

みたいなことを考えてたら頭がこんがらがり、ぐちゃぐちゃコードになり途中で挫折でした。

なのでとりあえずお勉強から入ろうと本買ってきました。

なぜ、あなたはJavaでオブジェクト指向開発ができないのか―Javaの壁を克服する実践トレーニング

なぜ、あなたはJavaでオブジェクト指向開発ができないのか―Javaの壁を克服する実践トレーニング

 

 本の内容はトランプゲームをオブジェクト指向で設計、製作していく内容で個人的には分かりやすく、読みやすかったです。

 

本をこなすと何となくクラス設計の考え方がわかってきたので、この本の内容に沿ってリバーシを作成していきたいと思います。

1、作成物の概要を文章にする。

これは機械にプログラミングで教えるにあたって、とりあえず日本語で説明しよう的なやつです。作ったものが下記になります。

 

プレイヤーの人数
プレイヤーは2人とする。

ボード
8マス×8マスとする。

ゲームの開始
ゲームマスターにプレイヤーを教える。
ゲームマスターがプレイヤーの順番を決める
先攻プレイヤーに黒、後攻プレイヤーに白とする。
両プレイヤーはボードの中央に黒、白の石を2つずつ置く。

ゲームの流れ
ゲームマスターが先攻から順番にプレイヤーを指名する。
指名されたプレイヤーは石を置ける位置を取得。
置けるところがある場合
プレイヤーによって動作を変える
・入力プレイヤー
石を置きたい場所を選択。
取得した位置と一致する場合、石を置く。
取得した位置と不一致な場合、石を置きたい場所を選択に戻る。
・自動プレイヤー
取得した位置から置ける場所を選択。
石を置く。

置いた石と同じ色の石に挟まれた違う色の石をひっくり返す。
白、黒石の数を数える。
ボードに置くとこがなくなった場合は石の数が多いプレイヤーが勝利とし、結果を表示し、ゲームを終了する。

置けるとこがない場合
パスをする。

ゲームマスターが次のプレイヤーを指名する。

 

まあ、こんな感じで考えました。はい、日本語も苦手なことがバレましたね。

 

 2、クラスになりえそうな名詞を抜き出す

ここでクラスの検討になります。それっぽいものを適当でいいので抜きだします。

 

プレイヤー、ゲームマスター、石、マス、ボード

 

的な感じですね。先の文章でゲームマスターとか書いてたのこのためです。せこい手つかいました。ターンとかの役割をゲームマスターが行ってくれるのでゲーム的なものは結構いいんじゃないかと思います。本でもやってましたし・・・

 

3、クラス操作の分析

操作とはクラス間のメッセージになります。先ほど上げたクラス間でどんなやり取りがあるか考えます。

文章のゲームの準備とゲームの開始に分けて考えてみます。

図と矢印で考えるとわかりやすいんでパワポで適当に図描きました。

 

 f:id:rui_phone:20140923211214p:plain

f:id:rui_phone:20140923212537p:plain

こんな感じになります。図についての意見は言わなくていいです。

最初は大体で描ければいいと思います。作ってるうちに増えたり減ったりしています。

ここで重要だと思ったのが矢印の向きになります。矢印が付いてるほうがメソッドを持つ方と反対が呼び出す方になります。

 

長くなってきた気がするので、次の記事に続きます。