python integer values are equal but if statement does nothing - python

I'm taking a course online to learn python. I am working on a project to code a tic-tac-toe game. I've built this game around a nested list represented by the 3x3 tic-tac-toe grid. Here is the nested list:
grid = [[1,2,3],[4,5,6],[7,8,9]]
I'd like to prompt the user to select a number 1-9 and then replace the selected number in the nested list with either an X or an O depending on which player made the selection.
I can find the value inside the list just fine, and it will print out okay, along with the number that was entered by the user. However, when I try to compare the two values with an if statement, nothing happens. I'd like to just update the nested list value after the if statement but I can't figure out what I'm doing wrong or why the if statement won't fire. I can't get the value to update so I replaced that line with a print statement just to see how it would handle but the line I'm trying to print just gets ignored. Here is the if statement, where p = the number input by the user.
for r in grid:
for c in r:
print str(c) + " / " + str(p) # so I can see the values
if c == p:
print "Winner winner, chicken dinner!"
When I run the code and feed it an integer (in this case 4), I expect to see the chicken dinner line printed out but instead I just get the following:
1 / 4
2 / 4
3 / 4
4 / 4
5 / 4
6 / 4
7 / 4
8 / 4
9 / 4
Why doesn't it recognize that 4 == 4?
UPDATE: I tried sticking the variables in the str() to make sure they were the same type, but I got the same results. Here is the whole code so far:
grid = [['1','2','3'],['4','5','6'],['7','8','9']]
plyr = ("X","O")
turn = 0
def drw_brd():
i = 1
f = turn
for spc in grid:
print " " + spc[0] + " | " + spc[1] + " | " + spc[2] + " "
if i<=2:
print "-----------"
i+=1
print''
print "Player %s (%s's) it's your turn!" %(str(f+1),plyr[turn])
place = input('Cell number to take:')
place_sym(int(place))
check_win()
def check_win():
switch_plyr()
def switch_plyr():
global turn
"""
if turn == 0:
turn = 1
else:
turn = 0
"""
if turn <= 0:
turn = 1
elif turn >= 1:
turn = 0
#print turn
drw_brd()
def place_sym(p):
global turn
global grid
global plyr
print plyr[turn]
for r in grid:
for c in r:
print str(c) + " / " + str(p)
if c == p:
print "Winner winner, chicken dinner!"

The problem is that p is a string, c is an integer. Wherever you are getting your value for p (should look something like)
p = input("enter a number")
you should put
p = int(input("enter a number"))
this should fix your problem
Edit
Not all values were of the same type. Grid defined the numbers as strings,
grid = [['1','2','3'],['4','5','6'],['7','8','9']]
and input was running eval on the entered number, changing its type to an int, which meant the check for p == c returned False, as they were different types

Related

Program to add the squares of numbers in list which have been entered by while-loop

