Морской бой

Lictor
Offline
Зарегистрирован: 01.10.2015

Не то что бы я опять обделался, но близко. Код более менее работает, но есть 1 нюанс. По которому  и прошу помощи: не знаю как дать понять Ардуине, что если корабль вертикальный, то и стрелять нужно вертикально (и с горизонтальными те же проблемы). Сейчас ардуина просто обстреливает окружающие клетки (верх, низ, право, лево) с учетом ранее произведенных попаданий/промахов (т.е. по два раза в одно и то же место не стреляет и не отстает, пока не добьет корабль игрока). По сути проблема в строках 271-239. Но играть уже кажется можно... Хреново, но можно. 

 

int battlefield_computer[10][10];  // Поле компьютера
int battlefield_player[10][10];  // Поле игрока
byte order_of_progress = 1;  // Флаг очередности хода, 1 - игрок, 0 - компьютер
int total_tonnage;  // Общее кол-во клеток-кораблей

void ship_arrangement();  // Функция расстановки кораблей, передаем размер и кол-во
void player_move();  // Функция хода игрока
void arduino_move();  // Функция хода компьютера

void setup() {

  Serial.begin(115200); // Открываем последовательное соединение
  randomSeed(analogRead(0));  // Запускаем функцию рандом случайным образом

  for (int i = 0; i < 10; i++) { // заполним поле нулями
    for (int j = 0; j < 10; j++) {
      battlefield_computer[i][j] = 0;
      battlefield_player[i][j] = 0;
    }
  }

  //////////////////// Расставим корабли
  ship_arrangement(4, 1); // Передаем размер корабля и кол-во
  ship_arrangement(3, 2); // Передаем размер корабля и кол-во
  ship_arrangement(2, 3); // Передаем размер корабля и кол-во
  ship_arrangement(1, 4); // Передаем размер корабля и кол-во

  for (int i = 0; i < 10; i++) { // Заменим 2 в полях вокруг корабля на 0
    for (int j = 0; j < 10; j++) {
      if (battlefield_computer[j][i] == 2) battlefield_computer[j][i] = 0;
    }
  }

  //////////////////// Закончили расстановку

  for (int i = 9; i >= 0; i--) { // Посмотрим, что получилось
    for (int j = 0; j < 10; j++) {
      //Serial.print(" ");
      Serial.print(battlefield_computer[i][j]);
    }
    Serial.println();
  }
  Serial.println();
  Serial.print("Общий тоннаж ");
  Serial.println(total_tonnage);

} // Конец void setup()

void loop() {
  if (order_of_progress == 1) {
    Serial.println("Ход игрока");
    player_move();
  }
  else arduino_move();
} // Конец void loop()

void ship_arrangement(int ship_size, int quantity) {  // Функция расстановки кораблей

  total_tonnage = total_tonnage + ship_size * quantity; // Кол-во клеток занятых кораблями

  for (int t = 0; t < quantity; t++) {  // Кол-во повторов равно кол-ву кораблей
label:
    int x = random(0, 10); // Случайные координаты корабля
    int y = random(0, 10);

    uint8_t Direction = random(0, 2); // Случайное направление корабля

    if (Direction == 1) { // Расположим корабль по оси Х (j)
      for (int j = 0; j < ship_size ; j++) {  // Проверяем свободны ли поля (т.е. равно ли оно 0)
        if (battlefield_computer[y][x + j] == 0 && x + j < 10) { // Если условие не выполняется, то переносимся на начало
        }
        else {
          goto label;
        }
      }

      for (int i = 0; i < ship_size ; i++) battlefield_computer[y][x + i] = 1; // Если проверка прошла успешно, рисуем корабль
      // А когда нарисовали корабль, заполним область вокруг
      for (int i = 0; i < ship_size ; i++) {
        if (y + 1 < 10)  battlefield_computer[y + 1][x + i] = 2;
        if (y - 1 >= 0)  battlefield_computer[y - 1][x + i] = 2;
      }

      if (x - 1 >= 0) {
        battlefield_computer[y][x - 1] = 2;
        if (y - 1 >= 0)  battlefield_computer[y - 1][x - 1] = 2;
        if (y + 1 < 10) battlefield_computer[y + 1][x - 1] = 2;
      }

      if (x + ship_size < 10) {
        battlefield_computer[y][x + ship_size] = 2;
        if (y - 1 >= 0) battlefield_computer[y - 1][x + ship_size] = 2;
        if (y + 1 < 10) battlefield_computer[y + 1][x + ship_size] = 2;
      }
      // Закончили заполнять область вокруг
    } // Конец расположения корабля по оси Х (j)
    else //Если корабль не расположен по оси Х
    { // Расположим корабль по оси Y (i)
      for (int i = 0; i < ship_size ; i++) {  // Проверяем свободны ли поля (т.е. равно ли оно 0)
        if (battlefield_computer[y + i][x] == 0 && y + i < 10) { // Если условие не выполняется, то переносимся на начало
        }
        else {
          goto label;
        }
      }

      for (int i = 0; i < ship_size ; i++) battlefield_computer[y + i][x] = 1; // Если проверка прошла успешно, рисуем корабль

      // А когда нарисовали корабль, заполним область вокруг
      for (int i = 0; i < ship_size ; i++) {
        if (x + 1 < 10)  battlefield_computer[y + i][x + 1] = 2;
        if (x - 1 >= 0)  battlefield_computer[y + i][x - 1] = 2;
      }

      if (y - 1 >= 0) {
        battlefield_computer[y - 1][x] = 2;
        if (x - 1 >= 0)  battlefield_computer[y - 1][x - 1] = 2;
        if (x + 1 < 10)  battlefield_computer[y - 1][x + 1] = 2;
      }

      if (y + ship_size < 10) {
        battlefield_computer[y + ship_size][x] = 2;
        if (x - 1 >= 0)  battlefield_computer[y + ship_size][x - 1] = 2;
        if (x + 1 < 10)  battlefield_computer[y + ship_size][x + 1] = 2;
      }
      // Закончили заполнять область вокруг
    }// Конец расположения корабля по оси Y (i)
  }
}

