{ "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\", 2),\n", " (\"DESTROYER\", 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 2 [(2, 5), (1, 5)]\nDESTROYER 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 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": [] } ] }