JavaRush /จาวาบล็อก /Random-TH /เกม Java สำหรับผู้เริ่มต้น
timurnav
ระดับ

เกม Java สำหรับผู้เริ่มต้น

เผยแพร่ในกลุ่ม
สวัสดีเพื่อน ๆ และเพื่อนร่วมงานในอนาคต! เกม Java สำหรับผู้เริ่มต้น - 1เมื่อเร็ว ๆ นี้ฉันได้ทำการทดสอบเพื่อเข้าร่วมในโครงการจริงและผ่านมันไป แต่มันก็เกิดขึ้นจนไม่สามารถมีส่วนร่วมใน RP ได้เนื่องจากสถานการณ์ส่วนตัว หลังจากปัญหาที่น่าสนใจเช่นการทดสอบ RP ปัญหาของหลักสูตรปกติก็กลายเป็นงานอดิเรกที่น่าดึงดูดน้อยลง โดยเฉพาะอย่างยิ่งเมื่อฉันได้แก้ไขปัญหาส่วนใหญ่ไปแล้ว ดังนั้น เพื่อไม่ให้พรสวรรค์ของฉันสูญเปล่าในการเรียนรู้ต่อ ฉันจึงตัดสินใจสร้างเกมบนเว็บที่มีผู้เล่นหลายคน ลิงค์เกมอื่นๆ:
  1. ความต่อเนื่องของบทความนี้
  2. 2048
Tic Tac Toe ดูเหมือนเป็นเกมที่ง่ายที่สุดสำหรับฉัน ดังนั้นฉันจึงตัดสินใจแบ่งงานออกเป็นงานย่อยหลายงาน:
  1. แอปพลิเคชันคอนโซลสำหรับทดสอบตรรกะของเกม
  2. ผู้เล่นหลายคน
  3. การแนบฐานข้อมูลผู้เล่นเข้ากับแอปพลิเคชันคอนโซล
  4. การสร้างการออกแบบส่วนหน้า การเขียนเทมเพลตหน้า อินเทอร์เฟซเกม
  5. วางมันทั้งหมดเข้าด้วยกัน
มีความเป็นไปได้ที่ฉันจะถูกดุสำหรับลำดับดังกล่าวและส่วนใหญ่แล้วโปรเจ็กต์ที่จริงจังทั้งหมดจะถูกสร้างขึ้นในลำดับที่แตกต่างไปจากเดิมอย่างสิ้นเชิง ฉันจะตอบทันทีเขียนโพสต์เกี่ยวกับ "สำหรับผู้เริ่มต้น" นี้เพื่อให้ทุกคน (รวมถึงฉันด้วย) สามารถเรียนรู้สิ่งนี้ได้ :) เอาละ มาเริ่มเขียนแอปพลิเคชันคอนโซลกันดีกว่า! ฉันจะทำตามขั้นตอนเดียวกับความท้าทายใหญ่ระดับ 20 ในเกมโอเอกซ์คืออะไร!
  1. สนาม
  2. ผู้เล่นสองคนที่ผลัดกัน คนหนึ่งวางกากบาท คนที่สองเป็นศูนย์ มันง่ายมาก