void player_move() {

  int Xp, Yp; // Координаты хода игрока

  while (1) { // Ждем координату по Х
    if (Serial.available() > 0) {
      Xp = Serial.parseInt();
      if (Xp < 0) Xp = 0;
      if (Xp > 9) Xp = 9;
      break;
    }
  }

  while (1) { // Ждем координату по Y
    if (Serial.available() > 0) {
      Yp = Serial.parseInt();
      if (Yp < 0) Yp = 0;
      if (Yp > 9) Yp = 9;
      Serial.print("Ход сделан ");
      Serial.print(Xp);
      Serial.print(" ");
      Serial.print(Yp);
      Serial.println();
      break;
    }
  }

  if (battlefield_computer[Yp][Xp] == 0) {
    Serial.println("Промах, ход переходит компьютеру ");
    order_of_progress = !order_of_progress;
  }


  int kill; // Вспомогательный счетчик
  kill = 0;

  if (battlefield_computer[Yp][Xp] == 1 || battlefield_computer[Yp][Xp] == 2) { // Если есть попадание или стреляем второй раз в раненый корабль
    battlefield_computer[Yp][Xp] = 2;  // Заменяем 1 на 2, что бы показать что корабль ранен

    for (int i = 1; i < 10; i++) { // Пройдемся по полям в поисках 0 или 1 по оси Х++
      if (Xp + i < 10) {
        if (battlefield_computer[Yp][Xp + i] == 1) {
          goto label;
          //  Serial.println("Ранен");
        }
        if (battlefield_computer[Yp][Xp + i] == 0) {
          kill++;
          break;
        }
      }
      else {  // Конец поля, корабль потоплен
        kill++;
        break;
      }
    } // Закончили хождения по оси Х++

    for (int i = 1; i < 10; i++) { // Пройдемся по полям в поисках 0 или 1 по оси Х--
      if (Xp - i >= 0) {
        if (battlefield_computer[Yp][Xp - i] == 1) {
          goto label;
          // Serial.println("Ранен");
        }
        if (battlefield_computer[Yp][Xp - i] == 0) {
          kill++;
          break;
        }
      }
      else {  // Конец поля, корабль потоплен
        kill++;
        break;
      }
    } // Закончили хождения по оси Х--

    for (int i = 1; i < 10; i++) { // Пройдемся по полям в поисках 0 или 1 по оси Y++
      if (Yp + i < 10) {
        if (battlefield_computer[Yp + i][Xp] == 1) {
          goto label;
          // Serial.println("Ранен");
        }
        if (battlefield_computer[Yp + i][Xp] == 0) {
          kill++;
          break;
        }
      }
      else {  // Конец поля, корабль потоплен
        kill++;
        break;
      }
    } // Закончили хождения по оси Y++

    for (int i = 1; i < 10; i++) { // Пройдемся по полям в поисках 0 или 1 по оси Y--
      if (Yp - i >= 0) {
        if (battlefield_computer[Yp - i][Xp] == 1) {
          goto label;
          // Serial.println("Ранен");
        }
        if (battlefield_computer[Yp - i][Xp] == 0) {
          kill++;
          break;
        }
      }
      else {  // Конец поля, корабль потоплен
        kill++;
        break;
      }
    } // Закончили хождения по оси Y--

    if (1 > 2) {
label:
      Serial.println("Ранен");
    }

    // Serial.println(kill);
    if (kill == 4) Serial.println("Убил");  // Если вокруг одни нули (через 2 перескакиваем и ищем 0 или 1)
  } // Закончили проверку потоплен ли корабль

  int w;  // Проверим, а не победили ли мы за последний ход
  w = 0;
  for (int i = 0; i < 10; i++) { // скопируем поле компьютера во вспомогательное поле
    for (int j = 0; j < 10; j++) {
      if (battlefield_computer[i][j] == 1) w++;
    }
  }
  if (w == 0) {
    Serial.println("Победа");
    while (1);
  }

}  // Конец функции стрельбы игрока

