JavaRush /Blog Java /Random-VI /Trò chơi Java cho người mới bắt đầu
timurnav
Mức độ

Trò chơi Java cho người mới bắt đầu

Xuất bản trong nhóm
Xin chào các bạn và đồng nghiệp tương lai! Trò chơi Java dành cho người mới bắt đầu - 1Gần đây, tôi đã tham gia một bài kiểm tra để tham gia vào một dự án thực tế và đã vượt qua nó, nhưng tình cờ là do hoàn cảnh cá nhân nên tôi không thể tham gia RP. Sau những bài toán thú vị như bài kiểm tra RP, những bài toán thông thường của khóa học đã trở thành trò tiêu khiển kém hấp dẫn hơn, đặc biệt là vì tôi đã giải được hầu hết chúng. Vì vậy, để tài năng của tôi không bị lãng phí khi tiếp tục học tập, tôi quyết định tạo một trò chơi web nhiều người chơi. Link các game khác:
  1. tiếp tục bài viết này
  2. 2048
Đối với tôi, Tic Tac Toe có vẻ là trò chơi đơn giản nhất nên tôi quyết định chia nhiệm vụ thành một số nhiệm vụ phụ:
  1. Ứng dụng Console để kiểm tra logic trò chơi
  2. Nhiều người chơi
  3. Đính kèm cơ sở dữ liệu người chơi vào ứng dụng bảng điều khiển
  4. Tạo thiết kế front-end, viết page template, giao diện game
  5. Để tất cả chúng cùng nhau
Có khả năng tôi sẽ bị mắng vì trình tự như vậy, và rất có thể tất cả các dự án nghiêm túc đều được xây dựng theo một trình tự hoàn toàn khác, tôi sẽ trả lời ngay, viết một bài về việc này “dành cho người mới bắt đầu” để mọi người (kể cả tôi) có thể học được điều này :) Chà. Hãy bắt đầu viết một ứng dụng bảng điều khiển! Tôi sẽ làm theo các bước tương tự như các thử thách lớn cấp 20. Trong trò chơi tic-tac-toe có gì?!
  1. cánh đồng
  2. hai người chơi thay phiên nhau, một người thực hiện một quả tạt, người thứ hai là số 0. nó đơn giản.
