I wrote some code for a Python homework assignment and it's running fine in Mu-editor and other IDE's, but not in the Atom editor (using the Hydrogen package to run it), where it gives me an unexpected NameError. I've already posted this issue in the Atom Github, but I'm not getting a response. The code:
theBoard = {'top-L': ' ', 'top-M': ' ', 'top-R': ' ',
'mid-L': ' ', 'mid-M': ' ', 'mid-R': ' ',
'low-L': ' ', 'low-M': ' ', 'low-R': ' '}
def printBoard(board):
print(board['top-L'] + '|' + board['top-M'] + '|' + board['top-R'])
print('-+-+-')
print(board['mid-L'] + '|' + board['mid-M'] + '|' + board['mid-R'])
print('-+-+-')
print(board['low-L'] + '|' + board['low-M'] + '|' + board['low-R'])
turn = 'X'
for i in range(9):
printBoard(theBoard)
print('Turn for ' + turn + '. Move on which space?')
move = input()
theBoard[move] = turn
if turn == 'X':
turn = 'O'
else:
turn = 'X'
printBoard(theBoard)
The NameError I get when trying to run this code:
----> 1 printBoard(theBoard)
NameError: name 'theBoard' is not defined
It throws this error in line 1 of the for loop printBoard(theBoard)
I've played around with formatting and shortening theBoard in case the formatting of the dictionary was the problem, but that did not change anything. theBoard is stored in the global scope (right?), so printBoard should be able to call it in the for loop.
Does anybody have an idea why this is happening?
Related
total begginner here.
I am trying to write a complete tic-tac-toe program based on the automate boring stuff exercise. I got it working before like this:
theBoard = {'top-L': ' ', 'top-M': ' ', 'top-R': ' ',
'mid-L': ' ', 'mid-M': ' ', 'mid-R': ' ',
'low-L': ' ', 'low-M': ' ', 'low-R': ' '}
def printBoard(board): #function to print board
print(board['top-L'] + '|' + board['top-M'] + '|' + board['top-R'])
print('-+-+-')
print(board['mid-L'] + '|' + board['mid-M'] + '|' + board['mid-R'])
print('-+-+-')
print(board['low-L'] + '|' + board['low-M'] + '|' + board['low-R'])
print('''
Hi! This is my tic-tac-toe text based game.
To make your move, write where you want to play:
top-L top-M top-R
mid-L mid-M mid-R
low-L low-M low-R
''')
turn= 'X' #starting
while True:
printBoard(theBoard)
print(f'Turn for {turn}. Where will you play?')
try:
move = input()
if theBoard[move] == ' ':
theBoard[move] = turn
if turn == 'X':
turn = 'O'
else:
turn = 'X'
else:
print('That move is not possible!')
continue
except KeyError:
print('''Wrong input.
To make your move, write where you want to play:
top-L top-M top-R
mid-L mid-M mid-R
low-L low-M low-R
''')
continue
if ((theBoard['top-L']==theBoard['top-M']==theBoard['top-R']) and theBoard['top-L']!=' ')\
or ((theBoard['mid-L']==theBoard['mid-M']==theBoard['mid-R']) and theBoard['mid-R']!=' ')\
or ((theBoard['low-L']==theBoard['low-M']==theBoard['low-R']) and theBoard['low-L']!=' ')\
or ((theBoard['top-L']==theBoard['mid-M']==theBoard['low-R']) and theBoard['top-L']!=' ')\
or ((theBoard['low-L']==theBoard['mid-M']==theBoard['top-R']) and theBoard['low-L']!=' ')\
or ((theBoard['top-L']==theBoard['mid-L']==theBoard['low-L']) and theBoard['top-L']!=' ')\
or ((theBoard['top-M']==theBoard['mid-M']==theBoard['low-M']) and theBoard['top-M']!=' ')\
or ((theBoard['top-R']==theBoard['mid-R']==theBoard['low-R']) and theBoard['top-R']!=' '):
break
if turn == 'X':
turn = 'O'
else:
turn = 'X'
print(f'Good Job {turn}, you won!')
This worked well and i turned to codereview for some improvements.
I stored the strings 'X' and 'O' as I discovered that those were considered magic strings and make my code less clean.
Next, I wanted to store all the win conditions in a variable called conditions. But when I do this my program will now not get out of the loop when I get a winning move. Why could this be?
theBoard = {'top-L': ' ', 'top-M': ' ', 'top-R': ' ',
'mid-L': ' ', 'mid-M': ' ', 'mid-R': ' ',
'low-L': ' ', 'low-M': ' ', 'low-R': ' '}
def printBoard(board):
print(board['top-L'] + '|' + board['top-M'] + '|' + board['top-R'])
print('-+-+-')
print(board['mid-L'] + '|' + board['mid-M'] + '|' + board['mid-R'])
print('-+-+-')
print(board['low-L'] + '|' + board['low-M'] + '|' + board['low-R'])
conditions = (((theBoard['top-L'] == theBoard['top-M'] == theBoard['top-R']) and theBoard['top-L'] != ' ') \
or ((theBoard['mid-L'] == theBoard['mid-M'] == theBoard['mid-R']) and theBoard['mid-R'] != ' ') \
or ((theBoard['low-L'] == theBoard['low-M'] == theBoard['low-R']) and theBoard['low-L'] != ' ') \
or ((theBoard['top-L'] == theBoard['mid-M'] == theBoard['low-R']) and theBoard['top-L'] != ' ') \
or ((theBoard['low-L'] == theBoard['mid-M'] == theBoard['top-R']) and theBoard['low-L'] != ' ') \
or ((theBoard['top-L'] == theBoard['mid-L'] == theBoard['low-L']) and theBoard['top-L'] != ' ') \
or ((theBoard['top-M'] == theBoard['mid-M'] == theBoard['low-M']) and theBoard['top-M'] != ' ') \
or ((theBoard['top-R'] == theBoard['mid-R'] == theBoard['low-R']) and theBoard['top-R'] != ' '))
print('''
Hi! This is my tic-tac-toe text based game.
To make your move, write where you want to play:
top-L top-M top-R
mid-L mid-M mid-R
low-L low-M low-R
''')
playerX = 'X'
playerO = 'O'
turn= playerX
while True:
printBoard(theBoard)
print(f'Turn for {turn}. Where will you play?')
try:
move = input()
if theBoard[move] == ' ':
theBoard[move] = turn
if turn == playerX:
turn = player0
else:
turn = playerX
else:
print('That move is not possible!')
continue
except KeyError:
print('''Wrong input.
To make your move, write where you want to play:
top-L top-M top-R
mid-L mid-M mid-R
low-L low-M low-R
''')
continue
if conditions == True:
printBoard(theBoard)
break
if turn == playerX:
turn = player0
else:
turn = playerX
print(f'Good Job {turn}, you won!')
That is because conditions is a bool value. It is calculated when it is set. That is to say - it not a function that makes its computations when it is called. In your case conditions is set to False and it will remain to be False. It is a constant.
Wrap it in a function like this:
def check():
conditions = (((theBoard['top-L'] == theBoard['top-M'] == theBoard['top-R']) and theBoard['top-L'] != ' ') \
or ((theBoard['mid-L'] == theBoard['mid-M'] == theBoard['mid-R']) and theBoard['mid-R'] != ' ') \
or ((theBoard['low-L'] == theBoard['low-M'] == theBoard['low-R']) and theBoard['low-L'] != ' ') \
or ((theBoard['top-L'] == theBoard['mid-M'] == theBoard['low-R']) and theBoard['top-L'] != ' ') \
or ((theBoard['low-L'] == theBoard['mid-M'] == theBoard['top-R']) and theBoard['low-L'] != ' ') \
or ((theBoard['top-L'] == theBoard['mid-L'] == theBoard['low-L']) and theBoard['top-L'] != ' ') \
or ((theBoard['top-M'] == theBoard['mid-M'] == theBoard['low-M']) and theBoard['top-M'] != ' ') \
or ((theBoard['top-R'] == theBoard['mid-R'] == theBoard['low-R']) and theBoard['top-R'] != ' '))
return conditions
And call this function instead of conditions in the if statement:
if check() == True:
printBoard(theBoard)
break
Sorry it may be very basic stuff. I'm new to python and cant put my finger on what's wrong here
I have this dictionary:
Board = {'top-L': ' ', 'top-M': ' ', 'top-R': ' ',
'mid-L': ' ', 'mid-M': ' ', 'mid-R': ' ',
'low-L': ' ', 'low-M': ' ', 'low-R': ' '}
I'm trying to write a function that accepts a number 1-9, convert it to dict keys representing these places and return True if value == ' ':
def CheckSpace(Space): # Will return True if space is available
switcher = {
1: 'top-L',
2: 'top-M',
3: 'top-R',
4: 'mid-L',
5: 'mid-M',
6: 'mid-R',
7: 'low-L',
8: 'low-M',
9: 'low-R',
}
return Board.get(switcher) == ''
Error : TypeError: unhashable type: 'dict'
Can someone give me a tip please?
***edit
I guess i can write that function like this:
def CheckSpace(Space):#Will return True if space is available
if space == 1:
place = Board.get('top-L')
if space == 2:
place = Board.get('top-M')
if space == 3:
place = Board.get('top-R')
if space == 4:
place = Board.get('mid-L')
#.... and so on to 9..
return place
But I'm trying to use something equivalent to switch case
Board.get(switcher) == ''
switcher is a dict. Maybe you want Board.get(switcher.get(Space)) == ' '
The .get method accepts a key. You passed in switcher which is a dictionary (dicts are not hashable, hence the error).
Get the key first using .get;
E.g. switcher.get(Space)
And then: Board.get(switcher.get(Space)) == ' '
So I am trying to create a very simple 1-player battleship game in python. Where the computer randomly places its ships in the rows and columns, and the player guesses which row and column a ship is in. My current problem is that my code does that, however it prints the board out each time and also seems to make the choices for the player as well.
import random
#Make board
board = [
[' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' '],
]
# List to refer to columns by letter, since that is how a typical battleship game is
#initiated
letters2Numbers = {
'A': 0,
'B': 1,
'C': 2,
'D': 3,
'E': 4,
}
#Function to ask the user for their board position
def generateShips():
for a in range (0,55):
row = random.randrange(1,6)
column = random.choice(['A','B','C','D','E'])
rowNumber = row
columnNumber = column
return int(row) - 1, letters2Numbers[column]
def askUser():
column = input("column (A to E):")
while column not in "ABCDE":
print("That column is wrong! It should be A, B, C, D or E")
column = input("column (A to E):")
row = input("row (1 to 5):")
while row not in "12345":
print("That row is wrong! it should be 1, 2, 3, 4 or 5")
row = input("row (1 to 5):")
return int(row) - 1, letters2Numbers[column]
def printBoard(board):
# Shows the board, one row at a time, labelled
print(" A B C D E")
print(" +-+-+-+-+-+")
rowNumber = 1
for row in board:
print("%d|%s|" % (rowNumber, "|".join(row)))
print(" +-+-+-+-+-+")
rowNumber = rowNumber + 1
# Now clear the screen, and the other player starts guessing
print("\n"*50)
guessesBoard = [
[' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' '],
]
# Keep playing until we have 5 right guesses
guesses = 0
while guesses < 5:
print("Guess a battleship location")
rowNumber, columnNumber = askUser()
if guessesBoard[rowNumber][columnNumber] != ' ':
print("You have already guessed that place!")
continue
# Check that there are no repeats
if board[rowNumber][columnNumber] == 'X':
print("HIT!")
guessesBoard[rowNumber][columnNumber] = 'X'
guesses = guesses + 1
else:
guessesBoard[rowNumber][columnNumber] = '.'
print("MISS!")
printBoard(guessesBoard)
print("GAME OVER!")
This is my code so far. If you run it, you'll see the error I'm talking about.
You never ask the player for choices; you print a message suggesting that you're about to do so, but then your code charges ahead and uses the row and column from ship generation. Nowhere in your program do you accept user input.
You want to use function input() rather than random.SOMETHING. Then your input will not be choosen by PC.
Then to convert user input (which always returns a string) to a number, you can use something like:
a = input("perhaps a number: ")
if not a.isdigit():
raise ValueError("I said number :(")
a = int(a)
You probably don't want to raise the error, I am just demonstrating what you can build on.
I am waiting for further development of this question. :)
I am trying to create a simple board in a draw_board definition that will use size and several coordinates where I will place 1 character length characters in specified coordinates. I am in the beginning stages and want to just simply create the board itself using a 2d array.
This method below works when I change individual elements :
board = [['','','',''], ['','','',''], ['', '', '', ''], ['','','','']]
board[0][0] = 'a'
print(' 0 1 2 3')
print('0 ' + board[0][0] + ' ' + board[0][1] + ' ' + board[0][2] + ' ' + board[0][3])
print('1 ' + board[1][0] + ' ' + board[1][1] + ' ' + board[1][2] + ' ' + board[1][3])
print('2 ' + board[2][0] + ' ' + board[2][1] + ' ' + board[2][2] + ' ' + board[2][3])
print('3 ' + board[3][0] + ' ' + board[3][1] + ' ' + board[3][2] + ' ' + board[3][3])
However, I would not be able to change the size by just a variable and would need to edit the initialization of the board myself.
This method below is better and would work because I could easily change the size variable and get any size board I want...
size = 4
board = [['']*size]*size
board[0][0] = 'a'
print(' 0 1 2 3')
print('0 ' + board[0][0] + ' ' + board[0][1] + ' ' + board[0][2] + ' ' + board[0][3])
print('1 ' + board[1][0] + ' ' + board[1][1] + ' ' + board[1][2] + ' ' + board[1][3])
print('2 ' + board[2][0] + ' ' + board[2][1] + ' ' + board[2][2] + ' ' + board[2][3])
print('3 ' + board[3][0] + ' ' + board[3][1] + ' ' + board[3][2] + ' ' + board[3][3])
However, when I implement board[0][0] = 'a', it changes the entire column to 'a', which is not what I want. Any suggestions of how I could change this second method to make it work for just the desired coordinate?
Use
board = [['' for i in range(size)] for j in range(size)]
this is because when you use the * operator, you're creating more references to the same object, not more copies.
Here's more in depth information about the strategy used above, called list comprehensions
if group == 10G2:
file_name='10G2 Scores.txt'
fileObject = open(file_Name,'wb')
pickle.dump(+str(name) + ' got ' + str(finalscore) + ' percent from ' + str(totalquestions) + ' question(s), this is ' + str(score) + ' out of ' + str(totalquestions) + '.') ,fileObject)
fileObject.close()
This is part of a maths quiz and I am trying to write scores to a text file. It says there is a syntax error on the 10G2?
All of the variables have been defined and I have imported pickle
Thanks in advance. BTW, I'm doing GCSE computing.
This is my whole code:
#Maths Quiz
noq=0
score=0
import math
import pickle
import random
import time
import pickle
def write(name, finalscore, totalquestions, score, file_Object):
pickle.dump ((str(name) + ' got ' + str(finalscore) + ' percent from ' + str(totalquestions) + ' question(s), this is ' + str(score) + ' out of ' + str(totalquestions) + '.') ,file_Object)
return
group=input("What mentor group are you in?: ")
name=input("What is your name?: ")
print ("Hello " + name + ". How many questions would you like to do?:")
totalquestions=int(input(" "))
for i in range (0,(totalquestions)):
noq=noq+1
print ("Question " +str(noq))
numberone=random.randint(1, 10)
numbertwo=random.randint(1, 10)
answer=int(numberone) + int(numbertwo)
print ("What is " +str(numberone) + "+" + str(numbertwo) + "?:")
uanswer=int(input(""))
if answer==uanswer:
print("That is correct!!!")
score=score +1
print ("Your score is.....")
time.sleep(0.5)
print("" +str(score) + " out of " + str(i+1))
time.sleep(1)
else:
print ("Sorry, that is wrong!!!")
score=score
print ("Your score is.....")
time.sleep(0.5)
print ("" +str(score) + " out of " + str(i+1))
time.sleep(1)
time.sleep(0.5)
print ("Your final score is.....")
finalscore=score/totalquestions
finalscore=finalscore*100
time.sleep(3)
print ("" +str(finalscore)+ " percent")
#file write###############################################################################
if group == 10G2:
file_name='10G2 Scores.txt'
fileObject= open(file_Name,'w')
pickle.dump((+str(name) + ' got ' + str(finalscore) + ' percent from ' + str(totalquestions) + ' question(s), this is ' + str(score) + ' out of ' + str(totalquestions) + '.') ,fileObject)
fileObject.close()
elif group == 10G1:
file_name='10G1 Scores.txt'
fileObject = open(file_Name,'w')
pickle.dump((+str(name) + ' got ' + str(finalscore) + ' percent from ' + str(totalquestions) + ' question(s), this is ' + str(score) + ' out of ' + str(totalquestions) + '.') ,fileObject)
fileObject.close()
elif group == 10G3:
file_name='10G3 Scores.txt'
fileObject = open(file_Name,'w')
pickle.dump((+str(name) + ' got ' + str(finalscore) + ' percent from ' + str(totalquestions) + ' question(s), this is ' + str(score) + ' out of ' + str(totalquestions) + '.') ,fileObject)
fileObject.close()
elif group == 10G4:
file_name='10G4 Scores.txt'
fileObject = open(file_Name,'w')
write ()
fileObject.close()
elif group == 10G5:
file_name='10G5 Scores.txt'
fileObject = open(file_Name,'w')
write ()
fileObject.close()
elif group == 10G6:
file_name='10G6 Scores.txt'
fileObject = open(file_Name,'w')
write ()
fileObject.close()
elif group == 10G7:
file-name='10G7 Scores.txt'
fileObject = open(file_Name,'w')
write ()
fileObject.close()
Try changing this line
if group == 10G2:
to:
if group == '10G2':