Bot do gry w statki

0

Cześć mam do napisania bota, który będzie grał w statki, przy czym zależy mi, aby bot wykonał jak najmniej strzałów. Przeczytałem fajny artykuł opierający się na prawdopodobieństwie znalezienia statku w danym rejonie (tutaj link dla zainteresowanych :) https://www.datagenetics.com/blog/december32011/index.html , jednakże zastanawiam się czy nie lepiej starać się zatopić coraz to mniejsze statki zaczynając od największego? Mam na myśli, aby strzelać co 5 pól wtedy na pewno trafimy w jednostkę o 5 polach. I potem po kolei strzelać co 4 , 3 ... aż uda zatopić mi się wszystkie . Co o tym sądzicie ? Może macie jakieś lepsze pomysły?

0

Myślę, że do momentu znalezienia statku strzelanie "na oślep" ( byle bez powtórzeń ) będzie równie skuteczne. Po zatopieniu statku wykluczyć pola otaczające go, w których nie może znaleźć się inny statek ( bo nie mogą się stykać ) i dalej walić "na oślep".
Jak to ogarniesz wtedy można kombinować coś ze strzelaniem co 5 czy co 2 i ewentualnym wykluczaniem obszarów gdzie nie ma prawa być dużych statków ( zakładając, że małe są wybite ).
Przypuszczam, ze równie dobrze można do tego zaciągnąć sieci neuronowe.

Swoją drogą fajny artykuł.

1

Są rożne wersje statków, więc może zacznij od opisania, o której wersji mówisz.
Różnice są:

  • kształt i wielkość statków
  • reguły rozmieszania - czy i jak mogą się stykać: dowolnie, rogami, wcale.
  • jak się strzela: pojedyncze strzały, salwy (po trzy).
  • czy istnieją dodatkowe funkcje (kiedyś grałem w wersję z sonarem).
0

Mam na myśli klasyczną 10 x 10 , nie mogą sie stykać, strzela się po raz i nie ma żadnych funkcji
I mam pytanie czy algorytm, który szedł by od lewej do prawej po polach tablicy i gdyby trafił to starałby się zatopić statek byłby skuteczny? Czy tak jak było pisane wyżej najlepszym sposobem jest po prstu strzelanie z obliczaniem prawdopodobieństwa na trafienie?

0

Jakoś by działał. Oczywiste ulepszenia to strzelanie w odstępach, co zwiększa szansę na trafienie w jakiś statek (jednomasztowców jest zazwyczaj dosyć mały odsetek całości) i odrzucanie przestrzeni zbyt małych, by się tam zmieścił jakiś okręt.

0

Może Ci się przyda. Żeby był "idealny" brakuje mu jednej rzeczy: sprawdzania czy któryś ze statków już jest zatopiony. Pozwoli to, dla przykładu, przerwać ostrzał statku, jeśli już zatopiłeś trzy maszty, a czteromasztowiec był zatopiony wcześniej. Kod brzydki i do refaktoryzacji, ale działa :)

@Injectable()
export class AiService {
  constructor(private board: BoardService) {}

  public getFireCoordinates(board: BoardCell[][]): Coordinates {
    let hits: BoardCell[] = this.board.getCurrentHits(board); // hit cells
    let missed: BoardCell[] = this.board.getCurrentMissed(board); //missed cells
    let forbidden: BoardCell[] = []; //can not shoot there
    let targets: BoardCell[] = []; //potential targets
    let isRandomCoordinateForbidden: boolean = true;
    let randomCoordinates: Coordinates = {
      row: -1,
      col: -1,
    } as Coordinates;
    forbidden.push.apply(forbidden, this.board.getCornerCells(hits));
    forbidden.push.apply(forbidden, missed);
    forbidden.push.apply(forbidden, hits);
    targets = this.board.getPotentialTargets(forbidden, hits);
    //todo: count hits in line and remove ships from list
    if (targets.length > 0) {
//todo: DRY
      while (isRandomCoordinateForbidden) {
        randomCoordinates = targets[Math.floor(Math.random() * targets.length)];
        if (!this.checkIfRandomIsForbidden(forbidden, randomCoordinates)) {
          isRandomCoordinateForbidden = false;
        }
      }
      return {
        row: randomCoordinates.row,
        col: randomCoordinates.col,
      } as Coordinates;
    } else {
//todo: DRY
      while (isRandomCoordinateForbidden) {
        randomCoordinates = this.getRandomCoordinates();
        if (!this.checkIfRandomIsForbidden(forbidden, randomCoordinates)) {
          isRandomCoordinateForbidden = false;
        }
      }

      return randomCoordinates;
    }
  }

  private checkIfRandomIsForbidden(
    cells: BoardCell[],
    coord: Coordinates
  ): boolean {
    for (let i = 0; i < cells.length; i++) {
      if (cells[i].row == coord.row && cells[i].col == coord.col) {
        return true;
      }
    }

    return false;
  }

  private getRandomCoordinates(): Coordinates {
    return {
      row: Math.floor(Math.random() * 10),
      col: Math.floor(Math.random() * 10),
    } as Coordinates;
  }
}

EDIT: algorytm dla klasycznej wersji gry w statki.

0

Grałem w taką wersję:

Jeżeli założyć, że statki nie mogą być wygięte ani się dotykać (nawet rogami), to na pustej planszy łatwiej trafić statek większy niż 1-masztowiec strzelając po przekątnej, jak w szachownicy. W tym filmiku można zaobserwować, jak bot "wybiera" miejsce strzału i wydaje się, że taką strategię przyjmuje.

W filmiku jak bot gra, to strzał spada z góry na planszę, a jak gracz gra, to obserwuje ostrzeliwany statek przez celownik (tylko taka animacja, nie ma żadnego celowania przez celownik).

1 użytkowników online, w tym zalogowanych: 0, gości: 1