I'm writing a program which should produce an output of something like this:
`Enter an integer (or Q to quit): 1
Enter an integer (or Q to quit): 2
Enter an integer (or Q to quit): 3
Enter an integer (or Q to quit): Q
(1 x 1) + (2 x 2) + (3 x 3) = 14`
So far, I've gotten the display of the equation right, but I can't seem to figure out how to actually get the total of the equation. Currently, the total displays 18 instead of the expected 14.
Here's my code so far:
`int_list = [] # initiate list
while True:
user_input = input("Enter an integer (or Q to quit): ") # get user input
if user_input == "Q": # break loop if user enters Q
break
integer = int(user_input) # convert user_input to an integer to add to list
int_list.append(integer) # add the integers entered to the list
for i in range(0, len(int_list)):
template = ("({0} x {1})".format(int_list[i], int_list[i]))
if i == len(int_list)-1:
trailing = " = "
else:
trailing = " + "
print(template, end="")
print(trailing, end="")
for i in range(0, len(int_list)):
x = (int_list[i]*int_list[i])
add = (x+x)
print(add)`
Any help would be greatly appreciated :))
Your problem exists in the here:
for i in range(0, len(int_list)):
x = (int_list[i]*int_list[i])
add = (x+x)
print(add)
Let us walk through what the code does to get a better understanding of what is going wrong.
With a list of [1, 2, 3] The for loop will iterate three times
On the first iteration, x will be assigned the value 1 because 1 * 1 is 1.
On the second iteration, x will be assigned the value 4 because 2 * 2 is 4. Notice that rather than the two values being added x's value being overwritten
On the third iteration, x will be assigned the value 9 because 3 * 3 is 9. Again the value is being overwritten.
After the loop, the variable add is created with the value x + x, or in our case 9 + 9 which is 18
This is why with the list [1, 2, 3] the value displayed is 18
Now that we have walked through the problem. We can see that the problem is overriding the value in the for loop then doubling the value before displaying it.
To fix these problems we can first remove the doubling giving the following code
for i in range(0, len(int_list)):
x = (int_list[i]*int_list[i])
print(x)
But the program still has the overriding problem so the value of a list [1, 2, 3] would be 9.
To fix this rather than overriding the value of x, let's create a new variable total that will have the result of the loop added to it every iteration rather than being overwritten.
total = 0
for i in range(0, len(int_list)):
total = total + (int_list[i]*int_list[i])
print(total)
Now let's walk through what the code does now.
With a list of [1, 2, 3] the for loop will iterate three times
On the first iteration, total will be assigned the value 1 because 0 + 1 * 1 is 1.
On the second iteration, total will be assigned the value 5 because 1 + 2 * 2 is 5. Notice how the previous value of the loop iteration is being added to the loop
On the third iteration, total will be assigned the value 14 because 5 + 3 * 3 is 14. Notice again how the previous value of the loop iteration is being added to the loop.
This gives us the correct result of 14.
One nice feature of python is the addition assignment which condentes A = A + B to A += B so it is possible to simply the following code to:
total = 0
for i in range(0, len(int_list)):
total += (int_list[i]*int_list[i])
print(total)
A reason this problem may have been so difficult is that the for loop is more complicated than it needs to be. It is possible that rather than iterating through a list of indices generated by a list of numbers then assessing the numbers from the list by their index. It is possible to iterate through the numbers directly.
With the that simplification your loop would look like this:
total = 0
for number in int_list:
total += number * number
print(total)
These changes would make your whole programme look like this:
int_list = [] # initiate list
while True:
user_input = input("Enter an integer (or Q to quit): ") # get user input
if user_input == "Q": # break loop if user enters Q
break
integer = int(user_input) # convert user_input to an integer to add to list
int_list.append(integer) # add the integers entered to the list
for i in range(0, len(int_list)):
template = ("({0} x {1})".format(int_list[i], int_list[i]))
if i == len(int_list)-1:
trailing = " = "
else:
trailing = " + "
print(template, end="")
print(trailing, end="")
total = 0 # start the total at zero as no values have been calculated yet
for number in int_list: # iterate through all values in the list
total += number * number # add to the total the number squared
print(total)
You duplicate only the last product (2 x 3 x 3 = 18).
Because you reassign x in your loop (x = (int_list[i]*int_list[i])) and than duplicate x with add = (x+x).
But you have to build the sum.
int_list = [] # initiate list
while True:
user_input = input("Enter an integer (or Q to quit): ") # get user input
if user_input == "Q": # break loop if user enters Q
break
integer = int(user_input) # convert user_input to an integer to add to list
int_list.append(integer) # add the integers entered to the list
for i in range(0, len(int_list)):
template = ("({0} x {1})".format(int_list[i], int_list[i]))
if i == len(int_list) - 1:
trailing = " = "
else:
trailing = " + "
print(template, end="")
print(trailing, end="")
x = 0
for i in range(0, len(int_list)):
x += (int_list[i] * int_list[i])
print(x)
You can try this
state= True
combi= []
while state:
user_input = input("Enter an integer (or Q to quit): ").lower()
if "q" in user_input:
state= False
else:
combi.append(int(user_input))
else:
final= sum([x+x for x in combi])
print(final)

Python TikTakToe game if statement not working properly

So I am writing a python tiktaktoe game as a project. I am required to use multidimensional arrays and have no errors. In the function p_turn() (Which manages the player move), I was going to implement an if statement to check whether the move is valid (between 1 and 3). But now, no matter what number I put in, it still says that the move is invalid.
The desired outcome is for the game not to allow numbers that aren't between 1 and 3.
def p_turn():
system(command='cls')
print_board()
p_play_1 = int(input("Choose a position for the Y between 1 and 3 --> "))
p_play_2 = int(input("Choose a position for the X between 1 and 3 --> "))
if p_play_1 != 1 or p_play_1 != 2 or p_play_1 != 3 or p_play_2 != 1 or p_play_2 != 2 or p_play_2 != 3: # This is whats not working correctly
print("This is not a valid move. The values must be betweeen 1 and 3! ")
time.sleep(3)
p_turn()
if board[p_play_1 - 1][p_play_2 -1] == " ":
board[p_play_1 - 1][p_play_2 - 1] = "X"
system(command='cls')
print_board()
c_turn() # Computer play
elif board[p_play_1 - 1][p_play_2 - 1] == "X" or [p_play_1 - 1][p_play_2 - 1] == "O":
print("Someone already went there! ")
time.sleep(3)
p_turn()
Also, if it's important, this is how I store my board.
board = [[" ", " ", " "],
[" ", " ", " "],
[" ", " ", " "]]
def print_board():
print()
print(f"{board[0][0]} | {board[0][1]} | {board[0][2]}")
print("---------")
print(f"{board[1][0]} | {board[1][1]} | {board[1][2]}")
print("---------")
print(f"{board[2][0]} | {board[2][1]} | {board[2][2]}")
print()
Rename p_turn to player_turn. That way you give your function much more meaning. The same applies to c_turn - cumputer_turn is far more clear. In your small example, it doesn't make that big a difference but in larger projects, naming is really important!
p_play_1 and p_play_2 would make much more sense if they were simply named x and y.
Your boundary check is essentially:
if x != 1 or x != 2 or x != 3 or # ... repeat for y
That can't work. The above if condition is evaluated from left to right and terminates as soon as something is True. Take for example x = 2 (which is a valid coordinate). x != 1 evaluates to True and your move is considered invalid.
There are many ways to check whether a variable is within a certain range in Python.
Using comparison operators:
if lower_bound <= value <= upper_bound:
# value is between lower and upper bound
Using range():
if value in range(lower_bound, upper_bound + 1):
# value is between lower and upper bound
You could try something like this:
while not 1 <= (p_play_1 := int(input("Choose a position for the Y between 1 and 3 --> "))) <= 3:
print(f"Invalid Y position: {p_play_1}")
while not 1 <= (p_play_2 := int(input("Choose a position for the X between 1 and 3 --> "))) <= 3:
print(f"Invalid X position: {p_play_2}")

How to break a while loop when input is a particular string?

I need to stop adding up user inputs when one of them is the string "F".
So basically If my input is a int then : += result, if the same input variable is a string then I need to stop and add them together.
My code actually works and has the same inputs and outputs the exercise demands but I'm very unhappy with the way I resolve it.
This is my code:
import numbers
cat = int(input())
def norm(cat):
res = 0
for n in range(cat):
x = int(input())
res += x
print(res)
def lon():
res = 0
while 2 > 1:
try :
y = int(input())
if isinstance(y,int):
res +=y
except:
print(res)
break
if cat >= 0 :
norm(cat)
else:
lon()
It's actually breaking the while loop in a stupid way by checking if my variable is an int. (I need to make it stop by simply pressing F)
Is there any cleaner and shorter way to obtain the same outputs?
Example of the actual inputs-outputs I expect :
in: out:16 (1 + 3 + 5 + 7)
4
1
3
5
7
in: out:37 (1 + 3 + 5 + 7 + 21)
-1
1
3
5
7
21
F
You could have written it a bit shorter:
result = 0
while True:
line = input()
try:
result += int(line)
except ValueError:
break
print(result)
Notice:
import numbers isn't needed. (I didn't even know that existed!)
Instead of 2 > 1, you can use True.
You don't need to check isinstance(..., int) since int() enforces that.
This runs until any non-integer string is reached.
If you want to specifically check for "F" only, it's a bit easier:
result = 0
while True:
line = input()
if line == "F":
break
result += int(line)
print(result)
Note that without using try, you'll crash the program if you input a non-integer, non-"F" string.

Nested Triangle in Python

My assingment
At each level the complete triangle for the previous level is placed into an extra outer triangle. The user should be asked to input the two characters to be used and the width of the innermost triangle, which must be odd. In addition to the test for negative input the function should test whether the supplied number is odd and display an appropriate message if it is not.
I need to print 3 triangles but every one of them includes other. It needs to get printed with two different character(like *-) and the user have to specify the length of innermost triangle and which has to be an odd number. Example,
Example output for 5 value
Ok, let me explain my way,
Every triangle should be in dictionary.
tri1 = {1:"*****", 2:"***", 3:"*"}
tri2 = {1:"..........", ...}
And couldn't find how I can deal with user input?
If enter 5,
length - 5 unit, height 3 unit
length - 11 unit, height 6 unit
length - 23 unit, height 12 unit.
How can i know? What is the logic?
Ok lets say if I did. I understand I should put a tringle in another triangle with nested loop, can simply iterate it another dictionary but, I need to check second character's position.
Thanks in advance.
My code,
ch1, ch2 = input("Please enter the characters you want to use: ")
num = int(input("Please specify the length of innermost triangle(only odd number): "))
if (num % 2 == 0) or (num < 3):
print("Number can not be even, less then 3 and negative")
num2 = (2 * num) + 1
num3 = (2 * num2) +1
tri1 = {}
tri2 = {}
tri3 = {}
for i in range(3):
tri1[i] = ch1*num
num -= 2
check = 1
cont = 0
var = 1
for ii in range(6):
tri2[ii] = ch2*check
check += 2
if (ii >= 3):
tri2[ii] = ch2*var + tri1[cont] + ch2*var
cont += 1
var += 2
for i in tri1:
print('{:^5}'.format(tri1[i]))
for i in tri2:
print('{:^11}'.format(tri2[i]))
The dictionary can be created using a simple function:
def create_tri_dict(tri_chars, tri_height):
level_str = {0:tri_chars[0]}
for i in range(1,tri_height):
level_length = i *2 +1
tri_char = tri_chars[i%2]
level_str[i] = level_str[i-1] + '\n' + tri_char * level_length
return level_str
Then the main logic of your program could be:
tri_chars = input('Input triangle characters: ')
tri_length = int(input('Input triangle base length: '))
tri_height = (tri_length + 1)//2
if tri_length %2 == 0:
raise Exception('Triangle base length not odd')
tri_dict = create_tri_dict(tri_chars, tri_length)
Then to print the final 3(?) triangles:
print(tri_dict[tri_height-2])
print(tri_dict[tri_height-1])
print(tri_dict[tri_height])

