/* public void NewGame(Size size) { width = size.Width; height = size.Height; state = new State[width, height]; left = new int[width, height]; right = new int[width, height]; below = new int[width, height]; above = new int[width, height]; space = new int[width, height]; hits = new int[width, height]; remainingShips = new List<int>(); mustExplore = new List<Point>(); } // nothing fancy, just random placement. Also note which ships we have available. public void PlaceShips(ReadOnlyCollection<Ship> ships) { remainingShips.Clear(); foreach (Ship s in ships) { remainingShips.Add(s.Length); s.Place( new Point( rand.Next(width), rand.Next(height)), (ShipOrientation)rand.Next(2),new Size(10,10)); } }*/ public System.Collections.IEnumerator PlaceShip(Ship ship) { yield return null;// return new WaitForSeconds(0.5f); if (ship != null) { int tries = 0; bool success = false; while (!success) { if (tries > 100) break; // no infinite loops if (!ship.Place(new Point(rand.Next(this.gameSize.Width), rand.Next(this.gameSize.Height)), (ShipOrientation)rand.Next(2), gameSize)) continue; remainingShips.Add(ship.Length); success = true; foreach (Ship s in mShips) { if(s != ship) success &= !ship.ConflictsWith(s); } tries++; } if (!success) throw new OperationCanceledException("PlaceShip"); if (mPlayer) { /*foreach (Point p in ship.GetAllLocations()) { Init_board.gameGrid[p.X, p.Y].renderer.material.color = Color.green; }*/ ship.LoadModel(); ship.ShowModel(); } } waitingForRoutine = false; curship++; }
// Renvoie une liste de bâteaux placés intelligemment dans la grille private List <Ship> placeShips(int[] ship_sizes) { int max_opp_shots = 0; // Plus grand nombre de coups tirés par l'adversaire sur un même point foreach (int x in opponent_shots) { max_opp_shots = Math.Max(max_opp_shots, x); } max_opp_shots++; // Précaution pour éviter la division par 0 #if DEBUG Console.WriteLine("square shot scores"); for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { Console.Write("{0,-4} ", 1000 * opponent_shots [x, y] / max_opp_shots); } Console.WriteLine(); } #endif // Génération aléatoire de 100 placements : liste de 100 listes de bâteaux const int N = 100; List <List <Ship> > allocations = new List <List <Ship> > (); for (int n = 0; n < N; n++) { List <Ship> allocation = new List <Ship> (); // Nouvelle liste de bâteaux foreach (int size in ship_sizes) // Pour toutes les tailles de bâteaux demandées... { Ship s = new Ship(size); // Nouveau bâteau de taille 'size' while (true) { // Position et orientation aléatoires int x = rand.Next(w); int y = rand.Next(h); int orient = rand.Next(2); s.Place(new Point(x, y), (ShipOrientation)orient); // Si le placement obtenu n'est pas valide on repars au début de la boucle while if (!s.IsValid(new Size(w, h))) { continue; } // S'il n'y a pas de conflits entre les bâteaux on sort de la boucle while bool ok = true; foreach (Ship t in allocation) { if (s.ConflictsWith(t)) { ok = false; break; } } if (ok) { break; } } allocation.Add(s); // Ajout du bâteau à la liste } allocations.Add(allocation); // Ajout de la liste à allocations } /* Notation des 100 placements et choix du meilleur : * Pour chaque cas on incrémente un score selon différents critères. * Le meilleur score (celui qu'on garde) est le plus faible. */ int minscore = 1000000000; // Score minimum initialisé avec une grande valeur List <Ship> min_allocation = null; // Placement optimal : correspond au score minimum foreach (List <Ship> allocation in allocations) // Pour chaque placement proposé... { int score = 0; // Initialisation du score à 0 foreach (Ship s in allocation) // Pour chaque bâteau s... { foreach (Point p in s.GetAllLocations()) // Pour chaque point appartenant au bâteau... // Incrémentation du score en fonction du nombre de tirs adverse sur ce point { score += 100 * opponent_shots [p.X, p.Y] / max_opp_shots; } foreach (Ship t in allocation) // Pour chaque bâteau t... // Si s et t son adjacents et que l'option standard_touching est désactivée : faible pénalité { if (!standard_touching && shipsAdjacent(s, t)) { score += 20; } // Si s et t son adjacents et que l'option place_notouching est activée : forte pénalité if (place_notouching && shipsAdjacent(s, t)) { score += 1000000; } } } score += rand.Next(15); // Ajout d'une faible valeur aléatoire pour éviter les doublons if (score < minscore) // Si le score obtenu est meilleure que minscore, on le prend comme référence. { minscore = score; // Nouveau score min de référence. min_allocation = allocation; // Nouveau placement optimal } } return(min_allocation); }
// Mise à jour de ship_possibilities suite à un coup réussi : bateau touché void updatePossibilitiesHit(Point p) { // This is the hard one. If a hit was on a ship in the list, // check a few things. Otherwise, we need to add to the list // all possible ships/positions that can cover the new hit. // Nouvelle liste de possibilités qui remplacera ship_possibilities List <List <Ship> > new_possibilities = new List <List <Ship> > (); foreach (List <Ship> list in ship_possibilities) // Pour chaque liste de bateaux dans ship_possibilities... { // Recherche du bateau qui a été touché Ship hit_ship = null; foreach (Ship s in list) { if (s.IsAt(p)) { hit_ship = s; } } if (hit_ship != null) // Si un bateau a été trouvé... { // Vérification : le bateau n'a pas été entièrement touché (coulé) foreach (Point q in hit_ship.GetAllLocations()) // Pour chaque point du bateau... { if (state [q.X, q.Y] == SeaState.CLEAR) // Si le SeaState est CLEAR : OK, bateau non coulé { new_possibilities.Add(list); // On ajoute cette liste aux nouvelles possibilités break; // On arrête la recherche, on sait que le bateau n'est pas coulé } } continue; } // Autres cas : tir en dehors des bateaux de la liste. // Ajout de toutes les nouvelles positions possibles // d'un bateau qui intersecte ce point // (création de plusieurs listes). List <int> t = new List <int> (orig_ship_sizes); // Liste des tailles des bateaux au départ du jeu foreach (Ship s in list) // Pour chaque bateau déjà placé dans la liste list... { t.Remove(s.Length); // on supprime la valeur correspondante dans t } // t est donc la liste des tailles des bateaux non placés dans cette liste de bateaux // Liste sans doublons des tailles des bateaux non placés dans cette liste de bateaux List <int> possible_sizes = new List <int> (); foreach (int v in t) // pour chaque valeur v de t { if (!possible_sizes.Contains(v)) // si v n'est pas déjà dans possible_size { possible_sizes.Add(v); // ajout de v dans possible_size } } // ... foreach (int size in possible_sizes) // Pour chaque taille possible de bateau non placé { for (int offset = 0; offset < size; offset++) { for (int orient = 0; orient < 2; orient++) { int dy = orient; int dx = 1 - dy; int x = p.X - offset * dx; int y = p.Y - offset * dy; if (x < 0 || y < 0) { continue; } if (x + size * dx > boardSize.Width) { continue; } if (y + size * dy > boardSize.Height) { continue; } bool valid = true; for (int i = 0; i < size; i++) { if (i == offset) { continue; // the new hit } if (state [x + i * dx, y + i * dy] != SeaState.CLEAR) { valid = false; break; } } if (!valid) { continue; } Ship s = new Ship(size); s.Place(new Point(x, y), (ShipOrientation)orient); foreach (Ship w in list) { if (s.ConflictsWith(w)) { valid = false; break; } } if (!valid) { continue; } List <Ship> new_list = new List <Ship> (list); new_list.Add(s); new_possibilities.Add(new_list); } } } } // Enregistrement des nouvelle possibilités dans ship_possibilities ship_possibilities = new_possibilities; }
public System.Collections.IEnumerator PlaceShip(Ship ship) { bool placed = false; bool valid = false; if (ship != null) { ship.LoadModel(); ship.HideModel(); while (!placed) { yield return null; if (Input.GetKeyDown("r")) { if(placeOrientation == ShipOrientation.Horizontal) placeOrientation = ShipOrientation.Vertical; else placeOrientation = ShipOrientation.Horizontal; } if (Input.GetMouseButtonDown(0) && valid) { placed = true; break; } Point cast = getBoardRayCast(false, Color.white); if (ship.Place(cast, placeOrientation, gameSize)) { bool collides = false; foreach (Ship s in mShips) { if (s != ship) collides |= ship.ConflictsWith(s); } if (!collides) { ship.ShowModel(); valid = true; } else { ship.HideModel(); valid = false; } } else { ship.HideModel(); valid = false; } } } waitingForRoutine = false; curship++; }