Last active
May 11, 2019 08:57
-
-
Save dermesser/966f7dbf3c658645ddb62ad7ec54d86f to your computer and use it in GitHub Desktop.
https://physikmix.lewinb.net for more!
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
#!/usr/bin/env python3 | |
# -*- coding: utf-8 -*- | |
""" | |
Created on Mon Apr 1 12:31:31 2019 | |
@author: lbo | |
""" | |
import numpy | |
import random | |
def create_field(dim): | |
return numpy.zeros((dim,dim), dtype=numpy.bool) | |
def place_1x1_ships(field, n): | |
i = 0 | |
def random_idx(): | |
return random.randint(0, field.shape[0]-1) | |
while i < n: | |
(x, y) = (random_idx(), random_idx()) | |
if field[x,y]: | |
continue | |
field[x,y] = True | |
i += 1 | |
def read_guess(dim): | |
raw = input("x,y?> ") | |
parts = raw.split(',') | |
(x, y) = parts[0:2] | |
(x, y) = (int(x), int(y)) | |
if x >= dim or y >= dim: | |
raise IndexError("Index must be in range 0..{}".format(dim-1)) | |
return (x,y) | |
def loop(field, finalcount=5): | |
count = 0 | |
while count < finalcount: | |
try: | |
c = read_guess(field.shape[0]) | |
if c == None: | |
print("aborted") | |
return | |
(x,y) = c | |
if field[x,y]: | |
count += 1 | |
print("BLLAAAMM") | |
else: | |
print("splash") | |
except KeyboardInterrupt: | |
return | |
except Exception as e: | |
print(e) | |
print("YOU WON") | |
if __name__ == '__main__': | |
f = create_field(10) | |
place_1x1_ships(f, 30) | |
loop(f) | |
print(f.astype(numpy.int)) | |
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
#!/usr/bin/env python3 | |
# -*- coding: utf-8 -*- | |
""" | |
Created on Mon Apr 1 12:31:31 2019 | |
@author: lbo | |
""" | |
import numpy | |
import random | |
# Functionality for building the board. | |
def create_field(dim): | |
"""Returns a dim*dim field with int fields. 0 is empty, 1 is ship, 2 is hit ship.""" | |
return numpy.zeros((dim,dim), dtype=numpy.int) | |
def place_1x1_ships(field, n): | |
i = 0 | |
def random_idx(): | |
return random.randint(0, field.shape[0]-1) | |
while i < n: | |
(x, y) = (random_idx(), random_idx()) | |
if field[x,y] == 1: | |
continue | |
field[x,y] = 1 | |
i += 1 | |
def place_ship(field, size): | |
"""Places a `size` ship somewhere on the field. | |
Returns a (x, y, 'h'/'v', size) tuple indicating its position.""" | |
direction = 'h' if random.randint(1, 100) <= 50 else 'v' | |
limits = (0,0) | |
max_idx = field.shape[0]-1 | |
if direction == 'h': # horizontal | |
limits = (max_idx, max_idx-size) | |
else: # vertical | |
limits = (max_idx-size, max_idx) | |
while True: | |
(x, y) = (random.randint(0, limits[0]), random.randint(0, limits[1])) | |
if direction == 'h': # horizontal | |
if field[x,y:y+size].sum() > 0: | |
continue | |
field[x, y:y+size] = 1 | |
# Cheat mode! | |
#print('size {} horiz at {},{}'.format(size, x, y)) | |
else: # vertical | |
if field[x:x+size,y].sum() > 0: | |
continue | |
field[x:x+size, y] = 1 | |
#print('size {} vert at {},{}'.format(size, x, y)) | |
return (x, y, 'h' if direction else 'v', size) | |
def place_real_ships(field, spec={1: 4, 2: 3, 3: 2, 4: 1}): | |
"""Places ships according to `spec` (size => number) and returns a list | |
of (x, y, 'h'/'v', size) tuples indicating the positions.""" | |
positions = [] | |
for (shipsize, num) in spec.items(): | |
for i in range(0, num): | |
positions.append(place_ship(field, shipsize)) | |
return positions | |
# Functionality for reading guesses and checking the board. | |
def read_guess(dim): | |
"""Read a coordinate guess from the user. | |
Raises exceptions if invalid input is received, returns None if the user | |
indicated that they want to exit the game, returns (x, y) tuple of the | |
entered position otherwise.""" | |
raw = input("x,y?> ") | |
if raw == 'ende': | |
return None | |
parts = raw.split(',') | |
(x, y) = parts[0:2] | |
(x, y) = (int(x), int(y)) | |
if x >= dim or y >= dim: | |
raise IndexError("Index must be in range 0..{}".format(dim-1)) | |
return (x,y) | |
def is_hit(field, c): | |
"""Check if there is a ship at x,y, or if there are neighbors. | |
Prints feedback about a hit.""" | |
(x,y) = c | |
if field[x,y] == 1: | |
print("BLLAAAMM") | |
return True | |
elif field[x,y] == 2: | |
print("Don't hit them! They're already sunk!") | |
elif has_ship_neighbor(field, c): | |
print("That was close!") | |
else: | |
print("splash") | |
return False | |
def has_ship_neighbor(field, c): | |
count = 0 | |
(x,y) = c | |
for dx in [-1, 0, 1]: | |
for dy in [-1, 0, 1]: | |
if dx == 0 and dy == 0: | |
continue | |
if (x+dx > field.shape[0]-1 or y+dy > field.shape[1]-1 or | |
x+dx < 0 or y+dy < 0): | |
continue | |
count += 1 if field[x+dx, y+dy] == 1 else 0 | |
return count > 0 | |
def check_sunk_and_remove(field, positions): | |
"""Checks if any ships have sunk. Returns True if so, and removes the ship | |
from the positions list in-place.""" | |
i = 0 | |
for pos in positions: | |
(x, y, direction, size) = pos | |
# 2 indicates a hit, so if a ship consists of only 2s, it's sunk. | |
if (direction == 'h' and field[x,y:y+size].sum() == size*2) or ( | |
direction == 'v' and field[x:x+size, y].sum() == size*2): | |
positions.pop(i) | |
return True | |
i += 1 | |
return False | |
def loop(field, positions, finalcount=5): | |
"""Run guessing loop. | |
field is the playing board, positions is a list of positions as returned | |
by place_real_ships().""" | |
count = 0 | |
while count < finalcount: | |
try: | |
c = read_guess(field.shape[0]) | |
if c == None: | |
print("aborted") | |
return | |
(x,y) = c | |
if is_hit(field, c): | |
field[x,y] = 2 | |
if check_sunk_and_remove(field, positions): | |
print("You sank it! Good job!") | |
count += 1 | |
except KeyboardInterrupt: | |
return | |
except Exception as e: | |
print("oh-oh!", e) | |
print("YOU WON") | |
if __name__ == '__main__': | |
f = create_field(10) | |
positions = place_real_ships(f) | |
loop(f, positions) | |
print(f.astype(numpy.int)) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment