JavaRush /Java Blog /Random-KO /초보자를 위한 자바 게임
timurnav
레벨 21

초보자를 위한 자바 게임

Random-KO 그룹에 게시되었습니다
안녕하세요 친구이자 미래의 동료입니다! 초보자를 위한 자바 게임 - 1얼마 전 실제 프로젝트에 참여하기 위해 시험을 쳐서 합격했는데, 부득이하게 개인 사정으로 인해 RP 자체에 참여하지 못하게 되었습니다. RP 테스트와 같은 흥미로운 문제 이후에는 일반적인 코스 문제가 덜 매력적인 취미가 되었습니다. 특히 이미 대부분의 문제를 해결했기 때문입니다. 그래서 계속해서 배우는 데 내 재능이 낭비되지 않도록 멀티플레이어 웹 게임을 만들기로 결정했습니다. 다른 게임 링크:
  1. 이 기사의 계속
  2. 2048년
Tic Tac Toe는 나에게 가장 간단한 게임처럼 보였기 때문에 작업을 여러 하위 작업으로 나누기로 결정했습니다.
  1. 게임 로직 테스트를 위한 콘솔 애플리케이션
  2. 멀티플레이어
  3. 플레이어 데이터베이스를 콘솔 애플리케이션에 연결
  4. 프론트엔드 디자인 제작, 페이지 템플릿 작성, 게임 인터페이스
  5. 함께 모아서
그러한 순서에 대해 꾸짖을 가능성이 있으며 모든 진지한 프로젝트는 완전히 다른 순서로 구축 될 가능성이 높습니다. 즉시 답변하고 "초보자 용"에 대한 게시물을 작성하여 모든 사람 (나 포함)이 배울 수 있습니다 :) 이제 콘솔 애플리케이션 작성을 시작해 보겠습니다! 저는 큰 레벨 20 챌린지와 동일한 단계를 따르겠습니다. 틱택토 게임에는 무엇이 들어있나요?!
  1. 필드
  2. 두 명의 플레이어가 교대로 플레이하고 한 명은 크로스를, 두 번째는 0을 넣습니다. 간단 해.
