Just to return to this idea again. I've found a bit of spare time and have returned to the code again and had a further play.
Hopefully it is a bit easier for others to tinker with. I've made the game area a class and made quite a lot into methods. Also I have tidied up the procedure for placing boats and now have one method to place boats of any size.
Anyhow, if you have a Unicorn hat feel free to have a play with the code and tinker.
Code: Select all
"""
Program: Battleships Unicorn Hat display
Author: Tim Mulford
Date: 28/08/2015
Version: 0.5
Changes:
I have update the code to make the game area a class with methods for the game.
"""
import unicornhat as unicorn
import time, random
# initialise Unicornhat board
# Unless you are using a difusser keep brightness low
unicorn.brightness(0.05)
unicorn.rotation(180)
# ocean stores the information about the game area and the methods required to
# interact with it
class ocean:
ships = 0
ammo = 0
water = [[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0]]
# Reset the game board
def reset(self):
self.water = [[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0]]
# Display the current board state on the Unicorn hat
def display_water(self):
for y in range(8):
for x in range(8):
if self.water[y][x] == 0 or self.water[y][x] == 1:
unicorn.set_pixel(x,y,79,106,226)
elif self.water[y][x] == 2:
unicorn.set_pixel(x,y,0,0,0)
elif self.water[y][x] == 3:
unicorn.set_pixel(x,y,255,0,0)
unicorn.show()
# Set every light on the board to the set colour
def flood_colour(self,red,green,blue):
for x in range(8):
for y in range(8):
unicorn.set_pixel(x,y,red,green,blue)
unicorn.show()
# Animation for when a shot is a hit
def hit_flash(self,count):
for repeat in range(count):
self.flood_colour(255,0,0)
time.sleep(0.2)
self.flood_colour(255,255,0)
time.sleep(0.2)
self.flood_colour(0,0,255)
time.sleep(0.5)
# Animation for when a shot is a miss
def miss_flash(self):
self.flood_colour(255,255,255)
time.sleep(0.3)
for a in range(0,255,10):
self.flood_colour(0,0,a)
# Animation for targetting using passed co-ordinates
def target_flash(self,x,y):
for a in range(8):
unicorn.set_pixel(x,a,0,200,0)
unicorn.show()
time.sleep(0.05)
for a in range(8):
unicorn.set_pixel(a,y,0,200,0)
unicorn.show()
time.sleep(0.05)
time.sleep(1)
for a in range(0,255,10):
unicorn.set_pixel(x,y,a,a,a)
unicorn.show()
time.sleep(0.01)
for a in range(0,255,10):
unicorn.set_pixel(x,y,255-a,255-a,255-a)
unicorn.show()
time.sleep(0.01)
# Animation for when the game is lost
def defeated(self):
for fade in range(0,255):
for y in range(8):
for x in range(8):
unicorn.set_pixel(x,y,255,255-fade,255-fade)
unicorn.show()
time.sleep(0.01)
# Animation for when the game is won
def victory(self):
for fade in range(0,255):
for y in range(8):
for x in range(8):
unicorn.set_pixel(x,y,255-fade,255,255-fade)
unicorn.show()
time.sleep(0.01)
# Place a boat of the passed size on the game board
# There is no limit to the number of boats placed though
# if too many boats are placed it might not be possible to
# place more and the program will get stuck in an infinite loop
# A "1" is placed in the water 2D array for each part of the boat
# The ships variable is updated to reflect the number of boat parts
# on the game area in total after the boat it placed.
def boat(self, size):
boat_mask = []
for a in range(size):
boat_mask.append(0)
orientation = random.choice(["horizontal","vertical"])
if orientation == "horizontal":
x = random.randint(0,8-size)
y = random.randint(0,7)
placement = []
for a in range(size):
placement.append(self.water[y][x+a])
while placement != boat_mask:
x = random.randint(0,8-size)
y = random.randint(0,7)
placement = []
for a in range(size):
placement.append(self.water[y][x+a])
for a in range(size):
self.water[y][x+a] = 1
else:
x = random.randint(0,7)
y = random.randint(0,8-size)
placement = []
for a in range(size):
placement.append(self.water[y+a][x])
while placement != boat_mask:
x = random.randint(0,8-size)
y = random.randint(0,7)
placement = []
for a in range(size):
placement.append(self.water[y+a][x])
for a in range(size):
self.water[y+a][x]=1
self.ships += size
# Process a shot using the passed co-ordinates on the game area
# determine if the shot is a hit, miss or an already hit area.
# The game area is then updated and the updated game area is displayed
# on the unicorn hat.
def shot(self,x,y):
if self.water[y][x] == 1:
print("Hit")
self.water[y][x] = 3
self.hit_flash(3)
self.ships -= 1
elif self.water[y][x] == 2:
print("You have already hit this area.")
else:
print("Miss")
self.water[y][x] = 2
self.miss_flash()
self.ammo -= 1
self.display_water()
# Enter and validate a co-ordinate
def enter_coord(direction):
valid = False
while valid != True:
try:
co_ord = int(input("Enter the "+direction+"-cordinate for your shot: "))
if co_ord in range(1,9):
valid = True
else:
print("Must be a number between 1 and 8.")
except:
print("Must be an number between 1 and 8.")
if direction == "x":
co_ord = co_ord - 1
else:
co_ord = 8 - co_ord
return co_ord
# Main Program
# Declare an instance of the game area
ocean = ocean()
# Main program loop
while True:
# Initialise the game area
ocean.reset()
ocean.boat(5)
ocean.boat(3)
ocean.boat(3)
ocean.boat(2)
ocean.boat(2)
ocean.ammo = 20
game_over = False
# Display the initial game area to the Unicornhat
ocean.display_water()
# Loop until game over conditions are met
while game_over == False:
# Display current game stats to the screen
print("\nYou have",ocean.ammo,"shots left")
print("There are",ocean.ships,"targets in our waters.")
print("")
# Get x and y co-ordinates of the shot
x = enter_coord("x")
y = enter_coord("y")
# Targetting animation
ocean.target_flash(x,y)
# Process the shot
ocean.shot(x,y)
# Check if the game over conditions are met
if ocean.ships == 0 or ocean.ammo == 0:
game_over = True
# If the game is over because it is lost display game over
if ocean.ammo == 0:
print("\nOur fleet is defeated.")
ocean.defeated()
# Else if it is over because the game is won display victory
elif ocean.ships == 0:
print("\nOur fleet is victorious.")
ocean.victory()
# Ask if the player wants another game
repeat = input("\nDo you want a rematch? ").lower()
# If the player doesn't want to play again quit the program
if repeat in ["no","n"]:
print("Thanks for playing")
break