void arduino_move() { // Ход компьютера

  //battlefield_player[10][10];  // Поле игрока
  //order_of_progress
  //total_tonnage;  // Общее кол-во клеток-кораблей

  int player_response = 0;  // Переменная ответа игрока (3 - промах, 2 - убил, 1 - ранил)
  int Xa = 99, Ya = 99; // Координаты хода компьютера
  // int flag = 0; // Флаг, 1 - было попадание до начала хода, 0 - не было попаданий

  // Проверяем есть ли прежние попадания (1)
replay2:
  for (int k = 0; k < 10; k++) {
    for (int m = 0; m < 10; m++) {
      if (battlefield_player[k][m] == 1) {  // нашли старое попадание


for (int i = 0; i < 10; i++) {
        if (k + i < 10 && battlefield_player[k + i][m] == 3) {
          goto z;
        }
        else {
          if (k + i < 10 && battlefield_player[k + i][m] == 0) {
            Xa = m;
            Ya = k + i;
            break;
          }
        }
z:
        if (k - i >= 0 && battlefield_player[k - i][m] == 3) {
          goto h;
        }
        else {
          if (k - i >= 0 && battlefield_player[k - i][m] == 0) {
            Xa = m;
            Ya = k - i;
            break;
          }
h:
          if (m + i < 10 && battlefield_player[k][m + i] == 3) {
            goto p;
          }
          else {
            if (m + i < 10 && battlefield_player[k][m + i] == 0) {
              Xa = m + i;
              Ya = k;
              break;
            }
          }
p:
          if (m - i >= 0 && battlefield_player[k][m - i] == 3) {
            break;
          }
          else {
            if (m - i >= 0 && battlefield_player[k][m - i] == 0) {
              Xa = m - i;
              Ya = k;
              break;
            }
          }

        }
        
        }
      }
    }


  } // Конец цикла,  в котором мы стреляли по раненому кораблю

if (Xa != 99 && Ya != 99) {
    Serial.print("Ход компьютера рядом со старым попаданием ");
    Serial.print("Xa= ");
    Serial.print(Xa);
    Serial.print(" Ya= ");
    Serial.println(Ya);
}



  if (Xa == 99 && Ya == 99) { // Не было попадания, генерируем случайный ход
newXY:
    Xa = random(0, 10); // Случайные координаты корабля
    Ya = random(0, 10);
    if (battlefield_player[Ya][Xa] == 2 || battlefield_player[Ya][Xa] == 3) goto newXY;
    Serial.print("Ход компьютера ");
    Serial.print("Xa= ");
    Serial.print(Xa);
    Serial.print(" Ya= ");
    Serial.println(Ya);
  }

  while (1) { // Ждем ответ игрока на запрошенные координаты
    if (Serial.available() > 0) {
      player_response = Serial.parseInt();
      if (player_response < 1) player_response = 1;
      if (player_response > 3) player_response = 3;
      Serial.print("Ответ получен ");
      Serial.println(player_response);
      break;
    }
  }

  if (player_response == 3) { // Если промахнулись, отдаем ход игроку, а результат записываем в массив
    order_of_progress = !order_of_progress;
    Serial.println("Компьютер промахнулся");
    battlefield_player[Ya][Xa] = 3;
  }

  if (player_response == 1) { // Ранил, записываем в массив, очередь хода не меняется
    Serial.println("Ранил, компьютер ходит опять");
    battlefield_player[Ya][Xa] = 1;
    goto replay2;
  }

  if (player_response == 2) { // Убил, записываем в массив, очередь хода не меняется, меняем все 1 (ранения) на 2 (убил)
    Serial.println("Убил, компьютер ходит опять");
    battlefield_player[Ya][Xa] = 2;
    for (int k = 0; k < 10; k++) {
      for (int m = 0; m < 10; m++) {
        if (battlefield_player[k][m] == 1) battlefield_player[k][m] = 2;
      }
    }

    // окружаем 2 ореолом из 3, что бы не стрелять в окрестностях корабля
    for (int k = 0; k < 10; k++) {
      for (int m = 0; m < 10; m++) {
        if (battlefield_player[k][m] == 2) {
          if (k + 1 < 10 && battlefield_player[k + 1][m] == 0) battlefield_player[k + 1][m] = 3;
          if (k - 1 >= 0 && battlefield_player[k - 1][m] == 0) battlefield_player[k - 1][m] = 3;

          if (m + 1 < 10 && battlefield_player[k][m + 1] == 0) battlefield_player[k][m + 1] = 3;
          if (m - 1 >= 0 && battlefield_player[k][m - 1] == 0) battlefield_player[k][m - 1] = 3;

          if (k + 1 < 10 && battlefield_player[k + 1][m + 1] == 0 && m + 1 < 10) battlefield_player[k + 1][m + 1] = 3;
          if (m - 1 >= 0 && battlefield_player[k + 1][m - 1] == 0 && k + 1 < 10) battlefield_player[k + 1][m - 1] = 3;

          if (k - 1 >= 0 && battlefield_player[k - 1][m - 1] == 0 && m - 1 >= 0) battlefield_player[k - 1][m - 1] = 3;
          if (m + 1 < 10 && battlefield_player[k - 1][m + 1] == 0 && k - 1 >= 0) battlefield_player[k - 1][m + 1] = 3;

        }
      }
    }

    ////////// Проверим, а не победил ли компьютер
    int w = total_tonnage;
    for (int k = 0; k < 10; k++) {
      for (int m = 0; m < 10; m++) {
        if (battlefield_player[k][m] == 2) {
          w = w - 1;
          if (w == 0) {
            Serial.println("Компьютер победил");
            while (1);
          }
        }
      }
    }

    /////// Посмотрим, что там окружилось 3
    for (int i = 9; i >= 0; i--) { // Посмотрим, что получилось
      for (int j = 0; j < 10; j++) {
        //Serial.print(" ");
        Serial.print(battlefield_player[i][j]);
      }
      Serial.println();
    }
    Serial.println();

  } // Конец условия, если ответ игрока 2 - убил

} // Конец хода компьютера

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

А я поддержу мнение, что данную задачу целесообразно решать через объекты.

По сути, игровое поле может оказаться полезным лишь на стадии расстановки кораблей, а для самой игры поле не нужно . От слова "совсем". Есть корабль с набором полей и методов и он сам помнит свое состояние, осуществляет проверки и отвечает на допустимые запросы о своем состоянии.

На очередном шаге придумываем очередную пару координат, сообщаем их в цикле всем кораблям, они отвечают, скажем:

0 - не попал,

1 - ранил, 

2 - убил,

3 - давно затонул.

Анализируем ответ и принимаем решение, что делать дальше.

Lictor
Offline
Зарегистрирован: 01.10.2015

Эх, хорошо... Все проблемы решены, единственный недостаток, когда ардуина ходит, она не учитывает, а влезет ли, например, 4 палубный корабль в те поля, куда она стреляет.  Но добивать корабли она кажется стала правильно. Ну и код прилагаю, вдруг кому понадобится. Т.к. задача хоть и тривиальная, да и задается на всех олимпиадах на которых не лень, но более менее простого кода я не нашел. А разбираться в 2000 строках кода чего то так себе затея. 

 

int battlefield_computer[10][10];  // Поле компьютера
int battlefield_player[10][10];  // Поле игрока
byte order_of_progress = 1;  // Флаг очередности хода, 1 - игрок, 0 - компьютер
int total_tonnage;  // Общее кол-во клеток-кораблей

void ship_arrangement();  // Функция расстановки кораблей, передаем размер и кол-во
void player_move();  // Функция хода игрока
void arduino_move();  // Функция хода компьютера

