Copied functions from Jupyter notebook to salvo.py. Started adding interactive player interface.

This commit is contained in:
Todd Kaiser
2021-03-13 16:17:49 -07:00
parent 540b6b763a
commit e707846091
2 changed files with 273 additions and 61 deletions

View File

@@ -24,7 +24,7 @@
"cells": [
{
"cell_type": "code",
"execution_count": 715,
"execution_count": 727,
"metadata": {},
"outputs": [],
"source": [
@@ -33,7 +33,7 @@
},
{
"cell_type": "code",
"execution_count": 716,
"execution_count": 728,
"metadata": {},
"outputs": [],
"source": [
@@ -57,7 +57,7 @@
},
{
"cell_type": "code",
"execution_count": 717,
"execution_count": 729,
"metadata": {},
"outputs": [],
"source": [
@@ -80,14 +80,14 @@
},
{
"cell_type": "code",
"execution_count": 718,
"execution_count": 730,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"8 4\n"
"5 3\n"
]
}
],
@@ -98,7 +98,7 @@
},
{
"cell_type": "code",
"execution_count": 719,
"execution_count": 731,
"metadata": {},
"outputs": [],
"source": [
@@ -155,14 +155,14 @@
},
{
"cell_type": "code",
"execution_count": 720,
"execution_count": 732,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"BATTLESHIP 5 [(9, 2), (8, 3), (7, 4), (6, 5), (5, 6)]\nCRUISER 3 [(3, 8), (2, 9), (1, 10)]\nDESTROYER<A> 2 [(3, 5), (3, 6)]\nDESTROYER<B> 2 [(6, 5), (7, 4)]\n"
"BATTLESHIP 5 [(10, 2), (10, 3), (10, 4), (10, 5), (10, 6)]\nCRUISER 3 [(9, 4), (8, 4), (7, 4)]\nDESTROYER<A> 2 [(2, 5), (1, 5)]\nDESTROYER<B> 2 [(7, 8), (7, 9)]\n"
]
}
],
@@ -175,7 +175,7 @@
},
{
"cell_type": "code",
"execution_count": 721,
"execution_count": 733,
"metadata": {},
"outputs": [],
"source": [
@@ -186,7 +186,7 @@
},
{
"cell_type": "code",
"execution_count": 722,
"execution_count": 734,
"metadata": {},
"outputs": [
{
@@ -221,7 +221,7 @@
},
{
"cell_type": "code",
"execution_count": 723,
"execution_count": 735,
"metadata": {},
"outputs": [],
"source": [
@@ -232,25 +232,14 @@
},
{
"cell_type": "code",
"execution_count": 724,
"execution_count": 736,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"DESTROYER<B> 2 [(1, 7), (2, 6), (3, 5), (4, 4), (5, 3)]\n",
" 1 2 3 4 5 6 7 8 9 10\n",
" 1 0 \n",
" 2 0 \n",
" 3 0 \n",
" 4 0 \n",
" 5 0 \n",
" 6 \n",
" 7 \n",
" 8 \n",
" 9 \n",
"10 \n"
"DESTROYER<B> 2 [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]\n 1 2 3 4 5 6 7 8 9 10\n 1 0 \n 2 0 \n 3 0 \n 4 0 \n 5 0 \n 6 \n 7 \n 8 \n 9 \n10 \n"
]
}
],
@@ -265,14 +254,24 @@
},
{
"cell_type": "code",
"execution_count": 725,
"execution_count": 737,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
" 1 2 3 4 5 6 7 8 9 10\n 1 1 0 \n 2 1 0 \n 3 1 0 \n 4 0 \n 5 2 0 \n 6 2 \n 7 3 3 \n 8 \n 9 \n10 \n"
" 1 2 3 4 5 6 7 8 9 10\n",
" 1 \n",
" 2 1 \n",
" 3 1 2 \n",
" 4 1 2 \n",
" 5 0 \n",
" 6 0 \n",
" 7 0 \n",
" 8 0 \n",
" 9 0 3 \n",
"10 3 \n"
]
}
],
@@ -305,14 +304,14 @@
},
{
"cell_type": "code",
"execution_count": 726,
"execution_count": 738,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"[(4, 4), (2, 8), (10, 6), (2, 4), (10, 7)]\n"
"[(4, 1), (3, 6), (6, 10), (10, 6), (4, 5)]\n"
]
}
],

