I made the original battleship and now I'm looking to upgrade my AI from random guessing to guessing statistically probably locations. I'm having trouble finding algorithms online, so my question is what kinds of algorithms already exist for this application? And how would I implement one?
Ships: 5, 4, 3, 3, 2
Field: 10X10
Board:
OCEAN = "O"
FIRE = "X"
HIT = "*"
SIZE = 10
SEA = [] # Blank Board
for x in range(SIZE):
SEA.append([OCEAN] * SIZE)
If you'd like to see the rest of the code, I posted it here: (https://github.com/Dbz/Battleship/blob/master/BattleShip.py); I didn't want to clutter the question with a lot of irrelevant code.
Place a ship on the edge of the board: Many opponents will fire most of their shots towards the middle of the board, so having at least one ship on an edge may give you an advantage. Do not place all your ships on the edge, or your opponent may guess the pattern of what you are doing.
To win at Battleship, try maximizing your hits by firing at the center of the board, since the four by four squares in the middle of the board are likely to contain a carrier ship or battleship! If you strike out twice when firing, move away from that area and try firing into a different segment of the board.
Battleship is a classic Navy strategy guessing game in which players guess at the location of an opponent's ships. As the game progresses the possibility of a ship to be in any location changes and the probabil- ity that a ship occupies any cell can be calculated based on the current state of the board.
Battleship is a game of both luck and strategy. To tip the scales toward strategy, it helps to play an offensive game. You can increase your odds by firing with purpose, even when you're firing blindly (which is the vast majority of the time).
The ultimate naive solution wold be to go through every possible placement of ships (legal given what information is known) and counting the number of times each square is full.
obviously, in a relatively empty board this will not work as there are too many permutations, but a good start might be:
for each square on board: go through all ships and count in how many different ways it fits in that square, i.e. for each square of the ships length check if it fits horizontally and vertically.
an improvement might be to also check for each possible ship placement if the rest of the ships can be placed legally whilst covering all known 'hits' (places known to contain a ship).
to improve performance, if only one ship can be placed in a given spot, you no longer need to test it on other spots. also, when there are many 'hits', it might be quicker to first cover all known 'hits' and for each possible cover go through the rest.
edit: you might want to look into DFS.
Edit: Elaboration on OP's (@Dbz) suggestion in the comments:
hold a set of dismissed placements ('dissmissed') of ships (can be represented as string, say "4V5x3"
for the placement of length 4 ship in 5x3, 5x4, 5x5, 5x6), after a guess you add all the placements the guess dismisses, then for each square hold a set of placements that intersect with it ('placements[x,y]') then the probability would be:
34-|intersection(placements[x,y], dissmissed)|/(3400-|dismissed|)
To add to the dismissed list:
placements[x,y]
<(2,3a,3b,4,5)>H<X+1>x<Y>
, <(2,3a,3b,4,5)>V<X>x<Y+1>
<(2,3a,3b,4,5)>H<X-(2,3,3,4,5)>x<Y>
, <(2,3a,3b,4,5)>V<X>x<Y-(2,3,3,4,5)>
2H<X+-1>x<Y+(-2 to 1)>
, 3aH<X+-1>x<Y+(-3 to 1)>
...2V<X+(-2 to 1)>x<Y+-1>
, 3aV<X+(-3 to 1)>x<Y+-1>
...|intersection(placements[x,y], dissmissed)|==33
, i.e. only one placement possible add ship (see later)adding a ship:
placements[x,y]
with out the actual placementi might have over complicated this, there might be some redundant actions, but you get the point.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With