JavaRush /Java Blog /Random EN /Java game for beginners
timurnav
Level 21

Java game for beginners

Published in the Random EN group
Hello friends and future colleagues! Java game for beginners - 1Quite recently, I took a test to participate in a real project, passed it, but it just so happened that due to personal circumstances I was unable to take part in the RP itself. After such interesting problems as the RP test, the usual course problems became a less attractive pastime, especially since I had already solved most of them. Therefore, so that my talent would not be wasted to continue learning, I decided to create a multiplayer web game. Links to other games:
  1. continuation of this article
  2. 2048
Tic Tac Toe seemed like the simplest game to me, so I decided to break the task into a number of subtasks:
  1. Console application for testing game logic
  2. Multiplayer
  3. Attaching a player database to a console application
  4. Creating front-end design, writing page templates, game interface
  5. Putting it all together
There is a possibility that I will be scolded for such a sequence, and most likely all serious projects are built in a completely different sequence, I will answer right away, write a post about this “for beginners” so that everyone (including me) can learn this :) Well. Let's start writing a console application! I'll follow the same steps as the big level 20 challenges. What is in the game tic-tac-toe?!
  1. field
  2. two players who take turns, one puts a cross, the second a zero. it's simple.
We make the field a standard 3x3 field. How can such a field be stored? the first option is a two-dimensional array. What elements should this array contain? The answer is that we need to think about what we will do with these elements, this is displaying and comparing to find the winner. If we were only displaying them on the screen, then it would be logical to keep them as a string, then the array itself and displaying it on the screen in a loop would look something like this:
String[][] strings = {{"O", "O", "_"},
                    {"_", "X", "O"},
                    {"X", "X", "X"},
for (String [] ss : strings){
    for (String s : ss) System.out.print(s + " ");
    System.out.println(); //для перевода строки
}
the screen would display:
O O _
_ X O
X X X
But in addition to display, we also have a comparison of values, and here options are already possible. You can compare strings, you can create a special enumeration class ( enum), but I would prefer to compare numbers, and replace them with “X” and “O” only when displayed on the screen. Let it be, for example, 1 - "X", 2 - "O", 0 - "_". So, how do you check a field for a triple X or O match?
The very first algorithm is checking the entire field
int[][] canvas = {{00, 01, 02},
                 {10, 11, 12},
                 {20, 21, 22}}
Winning combinations:
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.
Checking by comparing numbers, but it turns out you need to check the ENTIRE field, all 8 combinations, every time. Of course, this is not much, this is not a search for Armstrong numbers in the range from 0 to 1 billion, there are little more than no calculations here, but you still want something more optimal than checking the entire field. The second idea that came to me was to check only the cell that was marked on the previous move, so we can still determine the winner, because we will know who made this move. Thus, instead of all 8 combinations, we get only 2, 3 or 4 combinations, depending on the cell, see the picture: Java game for beginners - 2Now we need to figure out how to determine which combination needs to be launched? This is where I realized that using a two-dimensional array is not very convenient. I decided to consider other options. At first I came up with the idea that the field can be kept in a nine-digit number, for example, the same field that we displayed on the screen can be written like this: 220012111, I’ll explain in my fingers what it is... The code is the same, 1 - “X”, 2 - “O” , 0 – " ", which means 220012111 = "OO__XOXXX", or if after every third digit you insert a line break and add spaces for clarity:
О О _
_ Х О
Х Х Х
here again, convenient for storage, a device for display was invented, but inconvenient for comparison! The solution was found when I numbered the cells 1-9, then I thought, because in programming the countdown starts from 0 and numbered it as in the picture. Java game for beginners - 3Didn’t you notice any peculiarities? if you look at the picture above, it will become clear that solutions with 2 combinations have an odd serial number, 4 combinations have serial number 4, 3 combinations have the rest. So I came to the conclusion that you need to keep the playing field in a regular array of numbers: simple iteration between numbers, the ability to compare according to the algorithm that was chosen, simple output to the screen. As for the comparison algorithm itself. Let's go in order: in all options there is a check of the row and column, we check only them. if the search does not result, we check the cell number for even/odd, if it is odd, then we return to the game, there is no point in checking further, if it is even, we check whether this cell lies on the left diagonal, the numbers of this diagonal when divided by 4 have a remainder of 0. If it lies, we check for matches, if no matches are found, then we check for the number 4, if not, return to the game, if yes, we go further through the code and return the result of checking the last diagonal. Probably, for an unprepared person, this is difficult to understand after reading the set of letters above, but someone may say that there are a lot of letters in the code itself, which can be simpler, I will be happy to discuss this. We’ve sorted out the field, now we need to deal with two users who take turns and each of them has their own sign, X or O. At the first stage, we don’t have any multi-user functionality, so the easiest way would be to use the icons one by one. X always makes the first move, O always makes the second, then X again, and so on. It begs to be checked ( true/false ), and if true – then the current player is X, if false – then O and at the beginning of each move flag=!flag It remains to somehow receive a signal from the players about which cell they choose. Here we will need our unforgettable BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); Players will enter the cell numbers into the console, and pressing Enter will make a move. The cell corresponding to the entered number will change its value from 0 to 1 or 2, depending on the current state of the checkbox, which was discussed in the paragraph above. This is where it is important to validate the input so that no one can change X to O when the cell is already filled :) What can the player enter into the console?
  1. empty line
  2. letters, punctuation marks, brackets... in one word, non-numbers
  3. incorrect numbers - negative or outside the array size, occupied cells.
The standard method for getting a digit from a string is the static method parseInt of the Integer class. Integer.parseInt("2");It throws an exception NumberFormatExceptionif it cannot get a digit from a given string. We can provide protection from the first two points by intercepting this exception. For the third point, I would create another method that checks the entered value, but it would be most correct to move the string request into a separate method in which validation will be performed, and it will return only a number. To summarize, we created a field, made a method that displays it, made a method that checks “did this player win by an hour?”, and validated the entered numbers. There is very little left to do, check for a draw - a separate method that runs through the array and looks for 0, and displays the game results. That's all, the code is ready, the game turned out to be small, only one class, so tough copy-pasters can, without understanding, just copy everything into their project and run it on their own, I was like that myself, but now I try not to do that and not to anyone I recommend it :) Good luck to everyone in learning JAVA! ps the rest of the points - multiplayer and database will come later, I have already started studying the material :)
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;
    }
}
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION