Noughts and Crosses Issue part 2 - python

Keeping in mind I am a beginner programmer,
i've ran into another problem with my noughts and crosses code in my attempt to add functionality to not allow players to place on the same grid space more than once- however I cannot figure out why it is that when you enter a position for the first go it immediately states that you >Cannot place on a full grid space even though it is impossible for any spaces to be full.
won = False
sum = 0
for i in range (3):
if grid[i][i] == "X":
sum +=1
elif grid[i][i] == "O":
sum -=1
if sum == 3 or sum == -3:
won = True
sum = 0
for i in range (3):
if grid[row][i] == "X":
sum +=1
elif grid[row][i] == "O":
sum -=1
if sum == 3 or sum == -3:
won = True
sum = 0
for i in range (3):
if grid[i][column] == "X":
sum +=1
elif grid[i][column] == "O":
sum -=1
if sum == 3 or sum == -3:
won = True
return won
#############################main program#############################
grid = [["-","-","-"],
["-","-","-"],
["-","-","-"]]
for x in grid:
print (x)
win = False
repeat = False
while win == False:
print("\nCrosses\n")
while repeat == False:
column = int(input("Enter a Column\n"))
row = int(input("Enter a Row\n"))
if grid[row][column] == "X" or "O":
print("Cannot place on a full grid space")
else:
repeat == True
grid[row][column] = ("X")
for x in grid: print (x)
win = checkwin(grid, row, column)
if win:
break
repeat = False
print("\nNoughts\n")
column = int(input("Enter a Column\n"))
row = int(input("Enter a Row\n"))
grid[row][column] = ("O")
for x in grid: print (x)
win = checkwin(grid, row, column)```

I tried out your code and found a couple of issues that were tripping you up. Following is a revised version of your code with the corrections having a comment.
def checkwin(grid, row, column): # Added the function definition
won = False
sum = 0
for i in range (3):
if grid[i][i] == "X":
sum +=1
elif grid[i][i] == "O":
sum -=1
if sum == 3 or sum == -3:
won = True
sum = 0
for i in range (3):
if grid[row][i] == "X":
sum +=1
elif grid[row][i] == "O":
sum -=1
if sum == 3 or sum == -3:
won = True
sum = 0
for i in range (3):
if grid[i][column] == "X":
sum +=1
elif grid[i][column] == "O":
sum -=1
if sum == 3 or sum == -3:
won = True
return won
#############################main program#############################
grid = [["-","-","-"],
["-","-","-"],
["-","-","-"]]
for x in grid:
print (x)
win = False
repeat = False
while win == False:
print("\nCrosses\n")
while repeat == False:
column = int(input("Enter a Column\n"))
row = int(input("Enter a Row\n"))
if grid[row][column] == "X" or grid[row][column] == "O": # Revised the test
print("Cannot place on a full grid space")
else:
repeat = True # Removed second "=" sign
grid[row][column] = ("X")
for x in grid: print (x)
win = checkwin(grid, row, column)
if win:
break
repeat = False
print("\nNoughts\n")
column = int(input("Enter a Column\n"))
row = int(input("Enter a Row\n"))
grid[row][column] = ("O")
for x in grid: print (x)
win = checkwin(grid, row, column)
Following are the highlights.
The sample code was missing the function definition for checking for a winner so that was added.
The "if" test for empty grid positions needed to be corrected checking for not having an "X" nor having an "O".
The update of "repeat" variable only needed one "=", not "==" (that's an equality check).
After that the program seemed to play properly. Give that try.

Related

Noughts And Crosses game loop iterating too many times

This is my noughts and crosses code i am still early on in making it and I am trying to do it as independently as possible without too much help from google- this is a simple question but why is it that when you get 3 in a row within the 2d list that the loop I have made continues to iterate one last time before ending? thanks a lot
won = False
sum = 0
for i in range (3):
if grid[i][i] == "X":
sum +=1
elif grid[i][i] == "O":
sum -=1
if sum == 3 or sum == -3:
won = True
sum = 0
for i in range (3):
if grid[row][i] == "X":
sum +=1
elif grid[row][i] == "O":
sum -=1
if sum == 3 or sum == -3:
won = True
sum = 0
for i in range (3):
if grid[i][column] == "X":
sum +=1
elif grid[i][column] == "O":
sum -=1
if sum == 3 or sum == -3:
won = True
return won
#############################main program#############################
grid = [["-","-","-"],
["-","-","-"],
["-","-","-"]]
for x in grid:
print (x)
win = False
while win == False:
print("\nCrosses\n")
column = int(input("Enter a Column\n"))
row = int(input("Enter a Row\n"))
grid[row][column] = ("X")
for x in grid: print (x)
win = checkwin(grid, row, column)
print("\nNoughts\n")
column = int(input("Enter a Column\n"))
row = int(input("Enter a Row\n"))
grid[row][column] = ("O")
for x in grid: print (x)
win = checkwin(grid, row, column)```
After your check whether last placed X made the player win, you don't exit the loop in any case (the while loop condition is only checked when an iteration starts, not all the time) - the program always continues and allows O player to move, even if win is already true. To change that behaviour, you need to break from the loop if the X player won, using break keyword. Your loop would look like this:
while win == False:
print("\nCrosses\n")
column = int(input("Enter a Column\n"))
row = int(input("Enter a Row\n"))
grid[row][column] = ("X")
for x in grid: print (x)
win = checkwin(grid, row, column)
if win:
break
print("\nNoughts\n")
column = int(input("Enter a Column\n"))
row = int(input("Enter a Row\n"))
grid[row][column] = ("O")
for x in grid: print (x)
win = checkwin(grid, row, column)

Tic Tac Toe Program in Python shows errors when checking for diagonal wins

I'm making a tic tac toe in python and when creating a diagonal check, I keep getting the wrong results. In my script, I have a 2D list with all of the values on the board:
filled = [['n','n','n'],
['n','n','n'],
['n','n','n']]
This changes whenever the user enters values to add an X or O, for example:
filled= [['X','X','n'],
['n','O','O'],
['n','n','n']]
My horizontal and vertical checks work fine but my diagonal check gives me false wins whenever I run it. Here's the function:
def Dcheck(filled):
global win
global winner
global turn
dxcount = docount = 0
# Negative Diagonal (1,5,9)
x = 0
for row in filled:
if row[x] == 'X':
dxcount+=1
elif row[x] == 'O':
docount +=1
x+=1
if dxcount == 3:
win,winner,turn = True,'X',0
elif docount == 3:
win,winner,turn = True,'O',0
dxcount = docount = 0
# Positive Diagonal (3,5,7)
x = 2
for row in filled:
if row[x] == 'X':
dxcount+= 1
elif row[x] == 'O':
docount += 1
x -= 1
if dxcount == 3:
win,winner,turn = True,'X',0
elif docount == 3:
win,winner,turn = True,'O',0
return [win,winner,turn,dxcount,docount]
Now, whenever I play a game like this:
filled = [['X','O','O'],
['X','X','n'],
['n','n','n']]
X gets a win, even when it's not supposed to. Same goes if you invert the board to the right side. I still don't understand what I'm doing wrong. Thanks in advance for the help!
Edit: My Github repo if you want the whole script (it's tic_tac_toe.py): https://github.com/DarthKitten2130/PyGames.git
I think the error stems from another function, Vcheck.
def Vcheck(filled):
global win
global winner
global turn
vxcount = vocount = 0
for x in range(3):
for row in filled:
if row[x] == 'X':
vxcount+=1 # <--- is never reset
elif row[x] == 'O':
vocount+=1
if vxcount == 3:
win,winner,turn = True,'X',0
elif vocount == 3:
win,winner,turn = True,'X',0 # <---- 'X' should be 'O'
There you do not reset vxcount while looping (line 92, following). So you actually count the number of 'x' in your game which is 3 in your example.
Also you want to have another look at line 101. There you checked the win condition for 'O' but put 'X' as a winner.

Error in repeating input in a tictactoe game

I am trying to prevent the user from inputting a square that is already marked, but the for loop moves on to the next player's input without decrementing the value of i by one, so the player 1 can repeat his input. How do I fix this?
arr = [[0,0,0],[0,0,0],[0,0,0]]
grid = grid(arr)
grid.print_grid()
for i in range(9):
row = int(input("Enter the row name: "))
col = int(input("Enter the column name: "))
if(arr[row][col] == 0):
if(i%2):
arr[row][col] = 1
else:
arr[row][col] = 2
else:
print("\nThat square has already been marked! Please select another square")
i = i-1
continue
grid.print_grid()
res = grid.grid_checker()
if (res == 1):
print("\nPlayer 1 wins the game!")
break
elif(res == 2):
print("\nPlayer 2 wins the game!")
break
elif(i == 8):
print("\nThe game has ended in a draw!")
You need to store another variable to keep track of whose turn it is. You cannot modify the variable you are looping on while you are in the loop body. This means that i cannot be manipulated while you are running in the loop. Here's how I would change it.
turn = 0
while True:
row = int(input("Enter the row name: "))
col = int(input("Enter the column name: "))
if(arr[row][col] == 0):
if(i%2):
arr[row][col] = 1
turn = turn + 1
else:
arr[row][col] = 2
turn = turn + 1
else:
print("\nThat square has already been marked! Please select another square")
continue
grid.print_grid()
res = grid.grid_checker()
if (res == 1):
print("\nPlayer 1 wins the game!")
break
elif(res == 2):
print("\nPlayer 2 wins the game!")
break
elif(turn == 8):
print("\nThe game has ended in a draw!")
Here we're saving the turn number in the variable turn and only incrementing the variable when we can confirm a player has successfully completed their turn.
Why you cannot modify i: For optimisations, loops are often expanded by python before they are converted to assembly instructions. For example a simple loop like this:
for i in range(9):
print(i)
May be expanded to something like this:
i = 0
print(i)
i = 1
print(i)
# and so on, upto
i = 9
print(i)
This is done to avoid having to jump around in memory. So as you can see here, i is reassigned for every iteration of the loop. Therefore, even if you change the value of i in the body of the loop, it will simply be reassigned before the next iteration.

Ways to execute this code under 4 seconds given large inputs?

NOTE: I CAN NOT use any external module that is not built-in to python.
Problem:
A new and upcoming artist has a unique way to create checkered patterns. The idea is to
use an M-by-N canvas which is initially entirely black. Then the artist repeatedly chooses
a row or column and runs their magic brush along the row or column. The brush changes
the colour of each cell in the row or column from black to gold or gold to black.
Given the artist’s choices, your job is to determine how much gold appears in the pattern
determined by these choices.
Input Specification
The first line of input will be a positive integer M. The second line of input will be a positive
integer N. The third line of input will be a positive integer K. The remaining input will be
K lines giving the choices made by the artist. Each of these lines will either be R followed
by a single space and then an integer which is a row number, or C followed by a single space
and then an integer which is a column number. Rows are numbered top down from 1 to M.
Columns are numbered left to right from 1 to N.
Output Specification
Output one non-negative integer which is equal to the number of cells that are gold in the
pattern determined by the artist’s choices.
Limitations
M and N can be up to 5 000 000
K can be up to 1 000 000
My Solution
import sys
raw_input = sys.stdin.readline
m = int(raw_input())
n = int(raw_input())
brushes = raw_input()
stroke = []
colors = [['B' for _ in range(n)] for _ in range(m)]
for i in range(int(brushes)):
g = raw_input().split(' ')
if stroke.count(g) == 1:
stroke.remove(g)
else:
stroke.append(g)
def changeColumn(num,colors,index):
if num == 0:
return colors
colors[num-1][index] = 'G' if colors[num-1][index] == 'B' else 'B'
num -= 1
changeColumn(num,colors,index)
def countGold(c,options,i):
if options == []:
s = 0
for l in c:
s += l.count("G")
print(s)
return
area = options[i][0]
times = int(options[i][1]) - 1
if area == "R":
c[times] = list(''.join(c[times]).replace("G","A").replace("B","G").replace("A","B"))
elif area == "C":
changeColumn(m,c,times)
options.remove(options[i])
countGold(c,options,i)
countGold(colors,stroke,0)
Got everything right except for some problems. I exceeded the Time Limit of 4 seconds. I know that making colors takes up a lot of time. Is there any way to do this without generating the 2d array?
UPDATED CODE (doesn't work)
import sys
M = int(input())
N = int(input())
K = int(input())
dup = []
numR = 0
numC = 0
for i in range(K):
choice = input().split()
if choice not in dup:
if choice[0] == "R":
numR += 1
elif choice[0] == "C":
numC += 1
dup.append(choice)
print((M * numR) + (N * numC) - (2*numR*numC))
Let me put all that discussion in comments into the code:
import sys
M = int(input())
N = int(input())
K = int(input())
dup = set()
result = {'numR': 0, 'numC': 0}
def update(char, num):
if char == 'R':
result['numR'] += num
elif char == 'C':
result['numC'] += num
for i in range(K):
choice = input().split()
if choice in dup:
dup.remove(choice)
update(choice[0], -1)
else:
dup.add(choice)
update(choice[0], 1)
numR = result['numR']
numC = result['numC']
print((M * numR) + (N * numC) - (2*numR*numC))
The code sent by Freakish still doesn't work for some reason. Here is an updated code that works:
import sys
rw = sys.stdin.readline
M = int(rw())
N = int(rw())
choices = set()
K = int(rw())
for i in range(K):
g = input()
if g in choices:
choices.remove(g)
else:
choices.add(g)
numR = 0
numC = 0
s = 0
for choice in choices:
if choice[0] == "R":
numR += 1
elif choice[0] == "C":
numC += 1
for choice in choices:
if choice[0] == "R":
# numR += 1
s += N - numC
elif choice[0] == "C":
# numC += 1
s += M - numR
print(s)

Check if condition matches in python

Having trouble figuring out my list comprehension in python. I have 3 conditions that I'm looking for, and I know how to do two of them, but one of the conditions doesn't seem to work right.
My conditions are:
If all the numbers in my list are the same and they are all a specific number, then add points
If all numbers in my list are the same but they do not equal a specific number then do something else
If numbers in list do not match, but they equal a specific number than do something else.
I have 1 working, and I know how to do number 3, but I can't get number 2 working properly. No matter what numbers I put into my list (rolls), this condition still matches True. Can someone please assist? Here is my current code:
def check_conditions(rolls, round_number):
"""
Check if number on rolled die matches one of three conditions
:param rolls:
:param round_number:
:return round:
"""
round_score = ROUND_TOTAL
rolls = str(rolls)
bunco = all(roll == ROUND_NUMBER for roll in rolls)
mini_bunco = all(roll == roll[0] and roll != ROUND_NUMBER for roll in rolls)
if bunco == True:
print("BUNCO!")
round_score += 20
elif mini_bunco == True:
print("MINI-BUNCO!")
round_score += 5
else:
pass
return round_score
OUTPUT:
Starting Round Number 1
You rolled: [2, 3, 3]
MINI-BUNCO!
Points this round: 5
Something like this should get you there...
rolls = [5,5,5,5,5,5]
specificNum = 6
if len(set(rolls)) == 1:
if rolls[0] != specificNum:
print 'Do something'
#imports
import random
#variables
Roll_1_return = False
Roll_2_return = False
round_score = ROUND_TOTAL
#assuming you only want to roll twice
def Rolls():
Roll_1 = random.randrange(1, 10)
Roll_2 = random.randrange(1, 10)
While True:
if Roll_1 == 3:
Roll_1_return = True
return Roll_1_return
break
else:
break
While True:
if Roll_2 == 7:
Roll_2_return = True
return Roll_2_return
break
else:
break
Rolls()
if Roll_1_return == True:
print('Roll 1 is correct!')
round_score + 25
else:
print('Roll 1 is incorrect..')
if Roll_2_return == True:
print('Roll 2 is correct!')
round_score + 25
else:
print('Roll 2 is incorrect..')
if round_score == 50:
print('You won $100!')
elif round_score == 25:
print('You won $50!')
else:
print('Too bad, you lost!')
If I understand correctly, this should give you what you need! If this is not what you wanted, plz do not downvote me! I tried my hardest to understand.

Categories