void setup() {

  Serial.begin(9600); // Открываем последовательное соединение
  randomSeed(analogRead(0));  // Запускаем функцию рандом случайным образом

  for (int i = 0; i < 10; i++) { // заполним поле нулями
    for (int j = 0; j < 10; j++) {
      battlefield_computer[i][j] = 0;
      battlefield_player[i][j] = 0;
    }
  }

  //////////////////// Расставим корабли
  ship_arrangement(4, 1); // Передаем размер корабля и кол-во
  ship_arrangement(3, 2); // Передаем размер корабля и кол-во
  ship_arrangement(2, 3); // Передаем размер корабля и кол-во
  ship_arrangement(1, 4); // Передаем размер корабля и кол-во

  for (int i = 0; i < 10; i++) { // Заменим 2 в полях вокруг корабля на 0
    for (int j = 0; j < 10; j++) {
      if (battlefield_computer[j][i] == 2) battlefield_computer[j][i] = 0;
    }
  }

  //////////////////// Закончили расстановку

  for (int i = 9; i >= 0; i--) { // Посмотрим, что получилось
    for (int j = 0; j < 10; j++) {
      //Serial.print(" ");
      Serial.print(battlefield_computer[i][j]);
    }
    Serial.println();
  }
  Serial.println();
  Serial.print("Общий тоннаж ");
  Serial.println(total_tonnage);

} // Конец void setup()

void loop() {
  if (order_of_progress == 1) {
    Serial.println("Ход игрока");
    player_move();
  }
  else arduino_move();
} // Конец void loop()

void ship_arrangement(int ship_size, int quantity) {  // Функция расстановки кораблей

  total_tonnage = total_tonnage + ship_size * quantity; // Кол-во клеток занятых кораблями

  for (int t = 0; t < quantity; t++) {  // Кол-во повторов равно кол-ву кораблей
label:
    int x = random(0, 10); // Случайные координаты корабля
    int y = random(0, 10);

    uint8_t Direction = random(0, 2); // Случайное направление корабля

    if (Direction == 1) { // Расположим корабль по оси Х (j)
      for (int j = 0; j < ship_size ; j++) {  // Проверяем свободны ли поля (т.е. равно ли оно 0)
        if (battlefield_computer[y][x + j] == 0 && x + j < 10) { // Если условие не выполняется, то переносимся на начало
        }
        else {
          goto label;
        }
      }

      for (int i = 0; i < ship_size ; i++) battlefield_computer[y][x + i] = 1; // Если проверка прошла успешно, рисуем корабль
      // А когда нарисовали корабль, заполним область вокруг
      for (int i = 0; i < ship_size ; i++) {
        if (y + 1 < 10)  battlefield_computer[y + 1][x + i] = 2;
        if (y - 1 >= 0)  battlefield_computer[y - 1][x + i] = 2;
      }

      if (x - 1 >= 0) {
        battlefield_computer[y][x - 1] = 2;
        if (y - 1 >= 0)  battlefield_computer[y - 1][x - 1] = 2;
        if (y + 1 < 10) battlefield_computer[y + 1][x - 1] = 2;
      }

      if (x + ship_size < 10) {
        battlefield_computer[y][x + ship_size] = 2;
        if (y - 1 >= 0) battlefield_computer[y - 1][x + ship_size] = 2;
        if (y + 1 < 10) battlefield_computer[y + 1][x + ship_size] = 2;
      }
      // Закончили заполнять область вокруг
    } // Конец расположения корабля по оси Х (j)
    else //Если корабль не расположен по оси Х
    { // Расположим корабль по оси Y (i)
      for (int i = 0; i < ship_size ; i++) {  // Проверяем свободны ли поля (т.е. равно ли оно 0)
        if (battlefield_computer[y + i][x] == 0 && y + i < 10) { // Если условие не выполняется, то переносимся на начало
        }
        else {
          goto label;
        }
      }

      for (int i = 0; i < ship_size ; i++) battlefield_computer[y + i][x] = 1; // Если проверка прошла успешно, рисуем корабль

      // А когда нарисовали корабль, заполним область вокруг
      for (int i = 0; i < ship_size ; i++) {
        if (x + 1 < 10)  battlefield_computer[y + i][x + 1] = 2;
        if (x - 1 >= 0)  battlefield_computer[y + i][x - 1] = 2;
      }

      if (y - 1 >= 0) {
        battlefield_computer[y - 1][x] = 2;
        if (x - 1 >= 0)  battlefield_computer[y - 1][x - 1] = 2;
        if (x + 1 < 10)  battlefield_computer[y - 1][x + 1] = 2;
      }

      if (y + ship_size < 10) {
        battlefield_computer[y + ship_size][x] = 2;
        if (x - 1 >= 0)  battlefield_computer[y + ship_size][x - 1] = 2;
        if (x + 1 < 10)  battlefield_computer[y + ship_size][x + 1] = 2;
      }
      // Закончили заполнять область вокруг
    }// Конец расположения корабля по оси Y (i)
  }
}