View File

@@ -1,6 +1,12 @@
import re
import random
###################
#
# static variables
#
###################
# declare static variables
BOARD_WIDTH = 10
BOARD_HEIGHT = 10
@@ -9,17 +15,64 @@ SHIPS = [("BATTLESHIP", 5),
("DESTROYER<A>", 2),
("DESTROYER<B>", 2)]
VALID_MOVES = [[-1, 0],
[-1, 1],
[0, 1],
[1, 1],
[1, 0],
[1, -1],
[0, -1],
[1, -1]]
VALID_MOVES = [[-1, 0], # North
[-1, 1], # North East
[0, 1], # East
[1, 1], # South East
[1, 0], # South
[1, -1], # South West
[0, -1], # West
[-1, -1]] # North West
COORD_REGEX = '[ \t]{0,}(-?[0-9]{1,3})[ \t]{0,},[ \t]{0,}(-?[0-9]{1,2})'
####################
#
# global variables
#
####################
# array of BOARD_HEIGHT arrays, BOARD_WIDTH in length,
# representing the human player and computer
player_board = []
computer_board = []
# array representing the coordinates
# for each ship for player and computer
# array is in the same order as SHIPS
player_ship_coords = []
computer_ship_coords = []
# keep track of the turn
current_turn = 0
# flag indicating if computer's shots are
# printed out during computer's turn
print_computer_shots = False
####################
#
# game functions
#
####################
# random number functions
#
# seed the random number generator
random.seed()
# random_x_y
#
# generate a valid x,y coordinate on the board
# returns: x,y
# x: integer between 1 and BOARD_HEIGHT
# y: integer between 1 and BOARD WIDTH
def random_x_y():
x = random.randrange(1, BOARD_WIDTH+1)
y = random.randrange(1, BOARD_HEIGHT+1)
return (x, y)
# input_coord
#
@@ -51,32 +104,192 @@ def input_coord():
return x, y
# input_ship_coords
#
# ask the user for coordinates for each
# ship on their board. uses input_coord()
# to read each coord.
# returns an array of arrays, one array for
# each ship's coordinates, which is an array
# of (x,y) sets.
def input_ship_coords():
print("ENTER COORDINATES FOR...")
# TODO: add an optional starting coordinate for testing
# purposes
def generate_ship_coordinates(ship):
# randomly generate starting x,y coordinates
start_x, start_y = random_x_y()
coords = []
for ship in SHIPS:
print(ship[0])
list = []
for i in range(ship[1]):
x, y = input_coord()
list.append((x, y))
coords.append(list)
# using starting coordinates and the ship type,
# generate a vector of possible directions the ship
# could be placed. directions are numbered 0-7 along
# points of the compass (N, NE, E, SE, S, SW, W, NW)
# clockwise. a vector of valid directions where the
# ship does not go off the board is determined
ship_len = SHIPS[ship][1] - 1
dirs = [False for x in range(8)]
dirs[0] = (start_x - ship_len) >= 1
dirs[2] = (start_y + ship_len) <= BOARD_WIDTH
dirs[1] = dirs[0] and dirs[2]
dirs[4] = (start_x + ship_len) <= BOARD_HEIGHT
dirs[3] = dirs[2] and dirs[4]
dirs[6] = (start_y - ship_len) >= 1
dirs[5] = dirs[4] and dirs[6]
dirs[7] = dirs[6] and dirs[0]
directions = [p for p in range(len(dirs)) if dirs[p]]
# using the vector of valid directions, pick a
# random direction to place the ship
dir_idx = random.randrange(len(directions))
direction = directions[dir_idx]
# using the starting x,y, direction and ship
# type, return the coordinates of each point
# of the ship. VALID_MOVES is a staic array
# of coordinate offsets to walk from starting
# coordinate to the end coordinate in the
# chosen direction
ship_len = SHIPS[ship][1] - 1
d_x = VALID_MOVES[direction][0]
d_y = VALID_MOVES[direction][1]
coords = [(start_x, start_y)]
x_coord = start_x
y_coord = start_y
for i in range(ship_len):
x_coord = x_coord + d_x
y_coord = y_coord + d_y
coords.append((x_coord, y_coord))
return coords
# print out the title 'screen'
print('{0:>38}'.format("SALVO"))
print('{0:>57s}'.format("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"))
print('\n\n')
# create_blank_board
#
# helper function to create a game board
# that is blank
def create_blank_board():
return [[None for y in range(BOARD_WIDTH)]
for x in range(BOARD_HEIGHT)]
def print_board(board):
# print board header (column numbers)
print(' ', end='')
for z in range(BOARD_WIDTH):
print(f'{z+1:3}', end='')
print('')
for x in range(len(board)):
print(f'{x+1:2}', end='')
for y in range(len(board[x])):
if(board[x][y] is None):
print(f"{' ':3}", end='')
else:
print(f"{board[x][y]:3}", end='')
print('')
# place_ship
#
# place a ship on a given board. updates
# the board's row,column value at the given
# coordinates to indicate where a ship is
# on the board.
#
# inputs: board - array of BOARD_HEIGHT by BOARD_WIDTH
# coords - array of sets of (x,y) coordinates of each
# part of the given ship
# ship - integer repreesnting the type of ship (given in SHIPS)
def place_ship(board, coords, ship):
for coord in coords:
board[coord[0]-1][coord[1]-1] = ship
# NOTE: A little quirk that exists here and in the orginal
# game: Ships are allowed to cross each other!
# For example: 2 destroyers, length 2, one at
# [(1,1),(2,2)] and other at [(2,1),(1,2)]
def generate_board():
board = create_blank_board()
ship_coords = []
for ship in range(len(SHIPS)):
placed = False
coords = []
while not placed:
coords = generate_ship_coordinates(ship)
clear = True
for coord in coords:
if board[coord[0]-1][coord[1]-1] is not None:
clear = False
break
if clear:
placed = True
place_ship(board, coords, ship)
ship_coords.append(coords)
return board, ship_coords
# initialize
#
# function to initialize global variables used
# during game play.
def initialize_game():
# initialize the global player and computer
# boards
global player_board
player_board = create_blank_board()
# generate the ships for the computer's
# board
global computer_board
global computer_ship_coords
computer_board, computer_ship_coords = generate_board()
# print out the title 'screen'
print('{0:>38}'.format("SALVO"))
print('{0:>57s}'.format("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"))
print('\n\n')
######################
#
# main game flow
#
######################
# initialize the player and computer
# boards
initialize_game()
# ask the player for ship coordinates
print("ENTER COORDINATES FOR...")
ship_coords = []
for ship in SHIPS:
print(ship[0])
list = []
for i in range(ship[1]):
x, y = input_coord()
list.append((x, y))
ship_coords.append(list)
# add ships to the user's board
for ship in range(len(SHIPS)):
place_ship(player_board, ship_coords[ship], ship)
# see if the player wants the computer's ship
# locations printed out and if the player wants to
# start
input_loop = True
player_start = "YES"
while input_loop:
player_start = input("DO YOU WANT TO START? ")
if player_start == "WHERE ARE YOUR SHIPS?":
for ship in range(len(SHIPS)):
print(SHIPS[ship][0])
coords = computer_ship_coords[ship]
for coord in coords:
x = coord[0]
y = coord[1]
print('{0:2}'.format(x), '{0:2}'.format(y))
else:
input_loop = False
# ask the player if they want the computer's shots
# printed out each turn
see_computer_shots = input("DO YOU WANT TO SEE MY SHOTS? ")
if see_computer_shots.lower() == "yes":
print_computer_shots = True
# ask the user for ship coordinates
coords = input_ship_coords()