เราสร้างสนามให้เป็นสนามขนาด 3x3 มาตรฐาน ฟิลด์ดังกล่าวสามารถจัดเก็บได้อย่างไร? ตัวเลือกแรกคืออาร์เรย์สองมิติ อาร์เรย์นี้ควรมีองค์ประกอบใด คำตอบคือเราต้องคิดก่อนว่าเราจะทำอะไรกับองค์ประกอบเหล่านี้ นี่คือการแสดงและเปรียบเทียบเพื่อหาผู้ชนะ หากเราแสดงพวกมันบนหน้าจอเท่านั้น มันก็สมเหตุสมผลที่จะเก็บพวกมันไว้เป็นสตริง จากนั้นอาร์เรย์เองและการแสดงมันบนหน้าจอในลักษณะวนซ้ำจะมีลักษณะดังนี้:
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 - "_" แล้วคุณจะตรวจสอบสนามสำหรับการแข่งขัน Triple 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 ชุดทุกครั้ง แน่นอนว่ายังไม่มาก นี่ไม่ใช่การค้นหาตัวเลขของ Armstrong ในช่วงตั้งแต่ 0 ถึง 1 พันล้าน ไม่มีการคำนวณที่นี่เลย แต่คุณยังคงต้องการบางสิ่งที่เหมาะสมกว่าการตรวจสอบทั้งฟิลด์ แนวคิดที่สองที่เข้ามาหาฉันคือตรวจสอบเฉพาะช่องที่ถูกทำเครื่องหมายไว้ในการเคลื่อนไหวครั้งก่อน เพื่อให้เรายังคงสามารถระบุผู้ชนะได้ เพราะเราจะรู้ว่าใครเป็นผู้ทำการเคลื่อนไหวนี้ ดังนั้นแทนที่จะเป็นชุดค่าผสมทั้งหมด 8 ชุด เราจะได้ชุดค่าผสมเพียง 2, 3 หรือ 4 ชุดเท่านั้น ขึ้นอยู่กับเซลล์ ดูภาพ: เกม Java สำหรับผู้เริ่มต้น - 2ตอนนี้เราต้องหาวิธีกำหนดว่าจะต้องเปิดใช้ชุดค่าผสมใด นี่คือจุดที่ฉันรู้ว่าการใช้อาร์เรย์สองมิติไม่สะดวกนัก ฉันตัดสินใจพิจารณาตัวเลือกอื่น ตอนแรกผมเกิดไอเดียว่าช่องสามารถเก็บเป็นตัวเลข 9 หลักได้ เช่น ช่องเดียวกับที่เราแสดงบนหน้าจอก็เขียนได้ดังนี้ 220012111 ฉันจะอธิบายด้วยนิ้วว่ามันคืออะไร คือ... รหัสเหมือนกัน 1 - “X”, 2 - “O” , 0 – " " ซึ่งหมายถึง 220012111 = "OO__XOXXX" หรือถ้าหลังจากทุก ๆ หลักที่สามคุณแทรกตัวแบ่งบรรทัดและเพิ่มช่องว่างสำหรับ ความชัดเจน:
О О _
_ Х О
Х Х Х
ที่นี่อีกแล้ว สะดวกแก่การจัดเก็บ มีอุปกรณ์แสดงผล แต่เทียบไม่สะดวก! พบวิธีแก้ปัญหาเมื่อฉันกำหนดหมายเลขเซลล์ 1-9 ฉันคิดว่าเพราะในการเขียนโปรแกรมการนับถอยหลังเริ่มจาก 0 และกำหนดหมายเลขตามภาพ เกม Java สำหรับผู้เริ่มต้น - 3คุณไม่สังเกตเห็นลักษณะเฉพาะใด ๆ เลยเหรอ? หากคุณดูภาพด้านบนจะเห็นได้ชัดว่าโซลูชันที่มี 2 ชุดค่าผสมมีหมายเลขซีเรียลคี่ ชุดค่าผสม 4 ชุดมีหมายเลขซีเรียล 4 ชุดค่าผสม 3 ชุดมีส่วนที่เหลือ ดังนั้นฉันจึงได้ข้อสรุปว่าคุณต้องรักษาสนามแข่งขันให้อยู่ในอาร์เรย์ตัวเลขปกติ: การวนซ้ำอย่างง่ายระหว่างตัวเลข ความสามารถในการเปรียบเทียบตามอัลกอริทึมที่เลือก เอาต์พุตอย่างง่ายไปยังหน้าจอ สำหรับอัลกอริธึมการเปรียบเทียบนั้นเอง ตามลำดับ: ในตัวเลือกทั้งหมดจะมีการตรวจสอบแถวและคอลัมน์เราตรวจสอบเท่านั้น หากการค้นหาไม่เป็นผล เราจะตรวจสอบหมายเลขเซลล์เป็นคู่/คี่ หากเป็นคี่ เราก็กลับเข้าสู่เกม ไม่มีประเด็นให้ตรวจสอบเพิ่มเติม หากเป็นคู่ เราจะตรวจสอบว่าเซลล์นี้อยู่บน เส้นทแยงมุมซ้ายจำนวนเส้นทแยงมุมนี้เมื่อหารด้วย 4 แล้วจะเหลือ 0 หากเป็นเท็จเราจะตรวจสอบการจับคู่หากไม่พบการจับคู่เราจะตรวจสอบหมายเลข 4 หากไม่ใช่ให้กลับเข้าเกมหาก ใช่ เราดำเนินการโค้ดเพิ่มเติมและส่งคืนผลลัพธ์ของการตรวจสอบเส้นทแยงมุมสุดท้าย อาจเป็นเรื่องยากที่จะเข้าใจสำหรับคนที่ไม่ได้เตรียมตัวหลังจากอ่านชุดตัวอักษรด้านบน แต่บางคนอาจบอกว่ามีตัวอักษรจำนวนมากในโค้ดเองซึ่งอาจง่ายกว่านี้ฉันยินดีที่จะหารือเรื่องนี้ เราได้แยกส่วนออกแล้ว ตอนนี้เราต้องจัดการกับผู้ใช้สองคนที่ผลัดกันและแต่ละคนมีสัญลักษณ์ X หรือ O เป็นของตัวเอง ในระยะแรก เราไม่มีฟังก์ชันการใช้งานแบบหลายผู้ใช้ ดังนั้น วิธีที่ง่ายที่สุดคือการใช้ไอคอนทีละไอคอน X จะทำการเคลื่อนไหวครั้งแรกเสมอ O จะทำการเคลื่อนไหวครั้งที่สองเสมอ จากนั้น X อีกครั้ง และต่อๆ ไป มันขอให้ตรวจสอบ ( จริง/เท็จ ) และถ้าเป็นจริง – ดังนั้นผู้เล่นปัจจุบันคือ X ถ้าเป็นเท็จ – แล้ว O และที่จุดเริ่มต้นของแต่ละการย้าย flag=!flag มันยังคงได้รับสัญญาณจากผู้เล่นเกี่ยวกับที่ เซลล์ที่พวกเขาเลือก ที่นี่เราต้องการให้BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); ผู้เล่นที่น่าจดจำของเราป้อนหมายเลขเซลล์ลงในคอนโซลแล้วกด Enter จะเป็นการเคลื่อนไหว เซลล์ที่สอดคล้องกับหมายเลขที่ป้อนจะเปลี่ยนค่าจาก 0 เป็น 1 หรือ 2 ขึ้นอยู่กับสถานะปัจจุบันของช่องทำเครื่องหมายซึ่งได้กล่าวถึงในย่อหน้าข้างต้น นี่คือจุดสำคัญที่จะต้องตรวจสอบความถูกต้องของอินพุตเพื่อไม่ให้ใครเปลี่ยน X เป็น O ได้เมื่อเซลล์เต็มแล้ว :) ผู้เล่นสามารถเข้าสู่คอนโซลอะไรได้บ้าง
  1. บรรทัดว่าง
  2. ตัวอักษร เครื่องหมายวรรคตอน วงเล็บ...ในคำเดียว ไม่ใช่ตัวเลข
  3. ตัวเลขไม่ถูกต้อง - ลบหรืออยู่นอกขนาดอาร์เรย์ เซลล์ที่ถูกครอบครอง
วิธีการมาตรฐานในการรับตัวเลขจากสตริงคือวิธีคงที่ parseInt ของคลาส Integer Integer.parseInt("2");มันจะส่งข้อยกเว้นNumberFormatExceptionหากไม่สามารถรับตัวเลขจากสตริงที่กำหนด เราสามารถให้การป้องกันจากสองจุดแรกโดยการสกัดกั้นข้อยกเว้นนี้ สำหรับจุดที่สาม ฉันจะสร้างวิธีอื่นที่ตรวจสอบค่าที่ป้อน แต่จะถูกต้องที่สุดถ้าย้ายคำขอสตริงไปยังวิธีอื่นที่จะดำเนินการตรวจสอบความถูกต้อง และจะส่งกลับเฉพาะตัวเลขเท่านั้น โดยสรุป เราได้สร้างฟิลด์ สร้างวิธีการแสดง สร้างวิธีการตรวจสอบว่า "ผู้เล่นรายนี้ชนะภายในหนึ่งชั่วโมงหรือไม่" และตรวจสอบตัวเลขที่ป้อน เหลือเวลาอีกน้อยมากที่ต้องทำ ตรวจสอบการเสมอ - วิธีการแยกต่างหากที่รันผ่านอาเรย์และค้นหา 0 และแสดงผลเกม เพียงเท่านี้ รหัสก็พร้อมแล้ว เกมกลายเป็นเกมขนาดเล็ก มีเพียงคลาสเดียว ดังนั้นผู้คัดลอกพาสที่แข็งแกร่งสามารถคัดลอกทุกอย่างลงในโปรเจ็กต์ของพวกเขาและรันด้วยตัวเองโดยไม่เข้าใจ ฉันก็เป็นเช่นนั้น แต่ ตอนนี้ฉันพยายามไม่ทำอย่างนั้นและไม่ใช่กับใครก็ตามที่ฉันแนะนำ :) ขอให้ทุกคนโชคดีในการเรียนรู้ JAVA! ป.ล. ส่วนที่เหลือ - ผู้เล่นหลายคนและฐานข้อมูลจะมาในภายหลัง ฉันได้เริ่มศึกษาเนื้อหาแล้ว :)
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;
    }
}
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION