Issues with For loops inside of Functions in Python 3.3 - python

Okay, so I'm working on writing a tic tac toe game, and have run into a pretty bad error that I can't seem to solve. I have created a function that will have the computer block the player if the player is about to win, however, after if successfully blocks once, it doesn't trigger anymore even if the conditions are satisfied. The code for the function is:
def block():
for t in range(0, 9, 3):
if slot[t] == user_team and slot[t+1] == user_team and (slot[t+2] \
!= user_team) and (slot[t+2] != computer_team):
slot[int(t+2)] = computer_team
return
elif slot[t+1] == user_team and slot[t+2] == user_team and (slot[t] \
!= user_team) and (slot[t] != computer_team):
slot[int(t)] = computer_team
return
elif slot[t] == user_team and slot[t+2] == user_team and (slot[t+1] \
!= user_team) and (slot[t+1] != computer_team):
slot[int(t+1)] = computer_team
return
for t in range(3):
if slot[t] == user_team and slot[t+3] == user_team and (slot[t + 6] \
!= user_team) and (slot[t+6] != computer_team):
slot[int(t+6)] = computer_team
return
elif slot[t+3] == user_team and slot[t+6] == user_team and (slot[t] \
!= user_team) and (slot[t] != computer_team):
slot[int(t)] = computer_team
return
elif slot[t] == user_team and slot[t+6] == user_team and (slot[t+3] \
!= user_team) and (slot[t+3] != computer_team):
slot[int(t+3)] = computer_team
Also, user_team and computer_team lead back to whether that player is X or O, and the slot[int()] = computer_team is used to place the move on the board.
And below is where the function is called (just in case I messed up here.):
else:
draw_board()
'''win()'''
block()
cmove()
turn = "user"
if end_game() == True:
computer_win += 1
draw_board()
print ("The computer has won! But... We already knew that would happen. (:")
playing = False
elif end_game() == "Tie":
tie_win += 1
draw_board()
print ("The game is a tie. You're going to have to try harder " \
+ "\n" + "if you wish to beat the computer!" + "\n")
playing = False
else:
pass
If any of you could tell me where I went wrong, then that would make my day. c:
Board (Prints are indented, it just doesn't want to here.)
def draw_board():
'''Opted to use lists so that the numbers can be replaced with either
X or O later on and so that testing whether the game is over is simpler'''
print (" " + str(slot[0]) + " | " + str(slot[1]) + " | " + str(slot[2]))
print ("-----------")
print (" " + str(slot[3]) + " | " + str(slot[4]) + " | " + str(slot[5]))
print ("-----------")
print (" " + str(slot[6]) + " | " + str(slot[7]) + " | " + str(slot[8]))
print ("\n")
New ERRROR:
This is my board after I put in move 4
X | O | X
O | 4 | 5
X | 7 | X
The computer's board after it's move 4 (two moves, and replaces an x)
X | O | X
O | 4 | O
O | 7 | X

I believe your problem is in the logic of your block function.
Here is your board:
0 1 2
3 4 5
6 7 8
Walking through the first pair of nested for loops, let's see what your code does:
for t in range(0,9,3):
for y in range(1, 9, 3):
This will give you the follow pairs of t, y: (0,1), (0,4), (0,7), (3,1), (3,4), (3,7), (6,1), (6,4), and (6,7). Right away, I don't think this is what you had intended. From what I can tell, you are trying to check to see if the player has two marks in a row.
This problem is easy to fix - you don't need two for loops. Instead, just use t, t+1, and t+2.
Next, consider a row:
0 1 2
There are three conditions to check for, player has marks at 0 and 1, at 0 and 2, or at 1 and 2. You only check for two of these conditions - 0 and 1, and 1 and 2.
Additionally, the if statement isn't doing what you think it's doing:
if ... and slot[y+1] != user_team and computer_team:
This is equivalent to this:
if ... and (slot[y+1] != user_team) and computer_team:
I assume computer_team is 'x' or 'o', in which case python would use it the same as True in an if statement. What you want is this:
if ... and (slot[y+1] != user_team) and (slot[y+1] != computer_team):
This is also probably why your code would work only once - the next time it goes to evaluate the same row or column it found previously, the if statement will evaluate to True again, and it will set the same space again, which to you looks as if it is doing nothing.
Your code for checking the columns has the same issues. Hopefully the issues I've pointed out will be enough for you to figure out how to fix your code. Good luck!

Related

Problems with Tic Tac Toe Game

Im making a Tic Tac Toe game but I have met a couple of problems while doing it.
The firs problem, is that when I had the board like:
X | - | X
or like:
- | X | X
It counts as a Win and I don't know why. If I put:
X | X | -
there's no problem with that.
The second problem, is that I want to prevent the user to select a position that is already in use, so my idea is to add to a list the position that has been selected and compare if it is already in it or not. The problem is that when I call the function for the second time it doesn't have the previus list that contain the information of the previus position (it makes a new one), therefore it never detects that the position that the user is giving is already in use.
board = ["-","-","-",
"-","-","-",
"-","-","-"]
def display():
print(board[0] + " | " + board[1] + " | " + board[2])
print(board[3] + " | " + board[4] + " | " + board[5])
print(board[6] + " | " + board[7] + " | " + board[8])
def turn():
exist=[]
pos = int(input("Choose your position"))
while True:
if pos not in exist:
exist.append(pos)
print(exist)
print("Correct position")
break
else:
print("That position has been selected, choose another one")
board[pos-1] = "X"
display()
def checkwin():
#row
if (board[0] and board[1] and board[2] == "X") or (board[3] and board[4] and board[5] == "X") or (board[6] and board[7] and board[8] == "X"):
print("Victory")
return False
else:
return True
display()
while checkwin():
turn()
checkwin()
print(board)
print("Game has ended")
NOTE: Right now the game only can have the X player, I need still to add the O player. Also, it only can detect the win for the rows. Im still working on this.
To your second question, you are declaring your list inside the function turn, which is called every time a player makes a choice. When a function returns, all of its local variables are no longer accessible. Compare this with your code.
def addToList( item ):
items = []
items.append( item )
addToList( 'item1' )
addToList( 'item2' )
Each time the function is called, items = [] is called as well. Edit to clarify my first statement, functions create their own scope. The scope of a variable is where it is available in your program. For example
def addItem( item ):
items = []
items.append( item )
addItem( "item1" )
print( items )
ERROR: items is not defined
The logic of (board[0] and board[1] and board[2] == "X") won't work because you are only checking is board[2] == 'X', the others are just truthy, thus '-' will also evaluate to True
You should rather check like this (board[0] == board[1] == board[2] == "X").
This ensures that all values are equal to 'X'
sin tribu nailed it as to why your turn function is behaving the way it is.
As to how to make it work right... perhaps I'm missing something, but aren't you looking to make sure you can't select a space that's already occupied? For that, you could just check the board directly.
def turn():
pos = int(input("Choose your position"))
while board[pos-1] == "X":
pos = int(input("That position has been selected, choose another one"))
print("Correct position")
board[pos-1] = "X"
display()
This will keep asking until you specify an empty square.

if, elif & !=, == boolean operations only return "false" with inputs

I am creating an Among Us ripoff (for fun!) and the while True & if/elif/else statements will only return false (not An Impostor) with the inputs. I had created a list for the names and 2 random elements from the list will be chosen as An Impostor. However, whenever I input a name that is The Impostor, it will only return
(player) was not An Impostor.
Here is my code;
import sys, time, random
names = ["player1", "player2", "player3", "player4", "player5", "player6", "player7", "player8", "player9", "player10"]
print("Players: ")
for x in names:
print(x)
print('—————————————————————————')
impostor1 = random.choice(names)
impostor2 = random.choice(names)
crewmates = 8
impostors = 2
tries = 6
while True:
talk = input("Guess who The Impostor(s) are. " + str(crewmates) + " Crewmates are left. " + str(impostors) + " Impostors are left. You have " + str(tries) + " tries left.")
if talk in names:
print(talk + " was voted for.")
time.sleep(0.1)
if talk != impostor1 or talk != impostor2:
notimp = talk + " was not An Impostor. "
names.remove(talk)
for y in notimp:
sys.stdout.write(y)
sys.stdout.flush()
time.sleep(0.05)
crewmates -= 1
tries -= 1
elif talk == impostor1 or talk == impostor2:
wasimp = talk + " was An Impostor. "
names.remove(talk)
for v in wasimp:
sys.stdout.write(v)
sys.stdout.flush()
time.sleep(0.1)
impostors -= 1
else:
print("That player was either ejected or is not a valid player.")
However, whenever I put the Impostor in the input, it says it isn't An Impostor?
I think this line is the source of the problem:
if talk != impostor1 or talk != impostor2:
Let's say impostor1 is player1 and impostor2 is player2 and someone input in player1, according to Python Boolean expression operator or that if statement will evaluate like this:
if player1 != impostor1 evaluated to False because player1 is indeed equals to impostor1.
So far so good, but because the first test is a False, Python simply evaluates and returns the right side operand which may be either True or False. In your case Python will evaluate if talk != impostor2 and return True, thereafter executes the nested block.

Modifying a list outside a 'While' loop after running it through the 'While' loop

I'm currently trying to create my own game of TicTacToe from the ground up and I'm currently having difficulty with a 'while' loop corresponding to a list that I have created.
I'm using the following list:
board = [1,2,3,4,5,6,7,8,9]
to mark all 9 slots on a 3x3 game of TicTacToe.
However when player one makes a move(in slot '1' for example) the list should be changed to show
board = [X,2,3,4,5,6,7,8,9]
This should continue on until all 9 indexes(I believe is the appropriate term) within the list should be taken up by either 'X' or 'O' which will equal a tie in the game!
For now I'm just experimenting as I go along so pardon the rest of the code but the full code I'm using is:
board = [1,2,3,4,5,6,7,8,9]
def CreateBoard(board):
print(' | |')
print(' ' + board[7] + ' | ' + board[8] + ' | ' + board[9])
print(' | |')
print('-----------')
print(' | |')
print(' ' + board[4] + ' | ' + board[5] + ' | ' + board[6])
print(' | |')
print('-----------')
print(' | |')
print(' ' + board[1] + ' | ' + board[2] + ' | ' + board[3])
print(' | |')
PlayerOne = 'X'
Turn = 'player one'
GameRunning = True
while [0] == 1 or 2 or 3 or 4 or 5 or 6 or 7 or 8 or 9 in board == True:
if Turn == 'player one':
letter = 'X'
Move = input("Please pick where to go next: ")
Move = int(Move)
if Move in board:
board.insert(Move, letter)
board.remove(Move)
print(board)
Turn = 'player two'
else:
print("This move is invalid")
if Turn == 'player two':
letter = 'O'
Move = input("Pick where to go next: ")
Move = int(Move)
if Move in board:
board.insert(Move, letter)
board.remove(Move)
print(board)
Turn = 'player one'
else:
print("This move is invalid")
The output I get as I go along are:
I'm guessing the while loop is running the list that's outside of the loop but I'm trying to find a way to change that!
I've also not yet worked out why its printing 'That move is invalid'!
The issue with your while loop is that non-zero integers are always considered to be "true". Therefore
while [0] == 1 or 2 or 3 or 4 or 5 or 6 or 7 or 8 or 9 in board == True:
actually means "while the list containing 0 is equal to the integer 1 (always false), or 2 (true), or 3 (true)... or 9 in (board) (true if 9 is still on the board), then enter the block."
I believe that you meant was more:
while any((cell in range(1,10) for cell in board)):
which means while any cell in the board is in the range from 1 (inclusive) to 10 (exclusive), then enter the block.
Take a look at this code:
player = [
{"name": "Player One", "letter": "X"},
{"name": "Player Two", "letter": "O"},
]
def print_board(board):
def print_vbars():
print(" | |")
def print_hbars():
print("-----------")
print_vbars()
for row in range(3):
print(" {} | {} | {}".format(*(board[row*3 : row*3+3])))
print_vbars()
print_hbars()
print_vbars()
print_vbars()
def final_state(board):
winning_combinations = (
(0,1,2), # Horizontal top row
(3,4,5), # Horizontal middle row
(6,7,8), # Horizontal bottom row
(0,3,6), # Vertical left row
(1,4,2), # Vertical middle row
(2,5,7), # Vertical right row
(0,4,8), # Downward diagonal
(2,4,6), # Upward diagonal
)
for letter in ("X", "O"):
for combination in winning_combinations:
row_state = (board[index] for index in combination)
if all(map(lambda cell: letter == cell, row_state)):
return "{} wins".format(letter)
if all(map(lambda cell: cell in ("X", "O"), board)):
return "Game is a draw."
return False
def play_game():
board = list(range(9))
starting_player = 0
turn = 0
active_player = starting_player
while final_state(board) is False:
turn += 1
print("Turn {}:".format(turn))
print_board(board)
name, letter = player[active_player]["name"], player[active_player]["letter"]
move = None
while move is None:
try:
move = input("{} please make your move: ".format(name))
move = int(move)
if move in board:
board[move] = letter
print("{} played {} on {}.".format(name, letter, move))
active_player = 1 - active_player
else:
print("Move {} is invalid.".format(move))
move = None
except Exception as e:
print("Move {} is invalid.".format(move))
move = None
print_board(board)
print(final_state(board))
if __name__ == "__main__":
play_game()

Mastermind Python coding

Ok I have a feeling that this is a simple simple issue but I have been staring at this code for about 10 hours now.
The issue I am having is in mastermind is that once I get it to recognize that I have the correct colors in the right spot I can get it to display the right spots with X and the wrong spots with O. I need to be able to convert that so instead of X and O I need it to tell the user that he/she has 2 blacks and one white
For example: The secret code is RGYB The user enters RGOY so then Python relays "You have 2 blacks(The R and G spots) and one 1 White (The Y because it's the right color just in the wrong index) As of right now I got it to display X for the right color in the right spot and anything else it is an O
I will post what I have been working with now but today I am at my wit's end
https://pastebin.com/HKK0T7bQ
if correctColor != "XXXX":
for i in range(4):
if guess[i] == tempCode[i]:
correctColor += "X"
if guess[i] != tempCode[i] in tempCode:
correctColor += "O"
print (correctColor + "\n")
if correctColor == "XXXX":
if attempts == 1:
print ("You think you are sweet because you got it right on the first try? Play me again!")
else:
print ("Well done... You needed " + str(attempts) + " attempts to guess.")
game = False
A few comments
X and O
you use X and 0 to denote the success, it will be easier and faster to use a list or tuple or booleans for this, that way you can use sum() to count how many colors and locations were correct. Then whether you represent that with X and O or red and white pins is a matter for later
compartmentalization
Your game logic (guess input, input validation, do you want to continue, etc) is mixed with the comparison logic, so it would be best to separate the different functions of your program into different methods.
This is an fineexample to introduce object oriented programming, but is so simple it doesn't need OO, but it can help. What you need is a method which takes a series of colours and compares it to another series of colours
Standard library
Python has a very extended standard library, so a lot of stuff you want to do probably already exists
Correct colours
to count the number of letters which occur in 2 strings, you can use collections.Counter
guess = "RGOY "
solution = "RGYB"
a = collections.Counter(guess)
b = collections.Counter(solution)
a & b
Counter({'G': 1, 'R': 1, 'Y': 1})
correct_colours = sum((a & b).values())
3
So the user guessed 3 colours correctly
Correct locations
can be solved with an easy list comprehension
[g == s for g, s in zip(guess, solution)]
[True, True, False, False]
sum(g == s for g, s in zip(guess, solution))
2
so the used put 2 colours on the correct location
This is a MasterMind I made in Python. Hope you like it and it helped you! :)
import random
import time
from tkinter import *
def select_level():
global level
level = level_selector.get()
root.destroy()
root = Tk()
level_selector = Scale(root, from_=1, to=3, tickinterval=1)
level_selector.set(0)
level_selector.pack()
Button(root, text="Select a difficulty level", command=select_level).pack()
mainloop()
cpc_1_digit = 0
cpc_2_digit = 0
cpc_3_digit = 0
cpc_4_digit = 0
p_1_digit = 0
p_2_digit = 0
p_3_digit = 0
p_4_digit = 0
correct_correct = 0
correct_wrong = 0
chances = 0
if level == 1:
chances = 15
elif level == 2:
chances = 10
else:
chances = 7
cpc_1_digit = random.randint(0, 9)
while cpc_2_digit == cpc_1_digit or cpc_2_digit == cpc_3_digit or cpc_2_digit ==
cpc_4_digit:
cpc_2_digit = random.randint(0, 9)
while cpc_3_digit == cpc_1_digit or cpc_3_digit == cpc_2_digit or cpc_3_digit ==
cpc_4_digit:
cpc_3_digit = random.randint(0, 9)
while cpc_4_digit == cpc_1_digit or cpc_4_digit == cpc_2_digit or cpc_4_digit ==
cpc_3_digit:
cpc_4_digit = random.randint(0, 9)
while chances > 0:
correct_correct = 0
correct_wrong = 0
answer = input("Enter a four-digit number with different digits (e.g 1476): ")
p_1_digit = int(answer[0])
p_2_digit = int(answer[1])
p_3_digit = int(answer[2])
p_4_digit = int(answer[3])
if p_1_digit == cpc_1_digit:
correct_correct = int(correct_correct) + 1
elif p_1_digit == cpc_2_digit or p_1_digit == cpc_3_digit or p_1_digit ==
cpc_4_digit:
correct_wrong = int(correct_wrong) + 1
else:
pass
if p_2_digit == cpc_2_digit:
correct_correct = correct_correct + 1
elif p_2_digit == cpc_1_digit or p_2_digit == cpc_3_digit or p_2_digit ==
cpc_4_digit:
correct_wrong = int(correct_wrong) + 1
else:
pass
if p_3_digit == cpc_3_digit:
correct_correct = int(correct_correct) + 1
elif p_3_digit == cpc_1_digit or p_3_digit == cpc_2_digit or p_3_digit ==
cpc_4_digit:
correct_wrong = int(correct_wrong) + 1
else:
pass
if p_4_digit == cpc_4_digit:
correct_correct = int(correct_correct) + 1
elif p_4_digit == cpc_1_digit or p_4_digit == cpc_3_digit or p_4_digit ==
cpc_2_digit:
correct_wrong = int(correct_wrong) + 1
else:
pass
print("")
if int(correct_correct) == 4:
print("Congratsulations! You found the computer's number!")
break
elif int(correct_wrong) > 0 or int(correct_correct) >= 1 and int(correct_correct)
< 4:
print("You got " + str(correct_correct) + " correct digit(s) in the correct
place, and " + str(correct_wrong) + " correct digit(s) but in wrong place.")
elif int(correct_correct) == 0 and int(correct_wrong) == 0:
print("You didn't guess any number, try again!")
else:
raise Exception("CheckError: line 69, something went wrong with the
comparings.")
exit()
print("")
chances = chances - 1
if chances == 0:
print("You lost... The secret number was " + str(cpc_1_digit) + str(cpc_2_digit)
+ str(cpc_3_digit) + str(cpc_4_digit) + ". Try again by rerunning the program.")
time.sleep(4)

Python Can't find string in file

I started working on my game few days ago. I made system for loading(on start) and saving(on exit). On first loging in everything is fine but on second error(NameError: name 'strange' is not defined) showed up. Can someone help me to solve it please? I know that problem is in finding name in file becouse I tryed to put else statment after everything under
elif ab.read().find(a) != -1:
and that what I put under else worked but it was just print so other required didn't worked under else.
Here's my program:
import sys, random, time, re
print("Welcome to game Special Travel Adventure!")
def con(a, b):
return a.lower() == b.lower()
a = str(input("If you want to continue with game type your name here: "))
ab = open("STAPlayers.txt", "r+")
if ab.read().find(a) == -1:
if ab.read() == "":
ac = "Name:" + a + ":Strange:" + "0" + ":Courage:" + "0" + ":Skills:" + "0" + ":Money:" + "0" + ":Level:" + "0" + ":Deaths:" + "0"
ab.write(ac)
strange = 0
courage = 0
skills = 0
money = 0
level = 0
deaths = 0
else:
ac = "\nName:" + a + ":Strange:" + "0" + ":Courage:" + "0" + ":Skills:" + "0" + ":Money:" + "0" + ":Level:" + "0" + ":Deaths:" + "0"
ab.write(ac)
strange = 0
courage = 0
skills = 0
money = 0
level = 0
deaths = 0
elif ab.read().find(a) != -1:
readdd = ab.readlines()
for line in readdd:
if line.find(a) != -1:
zm = line.split(":")
zm.remove("Name")
zm.remove("Strange")
zm.remove("Courage")
zm.remove("Skills")
zm.remove("Money")
zm.remove("Level")
zm.remove("Deaths")
strange = int(zm[1])
courage = int(zm[2])
skills = int(zm[3])
money = int(zm[4])
level = int(zm[5])
deaths = int(zm[6])
ab.close()
def levelc():
if courage and strange and skills == 1:
level += 1
return True
if courage and strange and skills == 2:
level += 1
return True
if courage and strange and skills == 3:
level += 1
return True
if courage and strange and skills == 4:
level += 1
return True
if courage and strange and skills == 5:
level += 1
return True
else:
return False
b = input("Start Menu\nSelect: Start, Upgrades, Exit. ")
while b != "dont save":
if con(b, "Exit"):
aj = open("STAPlayers.txt", "r")
lines = aj.readlines()
aj.close()
aj = open("STAPlayers.txt", "w")
jmj = "Name:" + a + ":Strange:" + str(strange) + ":Courage:" + str(courage) + ":Skills:" + str(skills) + ":Money:" + str(money) + ":Level:" + str(level) + ":Deaths:" + str(deaths)
for linee in lines:
if str(a) not in linee:
aj.write(linee)
elif str(a) in linee:
jmjm = jmj + "\n"
aj.write(jmjm)
aj.close()
sys.exit()
break
I know that problem is in finding name in file becouse I tryed to put else statment after everything under
elif ab.read().find(a) != -1:
and that what I put under else worked but it was just print so other required didn't worked under else. Please help.
Your problem is you are trying to read the file twice. You can only read a file once (without resetting to the beginning of the file). Try this:
ab_read = ab.read()
if ab_read.find(a) == -1:
...
elif ab_read.find(a) != -1:
...
Although, you might be better off using if a in ab_read: and then an else. Also, you might consider more meaningful variable names than ab or a.
To answer the next question you will have: your call to readdd = ab.readlines() will fail for the same reason multiple calls to ab.read() fail. You can get the same information with readdd = ab_read.splitlines()
In general, you are reading files way too often. Reading from files is a slow and resource consuming operation in any language. You chould consider reading the same file multiple times a very poor programming practice. You should refactor your code to only read each file once, and that should fix most of your issues.

Categories

Resources