우리는 필드를 표준 3x3 필드로 만듭니다. 그러한 필드를 어떻게 저장할 수 있습니까? 첫 번째 옵션은 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억 사이의 암스트롱 숫자를 검색하는 것이 아니며 여기에는 계산이 거의 없지만 전체 필드를 확인하는 것보다 더 최적의 것을 원합니다. 나에게 떠오른 두 번째 아이디어는 이전 이동에 표시된 셀만 확인하여 누가 이 이동을 했는지 알 수 있기 때문에 승자를 결정할 수 있다는 것이었습니다. 따라서 8개의 조합 전체 대신 셀에 따라 2, 3 또는 4개의 조합만 얻습니다. 그림을 참조하십시오. 초보자를 위한 자바 게임 - 2이제 어떤 조합을 시작해야 하는지 결정하는 방법을 알아내야 합니까? 여기서 2차원 배열을 사용하는 것이 그다지 편리하지 않다는 것을 깨달았습니다. 나는 다른 옵션을 고려하기로 결정했습니다. 처음에는 필드를 9자리 숫자로 유지할 수 있다는 생각이 떠올랐습니다. 예를 들어 화면에 표시된 것과 동일한 필드를 다음과 같이 쓸 수 있습니다. 220012111, 그것이 무엇인지 손가락으로 설명하겠습니다. ... 코드는 동일합니다. 1 - “X”, 2 - “O”, 0 – " ", 이는 220012111 = "OO__XOXXX"를 의미합니다. 또는 세 번째 숫자마다 줄 바꿈을 삽입하고 공백을 추가하는 경우 명쾌함:
О О _
_ Х О
Х Х Х
여기서도 보관이 편리한 디스플레이 장치가 발명되었지만 비교가 불편하네요! 1~9번 셀에 번호를 매겼을 때 해결책을 찾았는데, 프로그래밍을 할 때 카운트다운이 0부터 시작해서 그림과 같이 번호가 매겨지기 때문에 그런 생각이 들었습니다. 초보자를 위한 자바 게임 - 3어떤 특이한 점을 발견하지 못하셨나요? 위 그림을 보면 2개 조합의 솔루션에는 홀수 일련 번호가 있고, 4개 조합에는 일련 번호 4가 있고, 3개 조합에는 나머지가 있다는 것이 분명해집니다. 그래서 저는 규칙적인 숫자 배열로 경쟁의 장을 유지해야 한다는 결론에 도달했습니다. 즉, 숫자 간의 간단한 반복, 선택한 알고리즘에 따른 비교 기능, 화면에 대한 간단한 출력이 필요합니다. 비교 알고리즘 자체에 관해서. 순서대로 봅시다. 모든 옵션에는 행과 열이 확인되어 있으며, 우리는 그것들만 확인합니다. 검색 결과가 없으면 셀 번호를 짝수/홀수로 확인하고, 홀수이면 게임으로 돌아가서 더 이상 확인할 필요가 없으며, 짝수이면 이 셀이 다음 위치에 있는지 확인합니다. 왼쪽 대각선, 4로 나눈 이 대각선의 숫자는 0의 나머지를 갖습니다. 그것이 거짓말이라면 일치하는 항목을 확인하고, 일치하는 항목이 없으면 숫자 4를 확인하고, 그렇지 않으면 게임으로 돌아갑니다. 예, 코드를 더 자세히 살펴보고 마지막 대각선을 확인한 결과를 반환합니다. 아마도 준비되지 않은 사람에게는 위의 문자 집합을 읽은 후 이해하기 어려울 수 있지만 누군가는 코드 자체에 많은 문자가 있다고 말할 수 있으므로 더 간단할 수 있으므로 이에 대해 기꺼이 논의하겠습니다. 필드를 정리했으므로 이제 교대로 돌아가는 두 명의 사용자를 처리해야 하며 각 사용자는 X 또는 O라는 고유한 기호를 가지고 있습니다. 첫 번째 단계에서는 다중 사용자 기능이 없으므로 가장 쉬운 방법은 아이콘을 하나씩 사용하는 것입니다. X는 항상 첫 번째 이동을 하고 O는 항상 두 번째 이동을 한 다음 X가 다시 이동하는 식으로 진행됩니다. 확인을 요청하고( true/false ), true 이면 현재 플레이어가 X이고 false 이면 O이며 각 이동 시작 시 플래그=!flag입니다. 플레이어로부터 어떤 신호를 받는지 어떻게든 수신해야 합니다. 셀을 선택합니다. 여기서는 잊을 수 없는 플레이어가 필요합니다. BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); 플레이어는 콘솔에 셀 번호를 입력하고 Enter를 누르면 이동합니다. 입력한 숫자에 해당하는 셀은 위 단락에서 설명한 체크박스의 현재 상태에 따라 해당 값을 0에서 1 또는 2로 변경합니다. 셀이 이미 채워졌을 때 누구도 X를 O로 변경할 수 없도록 입력을 검증하는 것이 중요한 곳입니다. 플레이어가 콘솔에 무엇을 입력할 수 있나요?
  1. 빈 줄
  2. 문자, 구두점, 괄호... 한 단어로, 숫자가 아닌 것
  3. 잘못된 숫자 - 음수이거나 배열 크기를 벗어나며 셀을 차지합니다.
문자열에서 숫자를 가져오는 표준 메소드는 Integer 클래스의 정적 메소드인parseInt입니다.이 메소드 Integer.parseInt("2");NumberFormatException주어진 문자열에서 숫자를 가져올 수 없으면 예외를 발생시킵니다.우리는 이 예외를 가로채서 처음 두 지점으로부터 보호를 제공할 수 있습니다. 세 번째로는 입력된 값을 확인하는 또 다른 메서드를 만들겠지만, 문자열 요청을 유효성 검사가 수행되고 숫자만 반환하는 별도의 메서드로 옮기는 것이 가장 정확할 것입니다. 정리하자면, 필드를 생성하고, 이를 표시하는 메소드를 만들고, “이 플레이어가 한 시간 차이로 승리했나요?”를 확인하는 메소드를 만들고, 입력된 숫자를 검증했습니다. 할 일이 거의 남지 않았습니다. 무승부를 확인하세요. 이는 배열을 통해 실행되고 0을 찾고 게임 결과를 표시하는 별도의 메서드입니다. 그게 다야, 코드가 준비되었고 게임이 작고 클래스가 하나 뿐인 것으로 판명되었으므로 어려운 복사 붙여 넣기 사람들은 이해하지 못한 채 모든 것을 프로젝트에 복사하고 스스로 실행할 수 있습니다. 저도 그랬습니다. 이제는 그렇게 하지 않으려고 노력하고 있으며 누구에게도 추천하지 않습니다. :) 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;
    }
}
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION