Created
March 28, 2015 10:50
-
-
Save nsmaciej/54804e2287b93384faa5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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