質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

Q&A

解決済

5回答

1733閲覧

クラスを配列の添字に...?

mightyMask

総合スコア143

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

0グッド

0クリップ

投稿2017/02/25 11:30

#前提
teratail.com/questions/67133
ここで質問した者です。
javaのswingを用いてGUIの将棋ソフトを作成しています。
ほぼ趣味プログラマーであり、プログラミング初心者です。
厳格で純粋なオブジェクト指向に近いコードで綺麗に書く事を目標とします。
そのため、早く軽快な動作は期待しません。
ソースコードを短くするという事も期待しません。

#クラスの関係
駒クラス(抽象)
歩、金、成桂などのクラス
駒台クラス

#質問
将棋の駒台クラスを作るにあたり、どのような設計にすれば良いものか悩んでいます。
ArrayListを使い駒台が所持している駒を保持するという方法を取ろうと思っていましたが、以下のような設計の方が色々と都合が良いのです。
駒台に乗る駒は飛、角、金、銀、桂、香、歩の7種類しかありません。
そこで、この7種の駒をそれぞれ何枚ずつ持っているかという事をint[7]という配列のようなもので管理する。
この方法で実現したいのですが、この構造だと困ることもあるわけです。
駒台クラスに必要なメソッドとして例えば、駒大に駒を追加する(引数は駒クラス)というものがあります。
引数から、配列のどの要素に+1するのかというのを決定するにはif/switchで条件分岐するという方法しか思いつきません。
配列名[引数で受け取った駒クラス] ++;この様に処理できればうまくいくわけですが...
javaのハッシュマップ機能を使えば実現できるわけですが、クラスを取得し、それをキーとするっていうのは美しくないし綺麗じゃないんですよね。
(クラスを取得する事をリフレクションと言うのでしょうか?)
そもそもクラスを配列の添字として使うのは良いやり方なのでしょうか。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

ベストアンサー

こんにちは。

駒クラスで参照しているインスタンスから駒台[0]駒台[6]へのマッピングが必要になります。
そのために方法の1つは質問で書かれている方法ですね。他にも様々な方法があります。

  • 各駒クラスの派生クラスにstaticなint型への参照を持ち、各駒台[n]への参照を設定する。
  • 先程の質問で回答した駒側で定義したインデックス番号を使う。
  • リフレクションで駒のクラス名を取り出し、名前に対してマッピングする。

などなど。

投稿2017/02/25 12:40

編集2017/02/25 13:55
Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mightyMask

2017/02/25 13:10

1つ目の方法はそれぞれの駒クラスにまたそれぞれ子クラスを作ると言う事でしょうか。局面クラスがその子クラスを40つ保持し、駒の所在地ははその子クラスが保持するという事でしょうか。 んーよく分かりませんがなんだか回りくどい事をすることになると思えますが、どうなんでしょう。 2つ目のインデックス番号をつけると言うのはZuishinさんが仰られる様になんだか美しくない様に思えます。 3つ目もなんだか気持ちの良い実装方法とは思えないんです。 厳格で純粋なオブジェクト指向で設計するなら、リフレクションやキーマップなんかは必要ないものだというのが私の考えです。 Featherweight Javaという言語があるらしいですが、私がイメージする厳格で純粋なオブジェクト指向に一番近いもがこれです。 私は英語が絶望的に苦手なので、Featherweight Javaというものがよくわからなかったため質問には載せませんでしたが、http://tarao.hatenablog.com/entry/20100419/1271645340で説明されている様なものだと思います。
Chironian

2017/02/25 13:55

> 局面クラスがその子クラスを40つ保持し、駒の所在地ははその子クラスが保持するという事でしょうか。 違います。 駒クラスは抽象クラスですよね。ぞれを派生した金クラスや銀クラス等にstatic変数を追加します。 プログラム起動時等に、そのstatic変数へ駒台[n]への参照を設定しておけば、後は「引数の駒クラス.static参照変数++;」でaddできます。至極簡単です。 インデックス番号を使う方法も下記要件に対しては何ら問題なく使えます。 「配列名[引数で受け取った駒クラス] ++;この様に処理できればうまくいくわけですが... 」 しかし、各配列の要素に対応するクラスを特定することが必要なら、どの案を使ってもなにか工夫が必要です。名前で対応しようが数値で対応しようが同じことです。 mightyMaskさんのもやもやは、この逆引きの要件を定めていないことから来ているのかも知れませんね。
Chironian

2017/02/25 14:01

> Featherweight Javaという言語があるらしいですが、私がイメージする厳格で純粋なオブジェクト指向に一番近いもがこれです。 なるほど。実用的な話ではなく、学術的な話をされているのですね。 すいません。学術的な私の知識は30年くらい古いのでお役には立てそうにないです。
guest

0

私に言わせれば数字を添え字にする方が美しくないと思います。
駒と数字には何の関連もありません。

駒クラスを作り、そこから派生した歩クラスを作り、getClass() あるいは toString() したものをキーにすればいいではありませんか。

投稿2017/02/25 12:31

Zuishin

総合スコア28660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2017/02/25 12:35

将棋の駒の種類が増えることは考えにくいことですが、ありえないことではありません。将棋から派生した別のゲームに対応する状況はよくあることです。その場合、駒と番号を関連づけていたら、駒と番号の対応に依存している部分を全ソースから見つけて必要に応じて修正しなければなりません。関連付けなければその作業は不要になります。
mightyMask

2017/02/25 12:43

はいそうです。私も数字を添字にしようとは思っていません。 数字を添字にすると美しくないので今の所はgetClassでクラスを取得しハッシュマップのキーとして使うという方法をとっています。 厳格で純粋なオブジェクト指向に近いソースコードを目標としているので、数字を使うよりはマシですが、どちらの方法も美しいやり方とは思えません。
Zuishin

2017/02/25 14:12

何が美しくて何が美しくないのか基準がさっぱりわかりませんが、純粋で厳格なオブジェクト指向ということになると、if や switch はどうなんでしょうね? どちらも純粋な手続きであり、オブジェクトに対するメッセージではありません。
Zuishin

2017/02/25 14:25

mightyMask さんの言われる「厳格で純粋なオブジェクト指向」は通常使われる意味での「厳格で純粋なオブジェクト指向」と乖離があるように感じます。まず mightyMask 風オブジェクト指向の定義から始めたら良いのではないでしょうか?共通の用語を使わなければ話は通じません。
guest

0

駒をenumで作成して、数の記録はEnumMapを使うと良いです。

「クラスを取得する」というのは、全種類の駒をクラスとして定義しているからですよね?
enumにすればそれぞれが「値」になるのでさほど違和感なくMapに組み込めます。
コンストラクタを用意して初期化を行えるようにしたり、
共通の抽象メソッドを用意し、それを各列挙でオーバーライドすることもできます。

java

1public enum Piece { 2 FU(1) { 3 // オーバーライドなど 4 } 5 KIN(2) { 6 // オーバーライドなど 7 } 8 ... 9 private final int x; 10 private Piece (int i) { //コンストラクタはprivate限定 11 x = i; 12 } 13} 14--- 15 16Map<Piece, Integer> table = new EnumMap<>(Piece.class); 17table.merge(Piece.FU, 1, Integer::sum);

投稿2017/02/25 12:27

編集2017/02/26 01:23
swordone

総合スコア20651

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

盤面と駒台を勘違いしていたので回答をごそっと編集。(前の回答は、編集履歴を参照ください。)
ただ、基本的な考えは変わらず。
盤面、駒台に存在する駒オブジェクトのリストと、
プレイヤー、プレイヤーが操作可能な駒オブジェクトのリストという概念が存在すれば。
駒の数自体を管理する必要はなく、必要な時にリストから集計する形でよいと考えています。

1.プレイヤーが、操作可能な駒のリストを持っているとして、
そのリストの中から、1つの駒オブジェクトを選択。
2.ゲームの進行を管理するゲームマスタークラスがいるとして、
ゲームマスターは、その駒オブジェクトが、盤面、駒台のどちらに含まれているか確認、
駒を配置できる位置を返却。
3.プレイヤーは、その位置の中から駒を置く場所を指定する。

といった流れを考えていました。

投稿2017/02/27 03:12

編集2017/02/27 04:00
abs123

総合スコア1280

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2017/02/27 03:19

駒台というのは盤面のことではなく、手駒を置く台のことです。
abs123

2017/02/27 03:35

ああ、検索して画像がぱっと見盤面に見えたから勘違いしてました。 修正しますね。
guest

0

みなさんと同じようなことに過ぎませんが、「あるものに対する関連情報をenumとして宣言的に定義」という方法があります。本件についていえば駒に関連する色々な情報があるように思えるのであちこちの連想コレクションを使って分散して定義するよりは一括して集中定義できるので自分は好んで使います。これがオブジェクト指向的かどうかと言われれば「駒の種類」をどんなクラスとして捉えるか如何にかかると思います。

メタ情報の代表はクラスオブジェクトですがクラスメソッドやクラスフィールドが必ずしも都合よく定義できない(※)のでメタ情報を保持するなんらかのメタクラスがほしくなります。必ずしもenumでなくてもよいのですがインスタンスの宣言が

static final Meta 王 = new Meta("王", ...);

ではなく、

王(...),

と書けば済むというだけの理由でenumの方が若干短く書けます。

java

1enum 駒の種類 { 2(...), 3(..., 0), 4(..., 1), 5 ... 6(..., 6), 7 ; 8 private int komadaiIndex; 9 10 駒の種類(...) { this(..., -1); } 11 12 駒の種類(..., int komadaiIndex) { 13 ... 14 this.komadaiIndex = komadaiIndex; 15 } 16 17 ... 18 19 public int getKomadaiIndex() { 20 if (komadaiIndex == -1) 21 throw new InternalError(name() + " has no komadaiIndex"); 22 return komadaiIndex; 23 } 24} 25 26classModel { 27 public abstract 駒の種類 get駒の種類(); 28 ... 29} 30

※:クラスメソッドやクラスフィールドが必ずしも都合よく定義できない
例えばstaticメソッドやstaticフィールドをクラスメソッド・クラスフィールドにみたてて使える場合もあると思いますがこれらは継承できないので、以下のように書けないのです。

java

1Class<? extendsModel>ModelClass = ...; 2int komadaiIndex =ModelClass.getKomadaiIndex();

投稿2017/02/25 14:15

KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問