void player_move() {

  int Xp, Yp; // Координаты хода игрока

  while (1) { // Ждем координату по Х
    if (Serial.available() > 0) {
      Xp = Serial.parseInt();
      if (Xp < 0) Xp = 0;
      if (Xp > 9) Xp = 9;
      break;
    }
  }

  while (1) { // Ждем координату по Y
    if (Serial.available() > 0) {
      Yp = Serial.parseInt();
      if (Yp < 0) Yp = 0;
      if (Yp > 9) Yp = 9;
      Serial.print("Ход сделан ");
      Serial.print(Xp);
      Serial.print(" ");
      Serial.print(Yp);
      Serial.println();
      break;
    }
  }

  if (battlefield_computer[Yp][Xp] == 0) {
    Serial.println("Промах, ход переходит компьютеру ");
    order_of_progress = !order_of_progress;
  }


  int kill; // Вспомогательный счетчик
  kill = 0;

  if (battlefield_computer[Yp][Xp] == 1 || battlefield_computer[Yp][Xp] == 2) { // Если есть попадание или стреляем второй раз в раненый корабль
    battlefield_computer[Yp][Xp] = 2;  // Заменяем 1 на 2, что бы показать что корабль ранен

    for (int i = 1; i < 10; i++) { // Пройдемся по полям в поисках 0 или 1 по оси Х++
      if (Xp + i < 10) {
        if (battlefield_computer[Yp][Xp + i] == 1) {
          goto label;
          //  Serial.println("Ранен");
        }
        if (battlefield_computer[Yp][Xp + i] == 0) {
          kill++;
          break;
        }
      }
      else {  // Конец поля, корабль потоплен
        kill++;
        break;
      }
    } // Закончили хождения по оси Х++

    for (int i = 1; i < 10; i++) { // Пройдемся по полям в поисках 0 или 1 по оси Х--
      if (Xp - i >= 0) {
        if (battlefield_computer[Yp][Xp - i] == 1) {
          goto label;
          // Serial.println("Ранен");
        }
        if (battlefield_computer[Yp][Xp - i] == 0) {
          kill++;
          break;
        }
      }
      else {  // Конец поля, корабль потоплен
        kill++;
        break;
      }
    } // Закончили хождения по оси Х--

    for (int i = 1; i < 10; i++) { // Пройдемся по полям в поисках 0 или 1 по оси Y++
      if (Yp + i < 10) {
        if (battlefield_computer[Yp + i][Xp] == 1) {
          goto label;
          // Serial.println("Ранен");
        }
        if (battlefield_computer[Yp + i][Xp] == 0) {
          kill++;
          break;
        }
      }
      else {  // Конец поля, корабль потоплен
        kill++;
        break;
      }
    } // Закончили хождения по оси Y++

    for (int i = 1; i < 10; i++) { // Пройдемся по полям в поисках 0 или 1 по оси Y--
      if (Yp - i >= 0) {
        if (battlefield_computer[Yp - i][Xp] == 1) {
          goto label;
          // Serial.println("Ранен");
        }
        if (battlefield_computer[Yp - i][Xp] == 0) {
          kill++;
          break;
        }
      }
      else {  // Конец поля, корабль потоплен
        kill++;
        break;
      }
    } // Закончили хождения по оси Y--

    if (1 > 2) {
label:
      Serial.println("Ранен");
    }

    // Serial.println(kill);
    if (kill == 4) Serial.println("Убил");  // Если вокруг одни нули (через 2 перескакиваем и ищем 0 или 1)
  } // Закончили проверку потоплен ли корабль

  int w;  // Проверим, а не победили ли мы за последний ход
  w = 0;
  for (int i = 0; i < 10; i++) { // скопируем поле компьютера во вспомогательное поле
    for (int j = 0; j < 10; j++) {
      if (battlefield_computer[i][j] == 1) w++;
    }
  }
  if (w == 0) {
    Serial.println("Победа");
    while (1);
  }

}  // Конец функции стрельбы игрока

