このプログラムはUTF-8で書かれています.
そのため,Windows環境で現在のLTSであるJava17においてこのプログラムをコンパイル,実行するとうまくいかない可能性があります.
これはJava17までプログラムファイルのデフォルトの文字エンコードをOS準拠のものとしているため, Mac並びにLinuxにおいてはUTF-8が選択されるものの, WindowsではShift-JISが選択されることに依拠します.
コンパイルの際にオプションで文字コードを指定すれば回避できますが, 現在の最新バージョンJava20ならびにLTSのJava17はどちらも今年の9月にサポートが終了するので素直にJava20を入れたほうが楽だと思います.
(JDK20で開発をしているため万一起動しなかった場合は最新バージョンのjavaをお試しください.(スレッドプール周りの関数がバージョンによっては未実装でエラーをはく可能性があります.))
残念ながら1ファイル1クラスの原則をガン無視しているので実装としては4つのファイルになっています.
- Server.java: サーバー部分の実装
- Client.java: クライアント部分の実装
- GUI.java: クライアントのGUIの実装
サーバーを立ち上げる際には
javac Server.java
java Server
クライアントを立ち上げる際には
javac Client.java
javac GUI.java
java Client
をそれぞれ指定してください.
GUI.javaはClient.javaが勝手に呼び出します.
各ファイルの中身は結構なボリュームです.Server.javaはある程度整理されていますが,Game.javaは個人で開発が完結していた,GUI.javaはぎりぎりまで開発していた関係でコードがぐちゃぐちゃです.
またServer.javaにはコメントアウトである程度説明が載っている一方,GUI.javaは開発終盤に実装した部分を中心に説明がなく,Game.javaに至ってはビット演算の説明が面倒で放棄しています(参考文献はコード内に記述してあるので頑張って).
また,このフォルダにはTest.javaが同封されていますが,これは合法手生成をテストするためのプログラムで本実装はされていません.記念ってことで残しておきました.(他にもテスト用のプログラムはあったのですが他のプログラムの仕様に依存して動くものが多かったので単体で完結しているこいつぐらいしか残らなかった.)
Server.javaはServerを立ち上げたユーザーからの入力を常に受け付けています.そこで,各コマンドが何に対応するかを記しておきます.
- shutdown: Server.javaを終了させます.基本的にこのコマンドで終了させるほうが安全です.
- info: サーバーの現在の状態を吐き出します.
- matchnow: マッチングを直ちに実行します.
- changematchtime: マッチングの間隔を変更します.この変更は直ちには適用されず,変更が行われてからマッチングが1度行われて適用されます.そのため,即材に適用したい場合は「matchnow」を併用するといいと思います.
残念ながら時間がなく未実装となってしまった構想をここに供養します
- チャット機能: サーバー全体でのチャット機能と対戦相手とのチャット機能を追加したかったが優先度自体は結構低めだった.理由としてはサーバーの負荷が増えるのをあまり好ましく思わなかったから.
- ユーザーログイン機能: ユーザー登録してレートを保持できるようなそんな構想.これも優先度としてはあまり高くなく,理由としてはそれなりのものを組もうと思ったらデータベースを実装しなければならずめんどうというもの.あと、やりすぎな気もする.
- ping機能: クライアント側ともセットの機能だがサーバーが動いているかを確認する機能を実装したかった.現状の実装だと即座にマッチング待機列に入れてしまうので変える必要がありそう(pingコマンドたたけば解決するのかな).
- 対戦観覧機能: 他者の対戦を観戦できるという機能.優先度は割と高かったがクライアント側でも見れるようにすると重くなりそうだなと思いサーバー側からのみ見れるようにするくらいならと後回し.それを実装しかたかった名残がソースコードに残ってるw
- 部屋立てマッチング: クライアントが部屋を立ててそこに入室してきた人と対戦できる機能.ランダムマッチングと違って友達と待ち合わせして対戦したり,特殊なルールで対戦したりという場面を想定していた.優先度は高めだったが,クライアントの実装が間に合いそうになく没.
- 4人オセロ: サーバー型にするんだからということで構想はあった.4人オセロ自体は市販もされている(パッと見た感じクソゲーだけど). Server.java側の実装はたいしたことないけどClient側の実装が間に合わない没.
GUI.javaはGame.javaがProcessBuilderで呼び出しています.そして標準入出力を利用したプロセス間通信を行ってデータをやり取りしています.
この実装の由来は単純で,最初はCUIベースでプレイヤーから標準入力で手を受け取り標準出力でボードを描画していたところにGUIをのっけた関係で,この実装が一番楽に実現できるからというだけです.
↓参考:CUIでのオセロボードの実装
a b c d e f g h
----------------
1| * * * * * * * * |
2| * * * * * * * * |
3| * * * O * * * * |
4| * * O w b * * * |
5| * * * b w O * * |
6| * * * * O * * * |
7| * * * * * * * * |
8| * * * * * * * * |
----------------
ちなみに,Test.javaはCUIでの実装になっているので,
34628173824
68853694464
を打ち込むと同じ図が出力されます.(後述)
一応,マルチスレッドでというのも考えましたが,時間がなくめんどうなのでやめました.
残念ながら時間がなく未実装となってしまった構想をここに供養します.
- 最終着手の強調表示: 画像だけは用意した.すぐに実装できそうだけどぎりぎりでタイムアップ.
- 観戦機能: Server.javaの項で述べた通り.
- 部屋立てマッチング: Server.javaの項で述べた通り.
- ルールの追加: 部屋立てマッチングにて想定.たとえばハンデをつけるとかナントカ.具体的な構想は部屋立てマッチングを作ってから考えるつもりだったのでペラペラ.
- 4人オセロ: Server.javaの項で述べた通り.一応,関数を改変するだけで実現できるが既存のオセロとルールが一部異なっておりその部分を実装するのがめんどいという残念な理由と時間の関係で没.
Windows環境でユーザー名に日本語を使用するとおそらくバグります.
原因はGUIとClient間の通信に標準入出力を使っている関係でこの文字のやり取りがShift-JISになる一方,Javaの内部ではUTF-8で文字が読まれるためです.
改修をするつもりはありましたが時間がありませんでした.
LinuxとMacではバグらないはずです(Linuxは面倒で,Macは嫌いなので未確認).
このプログラムは標準入力で黒,白それぞれの石が置かれている位置を表したlong型の整数を入力すると,黒番からみた合法手を生成してCUIで表示するものです.
このプログラムではデバッグ用にbitboardが回転して合法手生成される過程が出力されるようになっているので見てみると面白いと思います.
入力する整数は自分で生成することも可能ですがおそらく面倒なのでClient.javaをデバッグ実行して対戦を適当に行い任意のタイミングでストップしてGame.javaのローカル変数b(自分の石),w(相手の石)の値を持ってくるといいと思います.
いらすとや(画像): https://www.irasutoya.com/
ザ・マッチメイカァズ2nd(効果音): http://osabisi.sakura.ne.jp/m2/