Бот для игры в "Морской бой"

Я хочу сделать бота для игры в морской бой. И сделал вот такого бота:

 int x = new Random().nextInt(10);
                    int y = new Random().nextInt(10);
                    if(pole[x][y]==1){// 1 - корабль
                        pole[x][y]=2;// 2 - уже пристреленный корабль
                        ((ImageView)pole_image[x][y]).setImageResource(R.drawable.patron_in_ship);
                        boolean ships = true;
                        for (int[] vr: pole) {
                            for (int iq: vr) {
                                if (iq == 1) {
                                    ships = false;
                                    break;
                                }
                            }
                        }
                        if(ships) new AlertDialog.Builder(this).setTitle("Вы проиграли").setCancelable(false).setPositiveButton("OK", null).create().show();
                    } else if(pole[x][y]==0){ ((ImageView)pole_image[x][y]).setImageResource(R.drawable.patron_in_empty);}// 0 - пустое место

Но при игре он иногда то работает, то не работает
Подскажите пожалуйста, как сделать бота для игры в Морской бой


Ответы (1 шт):

Автор решения: Вася Воронцов

Боту как игроку должно быть известно, где находится "необитаемая зона" (поля, помеченные 2), поэтому их следует исключить из выбора. Кроме этого, необходимо помечать поля рядом с уничтоженным кораблём соответственно. Пришлось создать ArrayList с координатами кораблей:

import java.util.Random;
import java.util.ArrayList;

public class Main {
    //x - номер строки
    //y - номер столбца
    
    public static int steps = 0;
    public static boolean hasShips = true;
    public static ArrayList<int[]> occupatedInRow = new ArrayList<int[]>();
    public static int[] lastHurt = new int[]{-1, -1};
    public static int[] firstHurt = new int[]{-1, -1};
    public static boolean isDirectionTop = true;
    public static boolean isDirectionSetted = false;
    
    public static int[] calculateShot(int[][] pole) {
        Random rnd = new Random();
        int[] occupated = new int[0];
        
        int x = -1, y = -1;
        boolean isFirstNeeded = false;
        if (lastHurt[0] != -1) {
            if (isDirectionSetted) {
                if (isDirectionTop) {
                    if (lastHurt[0]-1 >= 0 && pole[lastHurt[0]-1][lastHurt[1]] == 1) {
                        x = lastHurt[0]-1;
                        y = lastHurt[1];
                    } else if (lastHurt[0]+1 < 10 && pole[lastHurt[0]+1][lastHurt[1]] == 1) {
                        x = lastHurt[0]+1;
                        y = lastHurt[1];
                    }
                } else {
                    if (lastHurt[1]-1 >= 0 && pole[lastHurt[0]][lastHurt[1]-1] == 1) {
                        x = lastHurt[0];
                        y = lastHurt[1]-1;
                    } else if (lastHurt[1]+1 < 10 && pole[lastHurt[0]][lastHurt[1]+1] == 1) {
                        x = lastHurt[0];
                        y = lastHurt[1]+1;
                    }
                }
            } else {
                if (lastHurt[0]-1 >= 0 && pole[lastHurt[0]-1][lastHurt[1]] == 1) {
                    x = lastHurt[0]-1;
                    y = lastHurt[1];
                } else if (lastHurt[0]+1 < 10 && pole[lastHurt[0]+1][lastHurt[1]] == 1) {
                    x = lastHurt[0]+1;
                    y = lastHurt[1];
                } else if (lastHurt[1]-1 >= 0 && pole[lastHurt[0]][lastHurt[1]-1] == 1) {
                    x = lastHurt[0];
                    y = lastHurt[1]-1;
                } else if (lastHurt[1]+1 < 10 && pole[lastHurt[0]][lastHurt[1]+1] == 1) {
                    x = lastHurt[0];
                    y = lastHurt[1]+1;
                }
            }
            if (x == -1) isFirstNeeded = true;
        } else isFirstNeeded = true;
        if (isFirstNeeded && firstHurt[0] != -1) {
            if (isDirectionSetted) {
                if (isDirectionTop) {
                    if (firstHurt[0]-1 >= 0 && pole[firstHurt[0]-1][firstHurt[1]] == 1) {
                        x = firstHurt[0]-1;
                        y = firstHurt[1];
                    } else if (firstHurt[0]+1 < 10 && pole[firstHurt[0]+1][firstHurt[1]] == 1) {
                        x = firstHurt[0]+1;
                        y = firstHurt[1];
                    }
                } else {
                    if (firstHurt[1]-1 >= 0 && pole[firstHurt[0]][firstHurt[1]-1] == 1) {
                        x = firstHurt[0];
                        y = firstHurt[1]-1;
                    } else if (firstHurt[1]+1 < 10 && pole[firstHurt[0]][firstHurt[1]+1] == 1) {
                        x = firstHurt[0];
                        y = firstHurt[1]+1;
                    }
                }
            } else {
                if (firstHurt[0]-1 >= 0 && pole[lastHurt[0]-1][lastHurt[1]] == 1) {
                    x = firstHurt[0]-1;
                    y = firstHurt[1];
                } else if (firstHurt[0]+1 < 10 && pole[firstHurt[0]+1][firstHurt[1]] == 1) {
                    x = firstHurt[0]+1;
                    y = firstHurt[1];
                } else if (firstHurt[1]-1 >= 0 && pole[firstHurt[0]][firstHurt[1]-1] == 1) {
                    x = firstHurt[0];
                    y = firstHurt[1]-1;
                } else if (firstHurt[1]+1 < 10 && pole[firstHurt[0]][firstHurt[1]+1] == 1) {
                    x = firstHurt[0];
                    y = firstHurt[1]+1;
                }
            }
        } else if (isFirstNeeded) {
            x = rnd.nextInt(10);
            while ((occupated = occupatedInRow.get(x)).length == 10) {
                x = rnd.nextInt(10);
            }
            y = getRandomWithExclusion(rnd, 0, 9, occupatedInRow.get(x));
        }
        occupatedInRow.set(x, push(occupated, y));
        return new int[] {x, y};
    }

