Python Battleship Game, Recursive Malfunction
<p>apologies in advance for the data dump. I'm recreating the Battleship game with Python. I'm having trouble with the <code>def battleship</code> function where the computer and user try to guess each other's coordinates. The computer has a <code>e/x</code>probability of guessing the user's coordinates correctly, where e is the number of ships left, and x is the number of unknown coordinates. The problem is, in the case that the user misses, how can I access local variable <code>x</code>, which is assigned a value when the user scores a hit? Since this is a recursive function, <code>x</code> is not defined if the user misses. I would still like the computer to guess the player's battleship location when the user misses. However, the error message I get reads: <code>local variable 'x' referenced before assignment</code></p>

<p>Thanks for your patience. Seems like there should be a simple solution out there. </p>

<pre><code>import random
import sys

globalValue=0 #for length of hitlist
loopcondition=True
compdestruction=0 #keep track of number of destroyed ships
userdestruction=0
destroyedships=[];
hitlist=[]; #a global variable
 #to end the program
you=[];
youhitship=[];

class Battleship(object):
    """ Ship object container. A game where the user tries to destroy the enemy's ships User tries to guess computer's position x and y """
    def __init__(self, size, numberships,position_x,position_y):
        self.position_x=position_x
        self.position_y=position_y
        self.numberships=numberships
        self.size = size

    def plotships(self,numberships):
        """input is integer coordinates for ships and output is an array of arrays with battleship locations CREATES THE HITLIST DONT REPEAT"""
        while len(hitlist)&lt;numberships:
            r=Battleship.randomness(self)
            if r not in hitlist:
                hitlist.append(r)
        originalhitlist=len(hitlist)
        global globalValue
        globalValue+=originalhitlist


    def destroy(self):
        """ Destroys the ship's point supplied if it contains it """
        compChoose=Battleship.randomness(self) #computer's attak pair
        print('computer choice is '+str(compChoose))
        ship=[self.position_x,self.position_y]
        print('Your Turn...')
        if  ship in hitlist:
            print('Direct hit Captain')
            global userdestruction
            hitlist.remove(ship)
            userdestruction+=1
            CompWreck=GameBoard(self.size)
            CompWreck.update(ship,self.size, destroyedships) #empty (at first) lists with coordinates of up-to-date list of destroyed ships
        else:
            print('Drat! missed!')
        print('\nComps Turn')
        if compChoose in you:
            print('Kabloom. Your ships sunk.')
            global compdestruction
            you.remove(compChoose)
            compdestruction+=1
            YourWreck=GameBoard(self.size) #create an instance of GameBoard
            YourWreck.update(ship,self.size,youhitship)
        else:
            print('Yay! The computer missed!\n')


    def randomness(self):
        """random coordinates for computer firing and computer ship location"""
        rand_x=random.choice(range(self.size))
        rand_y=random.choice(range(self.size))
        randcoord=[rand_x,rand_y]
        return randcoord

class GameBoard(object):
    """ The container for the ships """
    def __init__(self, size):
        """Initialize clean GameBoard depending on size, etc """
        self.size=size
        self.destroyed = 'x' # representation for destroyed area
        self.clear = '-' # representation for clear water

    def printBoard(self,destroytheseships):
        """ Print the current gameboard state"""
        global compdestruction
        global userdestruction
        global globalValue
        global loopcondition
        graf='' #printed board
        x=-1 #so the first row is 0, within the range of hitlist coordinates defined in Battleship.plotships(self)
        for row in range(self.size): #for every row inside the first set of brackets
            x+=1 #x,y pairs mark the possible ship locations
            graf+='\n'
            y=-1 #so the first column is 0 
            for column in range(self.size):
                y+=1
                if [x,y] in destroytheseships:                    
                    graf+=self.destroyed
                else:
                    graf+=self.clear
        print(graf)

        if userdestruction == globalValue:
            print('You Win!')
            sys.exit('Game Over')

        if compdestruction&gt;=originalyou:
            print('You Lose'  )
            sys.exit('Game Over')

    def update(self,ship,size,witchlist):#It matter whether it's computer or user's turn. WITCHLIST  defines which list you're choosing from
        """ Updates the gameboard according to updated ship """
        witchlist.append(ship)
        newboard=GameBoard(size) #create a new instance with the same sized board
        newboard.printBoard(witchlist)

#Game Interface do it once
size=int(input('Gameboard size'))
numberships=int(input('Waiting for Number of enemy ships'))
b=Battleship(size,numberships,0,0)
b.plotships(numberships) #create a hitlist and returns the original length of hitlist array

for i in range(numberships): #create list of your ships 
    you_x=int(input('Please enter a X coordinate for your ship'))
    you_y=int(input('Please enter a Y coordinate for your ship'))
    if ((you_x not in range(0,size)) or (you_y not in range(0,size))):
        print('please chooose a different pair of coordinates within board boundaries\n')
        continue
    your_xy=[you_x,you_y]
    you.append(your_xy)
    originalyou=len(you)
while loopcondition==True: #take another turn as long as all the ships are not destroyed
    ex=int(input('Waiting for attack X coordinate'))
    why=int(input('Waiting for attack Y coordinate'))
    if ((ex not in range(0,size)) or (why not in range(0,size))):
        print('please chooose a different pair of coordinates within board boundaries\n')
        continue
    b=Battleship(size,numberships,ex,why)
    b.destroy()
</code></pre>

<p>Your <code>if</code> statement means that <code>x</code> isn't calculated on a miss. You will have to add some more logic inside the else statement to work out what <code>x</code> should be. A starting point would be to duplicate the block of code that draws a graph but just keep the lines that modify the value of <code>x</code> (also initialize <code>x</code> as <code>0</code>).</p>

python recursion