JavaRush /Blog Java /Random-MS /Permainan Java untuk pemula
timurnav
Tahap

Permainan Java untuk pemula

Diterbitkan dalam kumpulan
Hello rakan-rakan dan rakan sekerja masa depan! Permainan Java untuk pemula - 1Baru-baru ini, saya mengambil ujian untuk mengambil bahagian dalam projek sebenar, lulus, tetapi kebetulan kerana keadaan peribadi saya tidak dapat mengambil bahagian dalam RP itu sendiri. Selepas masalah menarik seperti ujian RP, masalah kursus biasa menjadi hobi yang kurang menarik, terutamanya kerana saya telah menyelesaikan kebanyakannya. Oleh itu, supaya bakat saya tidak disia-siakan untuk terus belajar, saya memutuskan untuk mencipta permainan web berbilang pemain. Pautan ke permainan lain:
  1. sambungan artikel ini
  2. 2048
Tic Tac Toe kelihatan seperti permainan yang paling mudah bagi saya, jadi saya memutuskan untuk memecahkan tugas itu kepada beberapa subtugas:
  1. Aplikasi konsol untuk menguji logik permainan
  2. Berbilang pemain
  3. Melampirkan pangkalan data pemain pada aplikasi konsol
  4. Mencipta reka bentuk bahagian hadapan, menulis templat halaman, antara muka permainan
  5. Menyatukan semuanya
Terdapat kemungkinan bahawa saya akan dimarahi untuk urutan sedemikian, dan kemungkinan besar semua projek yang serius dibina dalam urutan yang sama sekali berbeza, saya akan menjawab dengan segera, menulis siaran tentang ini "untuk pemula" supaya semua orang (termasuk saya) boleh belajar ini :) Baiklah. Mari mula menulis aplikasi konsol! Saya akan mengikuti langkah yang sama seperti cabaran tahap 20 yang besar. Apa yang ada dalam permainan tic-tac-toe?!
  1. padang
  2. dua pemain yang bergilir-gilir, seorang meletakkan pangkah, yang kedua sifar. ianya mudah.