Chúng tôi biến trường thành trường 3x3 tiêu chuẩn. Làm thế nào một lĩnh vực như vậy có thể được lưu trữ? tùy chọn đầu tiên là mảng hai chiều. Mảng này nên chứa những phần tử nào? Câu trả lời là chúng ta cần suy nghĩ xem mình sẽ làm gì với những yếu tố này, đó là hiển thị và so sánh để tìm ra người chiến thắng. Nếu chúng ta chỉ hiển thị chúng trên màn hình thì sẽ hợp lý nếu giữ chúng dưới dạng một chuỗi, khi đó bản thân mảng và hiển thị nó trên màn hình theo vòng lặp sẽ trông giống như thế này:
String[][] strings = {{"O", "O", "_"},
                    {"_", "X", "O"},
                    {"X", "X", "X"},
for (String [] ss : strings){
    for (String s : ss) System.out.print(s + " ");
    System.out.println(); //для перевода строки
}
màn hình sẽ hiển thị:
O O _
_ X O
X X X
Nhưng ngoài việc hiển thị, chúng tôi còn có sự so sánh các giá trị và ở đây đã có sẵn các tùy chọn. Bạn có thể so sánh các chuỗi, bạn có thể tạo một lớp liệt kê đặc biệt ( enum), nhưng tôi muốn so sánh các số và chỉ thay thế chúng bằng “X” và “O” khi hiển thị trên màn hình. Ví dụ: đặt nó là 1 - "X", 2 - "O", 0 - "_". Vì vậy, làm cách nào để bạn kiểm tra một trường có khớp ba X hoặc O không?
Thuật toán đầu tiên là kiểm tra toàn bộ trường
int[][] canvas = {{00, 01, 02},
                 {10, 11, 12},
                 {20, 21, 22}}
Kết hợp chiến thắng:
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.
Kiểm tra bằng cách so sánh các con số, nhưng hóa ra bạn cần kiểm tra TOÀN BỘ trường, tất cả 8 kết hợp mọi lúc. Tất nhiên, điều này không nhiều, đây không phải là tìm kiếm các số Armstrong trong phạm vi từ 0 đến 1 tỷ, ở đây không có nhiều hơn một phép tính, nhưng bạn vẫn muốn thứ gì đó tối ưu hơn là kiểm tra toàn bộ trường. Ý tưởng thứ hai đến với tôi là chỉ kiểm tra ô đã được đánh dấu ở nước đi trước, để chúng tôi vẫn có thể xác định người chiến thắng, vì chúng tôi sẽ biết ai đã thực hiện nước đi này. Do đó, thay vì tất cả 8 tổ hợp, chúng ta chỉ nhận được 2, 3 hoặc 4 tổ hợp, tùy theo ô, xem hình: Trò chơi Java dành cho người mới bắt đầu - 2Bây giờ chúng ta cần tìm ra cách xác định tổ hợp nào cần được khởi chạy? Đây là lúc tôi nhận ra rằng việc sử dụng mảng hai chiều không thuận tiện lắm. Tôi quyết định xem xét các lựa chọn khác. Lúc đầu, tôi nảy ra ý tưởng rằng trường này có thể được giữ ở dạng số có chín chữ số, ví dụ: trường tương tự mà chúng tôi hiển thị trên màn hình có thể được viết như thế này: 220012111, tôi sẽ giải thích bằng ngón tay của mình nó là gì là... Mã giống nhau, 1 - “X”, 2 - “O”, 0 – " ", nghĩa là 220012111 = "OO__XOXXX", hoặc nếu sau mỗi chữ số thứ ba, bạn chèn dấu ngắt dòng và thêm dấu cách cho trong trẻo:
О О _
_ Х О
Х Х Х
Ở đây một lần nữa, thuận tiện cho việc lưu trữ, một thiết bị hiển thị đã được phát minh, nhưng lại bất tiện khi so sánh! Giải pháp đã được tìm ra khi tôi đánh số các ô từ 1-9, sau đó tôi nghĩ, vì trong lập trình, bộ đếm ngược bắt đầu từ 0 và đánh số như trong hình Trò chơi Java cho người mới bắt đầu - 3. Nếu bạn nhìn vào hình trên sẽ thấy rõ dung dịch có 2 tổ hợp có số sê-ri lẻ, 4 tổ hợp có số sê-ri 4, 3 tổ hợp có số còn lại. Vì vậy, tôi đi đến kết luận rằng bạn cần giữ sân chơi theo một dãy số đều đặn: lặp lại đơn giản giữa các số, khả năng so sánh theo thuật toán đã chọn, xuất đơn giản ra màn hình. Đối với chính thuật toán so sánh. Hãy đi theo thứ tự: trong tất cả các tùy chọn đều có kiểm tra hàng và cột, chúng tôi chỉ kiểm tra chúng. nếu tìm kiếm không có kết quả, chúng tôi kiểm tra số ô chẵn/lẻ, nếu nó là số lẻ thì chúng tôi quay lại trò chơi, không có ích gì khi kiểm tra thêm, nếu nó chẵn, chúng tôi kiểm tra xem ô này có nằm trên đường chéo trái, các số của đường chéo này khi chia cho 4 có số dư bằng 0. Nếu nằm, ta kiểm tra trùng khớp, nếu không trùng khớp thì kiểm tra số 4, nếu không thì quay lại trò chơi, nếu vâng, chúng tôi đi sâu hơn vào mã và trả về kết quả kiểm tra đường chéo cuối cùng. Có lẽ, đối với một người chưa chuẩn bị trước, điều này sẽ khó hiểu sau khi đọc bộ chữ cái ở trên, nhưng ai đó có thể nói rằng có rất nhiều chữ cái trong chính mã, điều này có thể đơn giản hơn, tôi sẽ vui lòng thảo luận về vấn đề này. Chúng tôi đã sắp xếp trường, bây giờ chúng tôi cần xử lý hai người dùng thay phiên nhau và mỗi người trong số họ có dấu hiệu riêng, X hoặc O. Ở giai đoạn đầu tiên, chúng tôi không có bất kỳ chức năng nhiều người dùng nào, vì vậy cách dễ nhất là sử dụng từng biểu tượng một. X luôn thực hiện bước đầu tiên, O luôn thực hiện bước thứ hai, sau đó X lại, v.v. Cần phải kiểm tra ( true/false ) và nếu đúng – thì người chơi hiện tại là X, nếu sai – thì O và khi bắt đầu mỗi nước đi flag=!flag Bằng cách nào đó vẫn phải nhận được tín hiệu từ người chơi về điều gì ô mà họ chọn. Ở đây chúng tôi sẽ cần BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); những người chơi khó quên của chúng tôi sẽ nhập số ô vào bảng điều khiển và nhấn Enter sẽ thực hiện một nước đi. Ô tương ứng với số đã nhập sẽ thay đổi giá trị của nó từ 0 thành 1 hoặc 2, tùy thuộc vào trạng thái hiện tại của hộp kiểm, điều này đã được thảo luận trong đoạn trên. Đây là lúc điều quan trọng là phải xác thực đầu vào để không ai có thể thay đổi X thành O khi ô đã được điền :) Người chơi có thể nhập gì vào bảng điều khiển?
  1. dòng trống
  2. các chữ cái, dấu chấm câu, dấu ngoặc... trong một từ, không phải số
  3. số không chính xác - âm hoặc nằm ngoài kích thước mảng, ô bị chiếm dụng.
Phương thức tiêu chuẩn để lấy một chữ số từ một chuỗi là phương thức tĩnh parsInt của lớp Integer. Integer.parseInt("2");Nó đưa ra một ngoại lệ NumberFormatExceptionnếu nó không thể lấy một chữ số từ một chuỗi nhất định. Chúng ta có thể cung cấp sự bảo vệ từ hai điểm đầu tiên bằng cách chặn ngoại lệ này. Đối với điểm thứ ba, tôi sẽ tạo một phương thức khác để kiểm tra giá trị đã nhập, nhưng cách chính xác nhất là chuyển yêu cầu chuỗi sang một phương thức riêng biệt trong đó việc xác thực sẽ được thực hiện và nó sẽ chỉ trả về một số. Tóm lại, chúng tôi đã tạo một trường, tạo một phương thức hiển thị nó, tạo một phương thức kiểm tra “người chơi này có thắng trong một giờ không?” và xác thực các số đã nhập. Còn rất ít việc phải làm, hãy kiểm tra kết quả hòa - một phương pháp riêng biệt chạy qua mảng và tìm kiếm số 0, đồng thời hiển thị kết quả trò chơi. Thế là xong, mã đã sẵn sàng, trò chơi hóa ra lại nhỏ, chỉ có một lớp, vì vậy những người sao chép khó tính có thể không hiểu mà sao chép mọi thứ vào dự án của họ và tự chạy, bản thân tôi cũng như vậy, nhưng bây giờ tôi cố gắng không làm điều đó và không giới thiệu nó cho bất kỳ ai :) Chúc mọi người học JAVA may mắn! ps những điểm còn lại - nhiều người chơi và cơ sở dữ liệu sẽ đến sau, tôi đã bắt đầu nghiên cứu tài liệu rồi :)
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;
    }
}
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION