こんにちは、友人、そして将来の同僚です! つい最近、実際のプロジェクトに参加するためのテストを受けて合格したのですが、たまたま個人的な事情によりRP自体に参加できなくなってしまいました。RP テストのような興味深い問題の後は、特に私がすでにほとんどの問題を解いてしまったので、通常のコースの問題はそれほど魅力的な娯楽ではなくなりました。そこで、学習を続けるために自分の才能を無駄にしないために、マルチプレイヤー Web ゲームを作成することにしました。他のゲームへのリンク:
私にとって三目並べは最も単純なゲームのように思えたので、タスクをいくつかのサブタスクに分割することにしました。
一番最初のアルゴリズムはフィールド全体をチェックすることです
- ゲームロジックをテストするためのコンソールアプリケーション
- マルチプレイヤー
- プレーヤー データベースをコンソール アプリケーションにアタッチする
- フロントエンドデザインの作成、ページテンプレートの作成、ゲームインターフェイスの作成
- すべてを一緒に入れて
- 分野
- 2人のプレーヤーが交代で、1人はクロスを入れ、2人目はゼロを入れます。それは簡単です。
String[][] strings = {{"O", "O", "_"},
{"_", "X", "O"},
{"X", "X", "X"},
for (String [] ss : strings){
for (String s : ss) System.out.print(s + " ");
System.out.println(); //для перевода строки
}
画面には次のように表示されます。
O O _
_ X O
X X X
ただし、表示に加えて、値の比較もあり、ここではすでにオプションが可能です。文字列を比較したり、特別な列挙クラス ( enum
) を作成したりすることもできますが、数値を比較し、画面に表示されるときのみ「X」と「O」に置き換えることを好みます。たとえば、1 - 「X」、2 - 「O」、0 - 「_」とします。では、トリプル X または O の一致についてフィールドをチェックするにはどうすればよいでしょうか?
一番最初のアルゴリズムはフィールド全体をチェックすることです
int[][] canvas = {{00, 01, 02},
{10, 11, 12},
{20, 21, 22}}
勝ちの組み合わせ:
00-01-02, 10-11-12, 20-21-22, 00-10-20, 01-11-21, 02-12-22, 00-11-22, 20-11-02 — всего 8.
数値を比較してチェックしますが、フィールド全体、8 つの組み合わせすべてを毎回チェックする必要があることがわかります。もちろん、これは大したことではありません。これは 0 から 10 億の範囲のアームストロング数値を検索するものではありません。ここでは計算はほとんどありませんが、フィールド全体をチェックするよりも最適なものが必要です。私が思いついた 2 番目のアイデアは、前の動きでマークされたセルのみをチェックすることで、誰がこの動きをしたかがわかるため、勝者を決定することができます。したがって、8 つの組み合わせすべてではなく、セルに応じて 2、3、または 4 つの組み合わせのみが得られます。図を参照してください。 次に、どの組み合わせを起動する必要があるかを判断する方法を理解する必要があります。ここで、2 次元配列を使用するのはあまり便利ではないことに気づきました。他の選択肢も検討してみることにしました。最初に、フィールドを 9 桁の数字で保持できるというアイデアを思いつきました。たとえば、画面に表示したのと同じフィールドを次のように書くことができます: 220012111、それが何であるかを指で説明します。コードは同じです。1 - "X"、2 - "O"、0 - " "、つまり 220012111 = "OO__XOXXX"、または 3 桁ごとに改行を挿入し、スペースを追加した場合明瞭さ:
О О _
_ Х О
Х Х Х
ここでもまた、保管には便利で、展示用の装置が発明されましたが、比較するには不便です。プログラミングでは0からカウントダウンが始まるので、セルに1から9まで番号を振ってみたら解決策が見つかったので、図のように番号を振ってみ ました。上の図を見ると、2 つの組み合わせのソリューションには奇数のシリアル番号があり、4 つの組み合わせにはシリアル番号 4 があり、3 つの組み合わせには残りのシリアル番号が付いていることがわかります。そこで私は、競技場を数値の規則的な配列に保つ必要があるという結論に達しました。つまり、数値間の単純な反復、選択されたアルゴリズムに従って比較する機能、画面への単純な出力です。比較アルゴリズム自体については。順番に見ていきましょう。すべてのオプションで行と列のチェックが行われますが、それらのみをチェックします。検索結果が見つからない場合は、セル番号の偶数/奇数をチェックし、奇数の場合はゲームに戻ります。これ以上チェックする意味はありません。偶数の場合は、このセルが上にあるかどうかを確認します。左対角線の場合、この対角線の数字は 4 で割ったときの余りが 0 になります。一致する場合は一致するかどうかを確認し、一致するものが見つからない場合は数字 4 を確認し、一致しない場合はゲームに戻ります。はい、コードをさらに進めて、最後の対角線をチェックした結果を返します。おそらく、準備ができていない人にとって、上記の一連の文字を読んでもこれを理解するのは難しいでしょう。しかし、コード自体に多くの文字が含まれていると言う人もいるかもしれません。その方が簡単かもしれません。これについては喜んで議論します。フィールドを整理しました。今度は、交代でそれぞれ独自の記号 (X または O) を持つ 2 人のユーザーを処理する必要があります。最初の段階では、マルチユーザー機能がありません。最も簡単な方法は、アイコンを 1 つずつ使用することです。X は常に最初の動きをし、O は常に 2 番目の動きをし、その後再び X を行います。それはチェックされます ( true/false )。 trueの場合– 現在のプレイヤーは X、falseの場合 – O であり、各動きの開始時に flag=!flag どういうわけかプレイヤーからシグナルを受信する必要があります。彼らが選んだ細胞。ここでは、忘れられないBufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
プレイヤーがコンソールにセル番号を入力し、Enter キーを押すと動きます。入力された数値に対応するセルの値は、上の段落で説明したチェックボックスの現在の状態に応じて、0 から 1 または 2 に変わります。ここで、セルがすでに入力されているときに誰も X を O に変更できないように、入力を検証することが重要です :) プレーヤーはコンソールに何を入力できますか?
- 空行
- 文字、句読点、括弧...一言で言えば、数字以外
- 数値が正しくありません - 負または配列サイズ外、セルが占有されています。
Integer.parseInt("2");
さNumberFormatException
れます。この例外をインターセプトすることで、最初の 2 点から保護できます。3 番目の点については、入力された値をチェックする別のメソッドを作成しますが、文字列リクエストを検証が実行される別のメソッドに移動し、数値のみを返すのが最も正確です。要約すると、フィールドを作成し、それを表示するメソッドを作成し、「このプレイヤーは 1 時間以内に勝ったかどうか」を確認するメソッドを作成し、入力された数値を検証しました。やるべきことはほとんど残されていません。引き分けを確認します。これは、配列を実行して 0 を探し、ゲーム結果を表示する別のメソッドです。これだけで、コードの準備は完了しました。ゲームは小さく、クラスが 1 つだけであることが判明しました。非常にタフなコピーペースト者は、理解せずにすべてを自分のプロジェクトにコピーして、自分で実行することができます。私自身もそうでした。今はそうしないようにしていますし、誰にも勧めません :) JAVA の学習で皆さん頑張ってください! ps、残りのポイント - マルチプレイヤーとデータベースは後で説明します。私はすでに教材の勉強を始めています:)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class GameField {
static int [] canvas = {0,0,0,
0,0,0,
0,0,0};
//012, 345, 678, 036, 147, 258, 048, 246
public static void main(String[] args){
boolean b;
boolean isCurrentX = false;
do {
isCurrentX = !isCurrentX;
drawCanvas();
System.out.println("mark " + (isCurrentX ? "X" : "O"));
int n = getNumber();
canvas[n] = isCurrentX ? 1 : 2;
b = !isGameOver(n);
if (isDraw()){
System.out.println("Draw");
return;
}
} while (b);
drawCanvas();
System.out.println();
System.out.println("The winner is " + (isCurrentX ? "X" : "O") + "!");
}
static int getNumber(){
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true){
try {
int n = Integer.parseInt(reader.readLine());
if (n >= 0 && n < canvas.length && canvas[n]==0){
return n;
}
System.out.println("Choose free cell and enter its number");
} catch (NumberFormatException e) {
System.out.println("Please enter the number");
} catch (IOException e) {
}
}
}
static boolean isGameOver(int n){
// 0 1 2
// 3 4 5
// 6 7 8
//поиск совпадений по горизонтали
int row = n-n%3; //номер строки - проверяем только её
if (canvas[row]==canvas[row+1] &&
canvas[row]==canvas[row+2]) return true;
//поиск совпадений по вертикали
int column = n%3; //номер столбца - проверяем только его
if (canvas[column]==canvas[column+3])
if (canvas[column]==canvas[column+6]) return true;
//мы здесь, значит, первый поиск не положительного результата
//если meaning n находится на одной из граней - возвращаем false
if (n%2!=0) return false;
//проверяем принадлежит ли к левой диагонали meaning
if (n%4==0){
//проверяем есть ли совпадения на левой диагонали
if (canvas[0] == canvas[4] &&
canvas[0] == canvas[8]) return true;
if (n!=4) return false;
}
return canvas[2] == canvas[4] &&
canvas[2] == canvas[6];
}
static void drawCanvas(){
System.out.println(" | | ");
for (int i = 0; i < canvas.length; i++) {
if (i!=0){
if (i%3==0) {
System.out.println();
System.out.println("_____|_____|_____");
System.out.println(" | | ");
}
else
System.out.print("|");
}
if (canvas[i]==0) System.out.print(" " + i + " ");
if (canvas[i]==1) System.out.print(" X ");
if (canvas[i]==2) System.out.print(" O ");
}
System.out.println();
System.out.println(" | | ");
}
public static boolean isDraw() {
for (int n : canvas) if (n==0) return false;
return true;
}
}
GO TO FULL VERSION