Kami menjadikan medan itu sebagai medan 3x3 standard. Bagaimanakah medan sedemikian boleh disimpan? pilihan pertama ialah tatasusunan dua dimensi. Apakah elemen yang harus ada dalam tatasusunan ini? Jawapannya ialah kita perlu memikirkan apa yang akan kita lakukan dengan elemen ini, ini memaparkan dan membandingkan untuk mencari pemenang. Jika kita hanya memaparkannya pada skrin, maka adalah logik untuk mengekalkannya sebagai rentetan, maka tatasusunan itu sendiri dan memaparkannya pada skrin dalam gelung akan kelihatan seperti ini:
String[][] strings = {{"O", "O", "_"},
                    {"_", "X", "O"},
                    {"X", "X", "X"},
for (String [] ss : strings){
    for (String s : ss) System.out.print(s + " ");
    System.out.println(); //для перевода строки
}
skrin akan memaparkan:
O O _
_ X O
X X X
Tetapi sebagai tambahan kepada paparan, kami juga mempunyai perbandingan nilai, dan di sini pilihan sudah mungkin. Anda boleh membandingkan rentetan, anda boleh mencipta kelas penghitungan khas ( enum), tetapi saya lebih suka membandingkan nombor, dan menggantikannya dengan "X" dan "O" hanya apabila dipaparkan pada skrin. Biarkan ia, sebagai contoh, 1 - "X", 2 - "O", 0 - "_". Jadi, bagaimanakah anda menyemak medan untuk padanan tiga X atau O?
Algoritma pertama adalah menyemak seluruh medan
int[][] canvas = {{00, 01, 02},
                 {10, 11, 12},
                 {20, 21, 22}}
Kombinasi kemenangan:
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.
Menyemak dengan membandingkan nombor, tetapi ternyata anda perlu menyemak SELURUH medan, kesemua 8 kombinasi, setiap kali. Sudah tentu, ini tidak banyak, ini bukan carian untuk nombor Armstrong dalam julat dari 0 hingga 1 bilion, terdapat lebih sedikit daripada tiada pengiraan di sini, tetapi anda masih mahukan sesuatu yang lebih optimum daripada menyemak seluruh medan. Idea kedua yang datang kepada saya adalah untuk menyemak hanya sel yang ditanda pada langkah sebelumnya, jadi kita masih boleh menentukan pemenang, kerana kita akan tahu siapa yang membuat langkah ini. Oleh itu, daripada semua 8 kombinasi, kita hanya mendapat 2, 3 atau 4 kombinasi, bergantung pada sel, lihat gambar: Permainan Java untuk pemula - 2Sekarang kita perlu memikirkan bagaimana untuk menentukan gabungan mana yang perlu dilancarkan? Di sinilah saya menyedari bahawa menggunakan tatasusunan dua dimensi tidak begitu mudah. Saya memutuskan untuk melihat pilihan lain. Pada mulanya saya mendapat idea bahawa medan itu boleh disimpan dalam nombor sembilan digit, sebagai contoh, medan yang sama yang kami paparkan pada skrin boleh ditulis seperti ini: 220012111, saya akan menerangkan dengan jari saya apa itu ialah... Kod adalah sama, 1 - “X”, 2 - “O” , 0 – " ", yang bermaksud 220012111 = "OO__XOXXX", atau jika selepas setiap digit ketiga anda memasukkan pemisah baris dan menambah ruang untuk kejelasan:
О О _
_ Х О
Х Х Х
di sini sekali lagi, mudah untuk penyimpanan, peranti untuk paparan telah dicipta, tetapi menyusahkan untuk perbandingan! Penyelesaiannya ditemui apabila saya menomborkan sel 1-9, kemudian saya berfikir, kerana dalam pengaturcaraan kira detik bermula dari 0 dan menomborkannya seperti dalam gambar. Permainan Java untuk pemula - 3Adakah anda tidak perasan sebarang keanehan? jika anda melihat gambar di atas, ia akan menjadi jelas bahawa penyelesaian dengan 2 kombinasi mempunyai nombor siri ganjil, 4 kombinasi mempunyai nombor siri 4, 3 kombinasi mempunyai selebihnya. Jadi saya sampai pada kesimpulan bahawa anda perlu mengekalkan padang permainan dalam susunan nombor biasa: lelaran mudah antara nombor, keupayaan untuk membandingkan mengikut algoritma yang dipilih, output mudah ke skrin. Bagi algoritma perbandingan itu sendiri. Mari kita berurutan: dalam semua pilihan terdapat semakan baris dan lajur, kami hanya menyemaknya. jika carian tidak membuahkan hasil, kami menyemak nombor sel untuk genap/ganjil, jika ganjil, kemudian kami kembali ke permainan, tidak ada gunanya menyemak lebih lanjut, jika ia genap, kami menyemak sama ada sel ini terletak pada pepenjuru kiri, nombor pepenjuru ini apabila dibahagikan dengan 4 mempunyai baki 0. Jika ia terletak, kita semak padanan, jika tiada padanan ditemui, maka kita semak nombor 4, jika tidak, kembali ke permainan, jika ya, kami pergi lebih jauh melalui kod dan mengembalikan hasil pemeriksaan pepenjuru terakhir. Mungkin, bagi orang yang tidak bersedia, ini sukar difahami selepas membaca set surat di atas, tetapi seseorang mungkin mengatakan bahawa terdapat banyak huruf dalam kod itu sendiri, yang boleh menjadi lebih mudah, saya akan gembira untuk membincangkan perkara ini. Kami telah menyelesaikan bidang, kini kami perlu berurusan dengan dua pengguna yang bergilir-gilir dan setiap daripada mereka mempunyai tanda mereka sendiri, X atau O. Pada peringkat pertama, kami tidak mempunyai sebarang fungsi berbilang pengguna, jadi cara paling mudah ialah menggunakan ikon satu demi satu. X sentiasa membuat langkah pertama, O sentiasa membuat yang kedua, kemudian X lagi, dan seterusnya. Ia mohon untuk diperiksa ( benar/salah ), dan jika benar – maka pemain semasa ialah X, jika palsu – maka O dan pada permulaan setiap pergerakan flag=!flag Ia tetap menerima isyarat daripada pemain tentang yang mana sel yang mereka pilih. Di sini kami memerlukan BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); Pemain kami yang tidak dapat dilupakan akan memasukkan nombor sel ke dalam konsol, dan menekan Enter akan bergerak. Sel yang sepadan dengan nombor yang dimasukkan akan menukar nilainya daripada 0 kepada 1 atau 2, bergantung pada keadaan semasa kotak semak, yang telah dibincangkan dalam perenggan di atas. Di sinilah pentingnya untuk mengesahkan input supaya tiada siapa boleh menukar X kepada O apabila sel sudah diisi :) Apakah yang boleh dimasukkan oleh pemain ke dalam konsol?
  1. baris kosong
  2. huruf, tanda baca, kurungan... dalam satu perkataan, bukan nombor
  3. nombor yang salah - negatif atau di luar saiz tatasusunan, sel yang diduduki.
Kaedah standard untuk mendapatkan digit daripada rentetan ialah kaedah statik parseInt kelas Integer. Integer.parseInt("2");Ia membuang pengecualian NumberFormatExceptionjika ia tidak boleh mendapatkan digit daripada rentetan yang diberikan. Kami boleh memberikan perlindungan daripada dua titik pertama dengan memintas pengecualian ini. Untuk titik ketiga, saya akan mencipta kaedah lain yang menyemak nilai yang dimasukkan, tetapi adalah paling tepat untuk mengalihkan permintaan rentetan ke kaedah berasingan di mana pengesahan akan dilakukan, dan ia hanya akan mengembalikan nombor. Untuk meringkaskan, kami mencipta medan, membuat kaedah yang memaparkannya, membuat kaedah yang menyemak "adakah pemain ini menang sejam?", dan mengesahkan nombor yang dimasukkan. Terdapat sedikit lagi yang perlu dilakukan, semak untuk seri - kaedah berasingan yang dijalankan melalui tatasusunan dan mencari 0, dan memaparkan keputusan permainan. Itu sahaja, kod sudah siap, permainan ternyata kecil, hanya satu kelas, jadi copy-pasters yang sukar boleh, tanpa memahami, hanya menyalin segala-galanya ke dalam projek mereka dan menjalankannya sendiri, saya sendiri begitu, tetapi sekarang saya cuba untuk tidak berbuat demikian dan bukan kepada sesiapa yang saya cadangkan :) Semoga berjaya kepada semua orang dalam mempelajari JAVA! ps mata yang lain - berbilang pemain dan pangkalan data akan datang kemudian, saya sudah mula mengkaji bahan :)
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;
    }
}
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION