Files
basic-computer-games/77 Salvo/python/salvo.ipynb

337 lines
9.7 KiB
Plaintext

{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3-final"
},
"orig_nbformat": 2,
"kernelspec": {
"name": "python3",
"display_name": "Python 3",
"language": "python"
}
},
"nbformat": 4,
"nbformat_minor": 2,
"cells": [
{
"cell_type": "code",
"execution_count": 727,
"metadata": {},
"outputs": [],
"source": [
"import random"
]
},
{
"cell_type": "code",
"execution_count": 728,
"metadata": {},
"outputs": [],
"source": [
"BOARD_WIDTH = 10\n",
"BOARD_HEIGHT = 10\n",
"\n",
"SHIPS = [ (\"BATTLESHIP\", 5),\n",
" (\"CRUISER\", 3),\n",
" (\"DESTROYER<A>\", 2),\n",
" (\"DESTROYER<B>\", 2) ]\n",
" \n",
"VALID_MOVES = [[-1, 0],\n",
" [-1, 1],\n",
" [ 0, 1],\n",
" [ 1, 1],\n",
" [ 1, 0],\n",
" [ 1,-1],\n",
" [ 0,-1],\n",
" [-1,-1]]"
]
},
{
"cell_type": "code",
"execution_count": 729,
"metadata": {},
"outputs": [],
"source": [
"# random number functions\n",
"#\n",
"# seed the random number generator\n",
"random.seed()\n",
"\n",
"# random_x_y\n",
"#\n",
"# generate a valid x,y coordinate on the board\n",
"# returns: x,y\n",
"# x: integer between 1 and BOARD_HEIGHT\n",
"# y: integer between 1 and BOARD WIDTH\n",
"def random_x_y():\n",
" x = random.randrange(1,BOARD_WIDTH+1)\n",
" y = random.randrange(1,BOARD_HEIGHT+1)\n",
" return (x,y)"
]
},
{
"cell_type": "code",
"execution_count": 730,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"5 3\n"
]
}
],
"source": [
"x,y = random_x_y()\n",
"print (x,y)"
]
},
{
"cell_type": "code",
"execution_count": 731,
"metadata": {},
"outputs": [],
"source": [
"# TODO: add an optional starting coordinate for testing\n",
"# purposes\n",
"def generate_ship_coordinates(ship):\n",
" \n",
" # randomly generate starting x,y coordinates\n",
" start_x, start_y = random_x_y()\n",
"\n",
" # using starting coordinates and the ship type,\n",
" # generate a vector of possible directions the ship \n",
" # could be placed. directions are numbered 0-7 along\n",
" # points of the compass (N, NE, E, SE, S, SW, W, NW)\n",
" # clockwise. a vector of valid directions where the\n",
" # ship does not go off the board is determined\n",
" ship_len = SHIPS[ship][1] - 1\n",
" dirs = [False for x in range(8)]\n",
" dirs[0] = (start_x - ship_len) >=1\n",
" dirs[2] = (start_y + ship_len) <= BOARD_WIDTH\n",
" dirs[1] = dirs[0] and dirs[2]\n",
" dirs[4] = (start_x + ship_len) <= BOARD_HEIGHT\n",
" dirs[3] = dirs[2] and dirs[4]\n",
" dirs[6] = (start_y - ship_len) >= 1\n",
" dirs[5] = dirs[4] and dirs[6]\n",
" dirs[7] = dirs[6] and dirs[0]\n",
" directions = [p for p in range(len(dirs)) if dirs[p]]\n",
"\n",
" # using the vector of valid directions, pick a\n",
" # random direction to place the ship\n",
" dir_idx = random.randrange(len(directions))\n",
" direction = directions[dir_idx]\n",
"\n",
" # using the starting x,y, direction and ship\n",
" # type, return the coordinates of each point \n",
" # of the ship. VALID_MOVES is a staic array\n",
" # of coordinate offsets to walk from starting\n",
" # coordinate to the end coordinate in the \n",
" # chosen direction\n",
" ship_len = SHIPS[ship][1] - 1\n",
" d_x = VALID_MOVES[direction][0]\n",
" d_y = VALID_MOVES[direction][1]\n",
"\n",
" coords = [(start_x,start_y)]\n",
" x_coord = start_x\n",
" y_coord = start_y\n",
" for i in range(ship_len):\n",
" x_coord = x_coord + d_x\n",
" y_coord = y_coord + d_y\n",
" coords.append((x_coord,y_coord))\n",
" return coords\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 732,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"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"
]
}
],
"source": [
"\n",
"for ship in range(len(SHIPS)):\n",
" coords = generate_ship_coordinates(ship)\n",
" print(f'{SHIPS[ship][0]:15}',f'{SHIPS[ship][1]:2}',coords)"
]
},
{
"cell_type": "code",
"execution_count": 733,
"metadata": {},
"outputs": [],
"source": [
"def create_blank_board():\n",
" return [ [ None for y in range(BOARD_WIDTH)] \n",
" for x in range(BOARD_HEIGHT)]"
]
},
{
"cell_type": "code",
"execution_count": 734,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
" 1 2 3 4 5 6 7 8 9 10\n 1 \n 2 \n 3 \n 4 \n 5 \n 6 \n 7 \n 8 \n 9 \n10 \n"
]
}
],
"source": [
"def print_board(board):\n",
"\n",
" # print board header (column numbers)\n",
" print(' ',end='')\n",
" for z in range(BOARD_WIDTH):\n",
" print(f'{z+1:3}',end='')\n",
" print('')\n",
"\n",
" for x in range(len(board)):\n",
" print(f'{x+1:2}',end='')\n",
" for y in range(len(board[x])):\n",
" if(board[x][y] is None):\n",
" print(f\"{' ':3}\",end='')\n",
" else:\n",
" print(f\"{board[x][y]:3}\",end='')\n",
" print('')\n",
"\n",
"computer_board = create_blank_board()\n",
"print_board(computer_board)"
]
},
{
"cell_type": "code",
"execution_count": 735,
"metadata": {},
"outputs": [],
"source": [
"def place_ship(board,coords,ship):\n",
" for coord in coords:\n",
" board[coord[0]-1][coord[1]-1] = ship"
]
},
{
"cell_type": "code",
"execution_count": 736,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"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"
]
}
],
"source": [
"# test place_ship\n",
"board = create_blank_board()\n",
"coords = generate_ship_coordinates(0)\n",
"print(f'{SHIPS[ship][0]:15}',f'{SHIPS[ship][1]:2}',coords)\n",
"place_ship(board,coords,0)\n",
"print_board(board)"
]
},
{
"cell_type": "code",
"execution_count": 737,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
" 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"
]
}
],
"source": [
"# NOTE: A little quirk that exists here and in the orginal\n",
"# game: Ships are allowed to cross each other!\n",
"# For example: 2 destroyers, length 2, one at\n",
"# [(1,1),(2,2)] and other at [(2,1),(1,2)]\n",
"\n",
"def generate_board():\n",
" board = create_blank_board()\n",
"\n",
" for ship in range(len(SHIPS)):\n",
" placed = False\n",
" coords = []\n",
" while not placed:\n",
" coords = generate_ship_coordinates(ship)\n",
" clear = True\n",
" for coord in coords:\n",
" if board[coord[0]-1][coord[1]-1] is not None:\n",
" clear = False\n",
" break\n",
" if clear:\n",
" placed = True\n",
" place_ship(board,coords,ship)\n",
" return board\n",
"\n",
"print_board(generate_board())"
]
},
{
"cell_type": "code",
"execution_count": 738,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"[(4, 1), (3, 6), (6, 10), (10, 6), (4, 5)]\n"
]
}
],
"source": [
"def generate_shots(number):\n",
" shots = []\n",
" for i in range(number):\n",
" shots.append(random_x_y())\n",
" return shots\n",
"\n",
"shots = generate_shots(5)\n",
"print(shots)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
]
}