Skip to content

Instantly share code, notes, and snippets.

@nsmaciej
Created March 28, 2015 10:50
Show Gist options
  • Save nsmaciej/54804e2287b93384faa5 to your computer and use it in GitHub Desktop.
Save nsmaciej/54804e2287b93384faa5 to your computer and use it in GitHub Desktop.
import random
import string
def pboard():
for i in board:
print(''.join(i))
def countf(what):
cnt = 0
for i in board:
cnt += sum(i.count(x) for x in what)
return cnt
def get(y, x):
if y < 0 or y > 9 or x < 0 or x > 9: return '!'
return board[y][x]
def around(y, x, diagonal, matching):
coords = [(0, 1), (0, -1), (1, 0), (-1, 0)]
if diagonal:
coords += [(1, 1), (1, -1), (-1, 1), (-1, -1)]
return [(y + yi, x + xi) for yi, xi in coords
if get(y + yi, x + xi) != '!' and (matching == None or get(y + yi, x + xi) in matching)]
def fill(y, x):
if get(y, x) == ' ':
board[y][x] = '.'
return 0
elif get(y, x) == '*':
board[y][x] = '@'
return sum(fill(yn, xn) for yn, xn in around(y, x, True, None)) + 1
return 0
def cntdown(y, x):
cnt, cnt2 = 0, 0
while get(y + cnt, x) == ' ': cnt += 1
while get(y - cnt2, x) == ' ': cnt2 += 1
return cnt + cnt2 - 1
def cntright(y, x):
cnt, cnt2 = 0, 0
while get(y, x + cnt) == ' ': cnt += 1
while get(y, x - cnt2) == ' ': cnt2 += 1
return cnt + cnt2 - 1
def findhit():
maxfound = 1
result = []
for y in range(10):
for x in range(10):
dres = cntdown(y, x)
if dres > maxfound: maxfound, result = dres, []
if dres == maxfound: result.append((y, x, 0))
rres = cntright(y, x)
if rres > maxfound: maxfound, result = rres, []
if rres == maxfound: result.append((y, x, 1))
y, x, _ = random.choice(result)
return y, x
def place(y, x):
global state
outcome = input('({}) {}{}: '.format(state, y + 1, string.ascii_uppercase[x]))[0].lower()
if outcome == 's':
board[y][x] = '*'
size = fill(y, x)
if ships.count(size) == 0:
raise ValueError("Sunk a non-existant ship")
ships.pop(ships.index(size))
state = 'find'
print('Sunk of size {}'.format(size))
elif outcome == 'h':
board[y][x] = '*'
elif outcome == 'm':
board[y][x] = 'x'
return outcome
ships = [4, 3, 3, 2, 2, 2, 1, 1, 1, 1]
board = [[' '] * 10 for x in range(10)]
state = 'find'
print("Outcomes: Hit, Miss, Sunk")
while ships:
if state == 'find':
y, x = findhit()
if place(y, x) == 'h':
state = 'dir'
elif state == 'dir':
result = around(y, x, False, [' '])
if not result:
raise ValueError("Impossible to place multi-part ship")
yp, xp = result[0]
if place(yp, xp) == 'h':
goy = int(yp != y)
gox = int(xp != x)
state = 'hright'
elif state == 'hright' or state == 'hleft':
count = 1
while get(y + count * goy, x + count * gox) in ['*', '@']:
count += 1
equals = get(y + count * goy, x + count * gox)
if equals != ' ':
if state == 'hleft':
raise ValueError("Unsinkabble ship")
state = 'hleft'
goy *= -1
gox *= -1
elif place(y + count * goy, x + count * gox) == 's':
state = 'find'
pboard()
print("All enemy ships sank")
print("Total shots: {}".format(countf(['x', '@'])))
print("On target: {}".format(countf(['@'])))
print("Real misses: {}".format(countf(['x'])))
print("Avoided misses: {}".format(countf(['.'])))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment