Как расставить корабли в игре "Морской бой"
У меня есть массив с массивами, в которых хранятся числа:
int[][] pole = new int[][]
{
{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},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0}
};
И код который добавляет корабли в этот массив (поле):
//set 1x4 ship
int j = new Random().nextInt(6)+1;
if(new Random().nextBoolean())
for (int i = 0; i < 4; i++) {
pole[j][i]=1;
pole[j-1][i]=2;
pole[j+1][i]=2;
if(i==3){
pole[j-1][i+1]=2;
pole[j+1][i+1]=2;
pole[j][i+1]=2;
}
}
else
for (int i = 0; i < 4; i++) {
pole[i][j]=1;
if(i!=0&&j!=6){
pole[i-1][j+1]=2;
pole[i+1][j+1]=2;
pole[i][j+1]=2;
}
if(i!=0){
pole[i-1][j-1]=2;
pole[i+1][j-1]=2;
pole[i][j-1]=2;
pole[i+1][j]=2;
}
}
while(true){
if(new Random().nextBoolean())
if(
pole[j][0]!=1&&pole[j][0]!=2&&
pole[j][1]!=1&&pole[j][1]!=2&&
pole[j][2]!=1&&pole[j][2]!=2
){ for (int i = 0; i < 3; i++) {
pole[j][i] = 1;
pole[j - 1][i] = 2;
pole[j + 1][i] = 2;
if (i == 2) {
pole[j - 1][i + 1] = 2;
pole[j + 1][i + 1] = 2;
pole[j][i + 1] = 2;
}
}
break;
}
else
if(
pole[0][j]!=2&&pole[0][j]!=1&&
pole[1][j]!=2&&pole[1][j]!=1&&
pole[2][j]!=2&&pole[2][j]!=1
){
for (int i = 0; i < 3; i++) {
pole[i][j]=1;
if(i!=0&&j!=6){
pole[i-1][j+1]=2;
pole[i+1][j+1]=2;
pole[i][j+1]=2;
}
if(i!=0){
pole[i-1][j-1]=2;
pole[i+1][j-1]=2;
pole[i][j-1]=2;
pole[i+1][j]=2;
}
}
break;}
}
Но этот код при выполнение начинает зависать. Я пытался пол часа довести его до нормального состояния и у меня все равно не получилось сделать так, чтобы он не зависал.
Подскажите пожалуйста, может кто-нибудь делал морской бой под Android, как вы делали система автоустановки кораблей?
Ответы (2 шт):
Автор решения: Андрей Городецкий
→ Ссылка
Когда-то давно писал морской бой на C#, вот по-быстрому перевел на java, код рабочий, но тестов не было, возможно оптимизации нужны. Алгоритм нашел где-то в интернете.
import java.util.Random;
public class Battleship {
public static void main(String[] args) {
Battleship battleship = new Battleship();
int[][] botField = new int[10][10];
battleship.ships(botField);
for (int i = 0; i < 10; i++) {
for (int k = 0; k < 10; k++) {
System.out.print(botField[i][k]);
}
System.out.println();
}
}
public boolean freedom(int x, int y, int[][] Pole) {
int dx, dy;
if ((x >= 0) & (x < 10) & (y >= 0) & (y < 10) && ((Pole[x][y] == 0) || (Pole[x][y] == 2))) {
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
dx = x + i;
dy = y + j;
if ((dx >= 0) & (dx < 10) & (dy >= 0) & (dy < 10) && (Pole[dx][dy] == 1)) {
return false;
}
}
}
return true;
} else {
return false;
}
}
public void ships(int[][] Pole) {
int x, y, kx, ky;
boolean B;
Random random = new Random();
for (int N = 3; N >= 0; N--) {
for (int M = 0; M <= 3 - N; M++) {
do {
x = random.nextInt(10);
y = random.nextInt(10);
kx = random.nextInt(2);
if (kx == 0) {
ky = 1;
} else {
ky = 0;
}
B = true;
for (int j = 0; j <= N; j++) {
if (!(freedom(x + kx * j, y + ky * j, Pole))) {
B = false;
break;
}
}
if (B) {
for (int k = 0; k <= N; k++) {
Pole[x + kx * k][y + ky * k] = 1;
}
}
}
while (!(B));
}
}
}
}
Автор решения: Вася Воронцов
→ Ссылка
Случайное заполнение поля игры "Морской бой" с вертикальными и горизонтальными кораблями:
import java.util.Random;
import java.util.ArrayList;
public class Main {
//пользовательские настройки
//ширина и высота
static int width = 8, height = 5;
//количество кораблей каждого вида
//1, 0, 0, 3 - 1 четырёхпалубник и 3 однопалубника
static int[] ships = new int[] {
1, 0, 0, 0, 0, 2, 3
};
//"системные" переменные
static int size = width * height;
static int[] field = new int[size];
static int[] shipsBuffer = ships.clone();
static boolean isOK = true;
//выделенный квадрат не должен содержать кораблей
public static boolean isValid(int position) {
boolean hasLeft = false, hasRight = false;
boolean totalExist = field[position] == 0;
int i = (int) (position / width);
if (totalExist && position+1 < (i+1)*width) {
hasRight = true;
totalExist = totalExist && (field[position+1] == 0);
}
if (totalExist && position-1 > i*width) {
hasLeft = true;
totalExist = totalExist && (field[position-1] == 0);
}
if (totalExist && position+width < size) {
totalExist = totalExist && (field[position+width] == 0);
if (totalExist && hasRight) {
totalExist = totalExist && (field[position+width+1] == 0);
}
if (totalExist && hasLeft) {
totalExist = totalExist && (field[position+width-1] == 0);
}
}
if (totalExist && position-width > 0) {
totalExist = totalExist && (field[position-width] == 0);
if (totalExist && hasRight) {
totalExist = totalExist && (field[position-width+1] == 0);
}
if (totalExist && hasLeft) {
totalExist = totalExist && (field[position-width-1] == 0);
}
}
return totalExist;
}
public static void main(String args[]) {
Random rnd = new Random();
int c = 0;
while (true) {
boolean isFinished = true;
int index = -1;
//списки доступных для этого корабля позиций
ArrayList<int[]> rows = new ArrayList<int[]>(height);
ArrayList<int[]> columns = new ArrayList<int[]>(width);
int length = -1;
//количество палуб корабля
for (int s = 0; s < shipsBuffer.length; s++) {
if (shipsBuffer[s] > 0) {
length = ships.length - s;
shipsBuffer[s]--;
isFinished = false;
break;
}
}
if (length > width && length > height) {
isOK = false;
System.out.print("Слишком большой корабль!\n");
break;
}
if (isFinished) {
System.out.print("Завершено!\n");
break;
}
for (int i = 0; i < height; i++) {
int count = 0;
for (int j = 0; j < width; j++) {
if (isValid(i*width+j)) {
if (count == 0) index = i*width+j;
count++;
} else {
if (count >= length) {
rows.add(new int[]{index, count-length});
}
count = 0;
}
}
if (count >= length) {
rows.add(new int[]{index, count-length});
}
}
for (int j = 0; j < width; j++) {
int count = 0;
for (int i = 0; i < height; i++) {
if (isValid(i*width+j)) {
if (count == 0) index = i*width+j;
count++;
} else {
if (count >= length) {
columns.add(new int[]{index, count-length});
}
count = 0;
}
}
if (count >= length) {
columns.add(new int[]{index, count-length});
}
}
boolean isVertical = true;
boolean hasPlace = rows.size() > 0 || columns.size() > 0;
if (rows.size() > 0) isVertical = false;
if (columns.size() > 0 && !isVertical) isVertical = rnd.nextBoolean();
if (hasPlace && isVertical) {//вертикальный корабль
//выбираем случайную доступную позицию
int[] choosedPosition = columns.get(rnd.nextInt(columns.size()));
//начальный индекс
int startIndex = choosedPosition[0];
if (choosedPosition[1] > 0) {
//доступный в ряду диапазон позиций
startIndex += rnd.nextInt(choosedPosition[1]) * width;
}
//заполняем массив
for (int k = 0; k < length; k++) {
field[startIndex + k*width] = 1;
}
} else if (hasPlace) {//горизонтальный корабль
//выбираем случайную доступную позицию
int[] choosedPosition = rows.get(rnd.nextInt(rows.size()));
//начальный индекс
int startIndex = choosedPosition[0];
if (choosedPosition[1] > 0) {
//доступный в ряду диапазон позиций
startIndex += rnd.nextInt(choosedPosition[1]);
}
//заполняем массив
for (int k = 0; k < length; k++) {
field[startIndex + k] = 1;
}
} else {
System.out.println("Не все корабли расставлены...");
System.out.println("Попробуйте ещё раз!");
isOK = false;
break;
}
}
//вывод массива
if (isOK) for (int l = 0; l < size; l++) {
if (l % width == 0) System.out.print("\n");
System.out.print(String.valueOf(field[l]) + " ");
}
}
}
Примеры вывода:
Завершено!
1 0 0 0 1 0 0 0
0 0 0 0 1 0 1 0
1 1 1 0 0 0 1 0
0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 1
или
Не все корабли расставлены...
Попробуйте ещё раз!