    public static int getRandomWithExclusion(Random rnd, int start, int end, int[] exclude) {
        int random = start + rnd.nextInt(end - start + 1 - exclude.length);
        for (int ex : exclude) {
            if (random < ex) {
                break;
            }
            random++;
        }
        return random;
    }
    
    public static int[] push(int[] array, int num) {
        int[] newArray = new int[array.length + 1];
        for (int a = 0; a < array.length; a++) {
            newArray[a] = array[a];
        }
        newArray[array.length] = num;
        return newArray;
    }
    
    public static void shot(int[][] pole, ArrayList<int[]> ships, int x, int y) {
        pole[x][y] = 2;
        
        int[] cs = null;
        boolean isX = false, isY = false;
        for (int a = 0; a < ships.size(); a++) {
            int[] ccs = ships.get(a);
            
            if (ccs[0] <= x && ccs[2] >= x && ccs[1] <= y && ccs[3] >= y) {
                cs = ccs;
                for (int i = cs[0]; i <= cs[2]; i++) {
                    if (pole[i][y] == 1) {
                        isX = true;
                        break;
                    }
                }
                for (int j = cs[1]; j <= cs[3]; j++) {
                    if (pole[x][j] == 1) {
                        isY = true;
                        break;
                    }
                }
                break;
            }
        }
        
        if (cs == null) {
            System.out.println("Промах!");
            lastHurt = new int[]{-1, -1};
        } else if (isX || isY) {
            System.out.println("Попал!");
            if (lastHurt[0] != -1) {
                isDirectionSetted = true;
                isDirectionTop = (lastHurt[0] - x) != 0;
            } else {
                isDirectionSetted = false;
                firstHurt = new int[]{x, y};
            }
            lastHurt = new int[]{x, y};
        } else {
            for (int i = cs[0]-1; i <= cs[2]+1; i++) {
                for (int j = cs[1]-1; j <= cs[3]+1; j++) {
                    pole[i][j] = 2;
                }
            }
            System.out.println("Потопил!");
            lastHurt = new int[]{-1, -1};
            firstHurt = new int[]{-1, -1};
            isDirectionSetted = false;
            
            hasShips = false;
            for (int i = 0; i < 10; i++) {
                for (int j = 0; j < 10; j++) {
                    if (pole[i][j] == 1) {
                        hasShips = true;
                        break;
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
        //инициализация
        for (int a = 0; a < 10; a++) {
            occupatedInRow.add(new int[0]);
        }
        int[][] pole = new int[][] {
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 1, 0, 0, 1, 1, 1, 1, 0, 0},
            {0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        };
        
        //массив с координатами кораблей
        ArrayList<int[]> ships = new ArrayList<int[]>();
        ships.add(new int[]{1, 1, 5, 1});
        ships.add(new int[]{4, 4, 4, 7});
        
        //просмотр стрельбы бота
        while (hasShips) {
            //получение координат
            int[] coords = calculateShot(pole);

            //выстрел
            shot(pole, ships, coords[0], coords[1]);
        
            //вывод
            for (int i = 0; i < 10; i++) {
                for (int j = 0; j < 10; j++) {
                    System.out.print(pole[i][j] + " ");
                }
                if (i == coords[0]) System.out.print("x (" + coords[0] + ")");
                System.out.println("");
            }
            String spaces = "";
            for (int k = 0; k < coords[1]-1; k++) {
                spaces += "  ";
            }
            System.out.println(spaces + "  y");
            System.out.println(spaces + " (" + coords[1] + ")");
            steps++;
            try {
                Thread.sleep(100);
            } catch (Exception e) {}
        }
        System.out.println("\nХодов сделано: " + steps);
    }
}

За getRandomWithExclusion благодарите участника Howard.

P.S. "бот" стреляет наугад, если до этого никуда не попадал, иначе бьёт в окрестности ранения в вычисленном по второму попаданию направлению.

→ Ссылка