Regarding formatting of printed outputs (python) [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I have been working on the program that lists out the products (with their cost and quantity) , and they are separately stored in 3 different lists.
However, what I can't figure out how to do is , aligning of the printed outputs
while valid ==1 :
if user_choice == 's':
user_product = str(input("Enter a product name: "))
valid = 2
elif user_choice == 'l':
print ("Product" + " " + "Quantity" +" "+ "Cost")
c = 0
while c < len(product_names):
print (product_names[c] + " " + str(product_costs[c]) + " "+ str(quantity[c]))
c +=1
valid = 0
break
valid = 0
So basically I am not sure on how to actually make output on line 6 and
line 9 be aligned together because I'll be getting a disorganized output because the product names differ in length, cost and quantity differ in length too.
Can anybody teach me how to actually align them all properly so that they might
look like a table?
Thanks so much!
Here is what you wanted, exactly by the prescribed order.
n = -1 # Intentionally an incorrect value
# Ask user for the number while he/she doesn't enter a correct one
while n < 10:
n = int(input("Enter an integer number greater or equal 10: "))
# Preparation for Sieve of Eratosthenes
flags_list = ["P"] # 1st value
flags_list = flags_list * (n + 1) # (n + 1) values
flags_list[0] = "N" # 0 is not a prime number
flags_list[1] = "N" # 1 is not a prime number, too
# Executing Sieve of Eratosthenes
for i in range(2, n + 1):
if flags_list[i] == "P":
for j in range(2 * i, n + 1, i):
flags_list[j] = "N"
# Creating the list of primes from the flags_list
primes = [] # Empty list for adding primes into it
for i in range(0, n + 1):
if flags_list[i] == "P":
primes.append(i)
# Printing the list of primes
i = 0 # We will count from 0 to 9 for every printed row
print()
for prime in primes:
if i < 10:
print("{0:5d}".format(prime), end="")
i = i + 1
else:
print() # New line after the last (10th) number
i = 0
=========== The answer for your EDITED, totally other question: ===========
=========== (Please don't do it, create a new question instead.) ===========
Replace this part of your code:
print ("Product" + " " + "Quantity" +" "+ "Cost")
c = 0
while c < len(product_names):
print (product_names[c] + " " + str(product_costs[c]) + " "+ str(quantity[c]))
c +=1
with this (with the original indentation, as it is important in Python):
print("{:15s} {:>15s} {:>15s}".format("Product", "Quantity", "Cost"))
for c in range(0, len(product_names)):
print("{:15s} {:15d} {:15d}".format(product_names[c], quantity[c], product_costs[c]))
(I changed your order in the second print to name, quantity, cost - to correspond with your 1st print.)
Probably you will want change 15's to other numbers (even individually, e. g. to 12 9 6) but the triad of numbers in the first print must be the same as in the second print().
The explanation:
{: } are placeholders for individual strings / integers listed in the print statements in the .format() method.
The number in the placeholder express the length reserved for the appropriate value.
The optional > means the output has be right aligned in its reserved space, as default alignment for text is to the left and for numbers to the right. (Yes, < means left aligned and ^ centered.)
The letter in the placeholder means s for a string, d (as "decimal") for an integer - and may be also f (as "float") for numbers with decimal point in them - in this case it would be {:15.2f} for 2 decimal places (from reserved 15) in output.
The conversion from number to string is performed automatically for symbols d or f in the placeholder, so str(some_number) is not used here.
Addendum:
If you will have time, please copy / paste your edited version as a new question, then revert this question to its original state, as people commented / answered your original one. I will find your new question and do the same with my answer. Thanks!

Categories