mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2026-02-04 19:12:07 -08:00
Move shot selection into ComputerShotSelector
This commit is contained in:
@@ -17,13 +17,13 @@ internal class Game
|
||||
{
|
||||
_io.Write(Streams.Title);
|
||||
|
||||
var hitRecords = new List<(int Turn, Ship Ship)>();
|
||||
var damagedShips = new List<(int Turn, Ship Ship)>();
|
||||
var temp = new Position[13];
|
||||
|
||||
var computerGrid = new Grid(_random);
|
||||
var humanGrid = new Grid(_io);
|
||||
var humanShotSelector = new HumanShotSelector(humanGrid, computerGrid, _io);
|
||||
var computerShotSelector = new SearchPatternShotSelector(computerGrid, humanGrid, _random);
|
||||
var computerShotSelector = new ComputerShotSelector(computerGrid, humanGrid, _random);
|
||||
var startResponse = _io.ReadString(Prompts.Start);
|
||||
while (startResponse == Strings.WhereAreYourShips)
|
||||
{
|
||||
@@ -64,12 +64,11 @@ L2850: if (humanGrid.UntriedSquareCount > numberOfShots) { goto L2880; }
|
||||
L2860: _io.Write(Streams.IHaveMoreShotsThanSquares);
|
||||
L2270: _io.Write(Streams.IWon);
|
||||
return;
|
||||
L2880: if (numberOfShots != 0) { goto L2960; }
|
||||
L2880: if (numberOfShots == 0) { goto L2960; }
|
||||
L2890: _io.Write(Streams.YouWon);
|
||||
L2900: return;
|
||||
|
||||
L2960: if (humanGrid.Ships.Any(s => s.IsDamaged)) { goto L3800; }
|
||||
temp = computerShotSelector.GetShots().ToArray();
|
||||
L2960: temp = computerShotSelector.GetShots().ToArray();
|
||||
// display shots
|
||||
L3380: if (seeShotsResponse == "YES")
|
||||
{
|
||||
@@ -80,64 +79,13 @@ L3380: if (seeShotsResponse == "YES")
|
||||
}
|
||||
foreach (var shot in temp)
|
||||
{
|
||||
if (!humanGrid.IsHit(shot, turnNumber, out var ship))
|
||||
if (humanGrid.IsHit(shot, turnNumber, out var ship))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
_io.Write(Strings.IHit(ship.Name));
|
||||
if (ship.IsDestroyed)
|
||||
{
|
||||
hitRecords = hitRecords.Where(hr => hr.Ship != ship).ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
hitRecords.Add((turnNumber, ship));
|
||||
_io.Write(Strings.IHit(ship.Name));
|
||||
computerShotSelector.RecordHit(ship, turnNumber);
|
||||
}
|
||||
}
|
||||
goto L1950;
|
||||
L3800: //REM************************USINGEARRAY
|
||||
var tempGrid = Position.All.ToDictionary(x => x, _ => 0);
|
||||
L3860: foreach (var (hitTurn, ship) in hitRecords)
|
||||
{
|
||||
foreach (var position in Position.All)
|
||||
{
|
||||
if (humanGrid.WasTargetedAt(position, out _))
|
||||
{
|
||||
tempGrid[position]=-10000000;
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var neighbour in position.Neighbours)
|
||||
{
|
||||
if (humanGrid.WasTargetedAt(neighbour, out var turn) && turn == hitTurn)
|
||||
{
|
||||
tempGrid[position] += hitTurn + 10 - position.Y * ship.Shots;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
L4030: for (var i = 0; i < numberOfShots; i++)
|
||||
{
|
||||
L4040: temp[i]=i+1;
|
||||
}
|
||||
foreach (var position in Position.All)
|
||||
{
|
||||
L4090: var Q9=0;
|
||||
L4100: for (var i = 0; i < numberOfShots; i++)
|
||||
{
|
||||
L4110: if (tempGrid[temp[i]] < tempGrid[temp[Q9]])
|
||||
{
|
||||
L4120: Q9 = i;
|
||||
}
|
||||
}
|
||||
L4131: if (position.X <= numberOfShots && position.IsOnDiagonal) { continue; }
|
||||
L4140: if (tempGrid[position]<tempGrid[temp[Q9]]) { continue; }
|
||||
if (!temp.Contains(position))
|
||||
{
|
||||
temp[Q9] = position;
|
||||
}
|
||||
}
|
||||
L4230: goto L3380;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,27 +2,20 @@ namespace Salvo.Targetting;
|
||||
|
||||
internal class ComputerShotSelector : ShotSelector
|
||||
{
|
||||
private readonly bool _displayShots;
|
||||
private readonly KnownHitsShotSelectionStrategy _knownHitsStrategy;
|
||||
private readonly SearchPatternShotSelector _searchPatternShotSelector;
|
||||
|
||||
internal ComputerShotSelector(Grid source, Grid target, bool displayShots)
|
||||
internal ComputerShotSelector(Grid source, Grid target, IRandom random)
|
||||
: base(source, target)
|
||||
{
|
||||
_displayShots = displayShots;
|
||||
_knownHitsStrategy = new KnownHitsShotSelectionStrategy(target);
|
||||
_searchPatternShotSelector = new SearchPatternShotSelector(source, target, random);
|
||||
}
|
||||
|
||||
internal override IEnumerable<Position> GetShots()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _knownHitsStrategy.GetShots(NumberOfShots) ?? _searchPatternShotSelector.GetShots();
|
||||
}
|
||||
|
||||
private void DisplayShots(IEnumerable<Position> shots, IReadWrite io)
|
||||
{
|
||||
if (_displayShots)
|
||||
{
|
||||
foreach (var shot in shots)
|
||||
{
|
||||
io.WriteLine(shot);
|
||||
}
|
||||
}
|
||||
}
|
||||
internal void RecordHit(Ship ship, int turn) => _knownHitsStrategy.RecordHit(ship, turn);
|
||||
}
|
||||
|
||||
71
77_Salvo/csharp/Targetting/KnownHitsShotSelectionStrategy.cs
Normal file
71
77_Salvo/csharp/Targetting/KnownHitsShotSelectionStrategy.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
namespace Salvo.Targetting;
|
||||
|
||||
internal class KnownHitsShotSelectionStrategy : ShotSelectionStrategy
|
||||
{
|
||||
private readonly List<(int Turn, Ship Ship)> _damagedShips = new();
|
||||
|
||||
internal KnownHitsShotSelectionStrategy(Grid target)
|
||||
: base(target)
|
||||
{
|
||||
}
|
||||
|
||||
internal IEnumerable<Position>? GetShots(int numberOfShots)
|
||||
{
|
||||
if (!_damagedShips.Any()) { return null; }
|
||||
|
||||
var tempGrid = Position.All.ToDictionary(x => x, _ => 0);
|
||||
var shots = Enumerable.Range(1, numberOfShots).Select(x => new Position(x, x)).ToArray();
|
||||
|
||||
foreach (var (hitTurn, ship) in _damagedShips)
|
||||
{
|
||||
foreach (var position in Position.All)
|
||||
{
|
||||
if (WasSelectedPreviously(position))
|
||||
{
|
||||
tempGrid[position]=-10000000;
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var neighbour in position.Neighbours)
|
||||
{
|
||||
if (WasSelectedPreviously(neighbour, out var turn) && turn == hitTurn)
|
||||
{
|
||||
tempGrid[position] += hitTurn + 10 - position.Y * ship.Shots;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var position in Position.All)
|
||||
{
|
||||
var Q9=0;
|
||||
for (var i = 0; i < numberOfShots; i++)
|
||||
{
|
||||
if (tempGrid[shots[i]] < tempGrid[shots[Q9]])
|
||||
{
|
||||
Q9 = i;
|
||||
}
|
||||
}
|
||||
if (position.X <= numberOfShots && position.IsOnDiagonal) { continue; }
|
||||
if (tempGrid[position]<tempGrid[shots[Q9]]) { continue; }
|
||||
if (!shots.Contains(position))
|
||||
{
|
||||
shots[Q9] = position;
|
||||
}
|
||||
}
|
||||
|
||||
return shots;
|
||||
}
|
||||
|
||||
internal void RecordHit(Ship ship, int turn)
|
||||
{
|
||||
if (ship.IsDestroyed)
|
||||
{
|
||||
_damagedShips.RemoveAll(x => x.Ship == ship);
|
||||
}
|
||||
else
|
||||
{
|
||||
_damagedShips.Add((turn, ship));
|
||||
}
|
||||
}
|
||||
}
|
||||
16
77_Salvo/csharp/Targetting/ShotSelectionStrategy.cs
Normal file
16
77_Salvo/csharp/Targetting/ShotSelectionStrategy.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
namespace Salvo.Targetting;
|
||||
|
||||
internal abstract class ShotSelectionStrategy
|
||||
{
|
||||
private readonly Grid _target;
|
||||
protected ShotSelectionStrategy(Grid target)
|
||||
{
|
||||
_target = target;
|
||||
}
|
||||
|
||||
protected bool WasSelectedPreviously(Position position)
|
||||
=> _target.WasTargetedAt(position, out _);
|
||||
|
||||
protected bool WasSelectedPreviously(Position position, out int turn)
|
||||
=> _target.WasTargetedAt(position, out turn);
|
||||
}
|
||||
Reference in New Issue
Block a user