void arduino_move() { // Ход компьютера

  //battlefield_player[10][10];  // Поле игрока
  //order_of_progress
  //total_tonnage;  // Общее кол-во клеток-кораблей

  int player_response = 0;  // Переменная ответа игрока (3 - промах, 2 - убил, 1 - ранил)
  int Xa = 99, Ya = 99; // Координаты хода компьютера
  // int flag = 0; // Флаг, 1 - было попадание до начала хода, 0 - не было попаданий

  // Проверяем есть ли прежние попадания (1)
replay2:

  //////// введем элементы ИИ (проставим 3 вокруг двух и более раненых элементов корабля, для задания направления стрельбы)
  for (int k = 0; k < 10; k++) {
    for (int m = 0; m < 10; m++) {

      if (battlefield_player[k][m] == 1 && battlefield_player[k + 1][m] == 1 && k + 1 < 10) {
        if (m + 1 < 10)  battlefield_player[k + 1][m + 1] = 3;
        if (m - 1 >= 0)  battlefield_player[k + 1][m - 1] = 3;
        if (m + 1 < 10)    battlefield_player[k][m + 1] = 3;
        if (m - 1 >= 0)  battlefield_player[k][m - 1] = 3;
      }

      if (battlefield_player[k][m] == 1 && battlefield_player[k - 1][m] == 1 && k - 1 >= 0) {
        if (m + 1 < 10)  battlefield_player[k - 1][m + 1] = 3;
        if (m - 1 >= 0)  battlefield_player[k - 1][m - 1] = 3;
        if (m + 1 < 10)    battlefield_player[k][m + 1] = 3;
        if (m - 1 >= 0)  battlefield_player[k][m - 1] = 3;
      }

      if (battlefield_player[k][m] == 1 && battlefield_player[k][m + 1] == 1 && m + 1 < 10) {
        if (k + 1 < 10)  battlefield_player[k + 1][m + 1] = 3;
        if (k - 1 >= 0)  battlefield_player[k - 1][m + 1] = 3;
        if (k + 1 < 10)    battlefield_player[k + 1][m] = 3;
        if (k - 1 >= 0)  battlefield_player[k - 1][m] = 3;
      }


      if (battlefield_player[k][m] == 1 && battlefield_player[k][m - 1] == 1 && m - 1 >= 0) {
        if (k + 1 < 10)  battlefield_player[k + 1][m - 1] = 3;
        if (k - 1 >= 0)  battlefield_player[k - 1][m - 1] = 3;
        if (k + 1 < 10)    battlefield_player[k + 1][m] = 3;
        if (k - 1 >= 0)  battlefield_player[k - 1][m] = 3;
      }

    }
  }


// Посмотрим, что там окружилось:
    for (int i = 9; i >= 0; i--) { // Посмотрим, что получилось
      for (int j = 0; j < 10; j++) {
        //Serial.print(" ");
        Serial.print(battlefield_player[i][j]);
      }
      Serial.println();
    }
    Serial.println();
  //////// ввели элементы ИИ

int  X1 = 1, X2 = 1, Y1 = 1, Y2 = 1;

  for (int k = 0; k < 10; k++) {
    for (int m = 0; m < 10; m++) {
      if (battlefield_player[k][m] == 1) {  // нашли старое попадание
  
        for (int i = 0; i < 10; i++) {

if (X1 == 1) {
          
          if (k + i < 10 && battlefield_player[k + i][m] == 3) {
            X1 = 0;
            goto z;
          }
          else {
            if (k + i < 10 && battlefield_player[k + i][m] == 0) {
              Xa = m;
              Ya = k + i;
              break;
            }
         }
                

}
        z:
if (X2 == 1) {
        
          if (k - i >= 0 && battlefield_player[k - i][m] == 3) {
            X2 = 0;
            goto h;
          }
          else {
            if (k - i >= 0 && battlefield_player[k - i][m] == 0) {
              Xa = m;
              Ya = k - i;
              break;
            }
          }

}

h:

if (Y1 == 1) {

            if (m + i < 10 && battlefield_player[k][m + i] == 3) {
              Y1 = 0;
              goto p;
            }
            else {
              if (m + i < 10 && battlefield_player[k][m + i] == 0) {
                Xa = m + i;
                Ya = k;
                break;
              }
            }

}

p:

if (Y2 == 1) {
            if (m - i >= 0 && battlefield_player[k][m - i] == 3) {
              Y2 = 0;
              break;
            }
            else {
              if (m - i >= 0 && battlefield_player[k][m - i] == 0) {
                Xa = m - i;
                Ya = k;
                break;
              }
            }
}
          }

        }
      }
    


  } // Конец цикла,  вкотором мы стреляли по раненому кораблю

  if (Xa != 99 && Ya != 99) {
    Serial.print("Ход компьютера рядом со старым попаданием ");
    Serial.print("Xa= ");
    Serial.print(Xa);
    Serial.print(" Ya= ");
    Serial.println(Ya);
  }



  if (Xa == 99 && Ya == 99) { // Не было попадания, генерируем случайный ход
newXY:
    Xa = random(0, 10); // Случайные координаты корабля
    Ya = random(0, 10);
    if (battlefield_player[Ya][Xa] == 2 || battlefield_player[Ya][Xa] == 3) goto newXY;
    Serial.print("Ход компьютера ");
    Serial.print("Xa= ");
    Serial.print(Xa);
    Serial.print(" Ya= ");
    Serial.println(Ya);
  }

  while (1) { // Ждем ответ игрока на запрошенные координаты
    if (Serial.available() > 0) {
      player_response = Serial.parseInt();
      if (player_response < 1) player_response = 1;
      if (player_response > 3) player_response = 3;
      Serial.print("Ответ получен ");
      Serial.println(player_response);
      break;
    }
  }

  if (player_response == 3) { // Если промахнулись, отдаем ход игроку, а результат записываем в массив
    order_of_progress = !order_of_progress;
    Serial.println("Компьютер промахнулся");
    battlefield_player[Ya][Xa] = 3;
  }

  if (player_response == 1) { // Ранил, записываем в массив, очередь хода не меняется
    Serial.println("Ранил, компьютер ходит опять");
    battlefield_player[Ya][Xa] = 1;
    goto replay2;
  }

  if (player_response == 2) { // Убил, записываем в массив, очередь хода не меняется, меняем все 1 (ранения) на 2 (убил)
    Serial.println("Убил, компьютер ходит опять");
    battlefield_player[Ya][Xa] = 2;
    for (int k = 0; k < 10; k++) {
      for (int m = 0; m < 10; m++) {
        if (battlefield_player[k][m] == 1) battlefield_player[k][m] = 2;
      }
    }

    // окружаем 2 ореолом из 3, что бы не стрелять в окрестностях корабля
    for (int k = 0; k < 10; k++) {
      for (int m = 0; m < 10; m++) {
        if (battlefield_player[k][m] == 2) {
          if (k + 1 < 10 && battlefield_player[k + 1][m] == 0) battlefield_player[k + 1][m] = 3;
          if (k - 1 >= 0 && battlefield_player[k - 1][m] == 0) battlefield_player[k - 1][m] = 3;

          if (m + 1 < 10 && battlefield_player[k][m + 1] == 0) battlefield_player[k][m + 1] = 3;
          if (m - 1 >= 0 && battlefield_player[k][m - 1] == 0) battlefield_player[k][m - 1] = 3;

          if (k + 1 < 10 && battlefield_player[k + 1][m + 1] == 0 && m + 1 < 10) battlefield_player[k + 1][m + 1] = 3;
          if (m - 1 >= 0 && battlefield_player[k + 1][m - 1] == 0 && k + 1 < 10) battlefield_player[k + 1][m - 1] = 3;

          if (k - 1 >= 0 && battlefield_player[k - 1][m - 1] == 0 && m - 1 >= 0) battlefield_player[k - 1][m - 1] = 3;
          if (m + 1 < 10 && battlefield_player[k - 1][m + 1] == 0 && k - 1 >= 0) battlefield_player[k - 1][m + 1] = 3;

        }
      }
    }

    ////////// Проверим, а не победил ли компьютер
    int w = total_tonnage;
    for (int k = 0; k < 10; k++) {
      for (int m = 0; m < 10; m++) {
        if (battlefield_player[k][m] == 2) {
          w = w - 1;
          if (w == 0) {
            Serial.println("Компьютер победил");
            while (1);
          }
        }
      }
    }

    /////// Посмотрим, что там окружилось 3
  /*  for (int i = 9; i >= 0; i--) { // Посмотрим, что получилось
      for (int j = 0; j < 10; j++) {
        //Serial.print(" ");
        Serial.print(battlefield_player[i][j]);
      }
      Serial.println();
    }
    Serial.println();
*/
  } // Конец условия, если ответ игрока 2 - убил

} // Конец хода компьютера

 

Bruzzer
Offline
Зарегистрирован: 17.03.2020

Обратите внимание, вы объявили прототип функции, но не указали параметры. Это не правильно.

006    void ship_arrangement();  // Функция расстановки кораблей, передаем размер и кол-во

Arduino IDE не требует предварительного объявления функций, и наверное поэтому нет сообщения об ошибке.

 

Lictor
Offline
Зарегистрирован: 01.10.2015

ЕвгенийП пишет:

mykaida пишет:

Пипец- дальше будет спейсквест? Или тетрис?

А слабо сделать физический Тетрис? Чтобы реальные тетраминошки падали? Я вот давно думаю. Мож систему магнитов какую? Может, чтобы падали в жидкости, чтобы помедленнее? Всякий бред в голову приходит.

 

Это можно сделать на подобии гидравлического компьютера: поле представляет собой кубы с отверстиями для перетока жидкости, а открывая и закрывая отдельные "перетоки" между кубами можно управлять формой фигуры, давлением поддавки регулировать скорость "падения" фигуры. 

Если непонятно, могу нарисовать набросок