os.system function will not clear screen - python

I don't know why my screen won't clear. Instead, I get an arrow pointing to the first letter. I looked on Google and one source said that it certain circumstances it may return a 0. Perhaps that is why it is pointing to the first letter of my first string? There are other problems with my code as well but I've spent a lot of time trying to figure out why this function won't work and I can't figure it out.
import os
import random
'''
In this tic-tac-toe game, the user will be prompted to choose a mark.
The player will play against a computer.
CURRENT PROBLEMS WITH GAME:
board_tiles and tiles_available do not reset after new game
clear_screen function does not work
Error when tie occurs
'''
board_tiles = [0, 1, 2, 3, 4, 5, 6, 7, 8]
tiles_available = [0, 1, 2, 3, 4, 5, 6, 7, 8]
# create a function that clears the screen
def clear_screen():
os.system('cls')
# create a function that draws the tic-tac-toe board
def draw_board():
# clear screen
clear_screen()
print(f'{board_tiles[0]} | {board_tiles[1]} | {board_tiles[2]}')
print('-' * 10)
print(f'{board_tiles[3]} | {board_tiles[4]} | {board_tiles[5]}')
print('-' * 10)
print(f'{board_tiles[6]} | {board_tiles[7]} | {board_tiles[8]}')
# create a function that allows the user to choose a piece
def choose_mark():
player = input("Would you like to be 'X' or 'O'? ").upper()
if player == 'X':
computer = 'O'
else:
computer = 'X'
print(f'Player is {player}. Computer is {computer}.')
return player, computer
# create a function that allows the computer to make a random move on the board
def computer_move(computer):
computers_move = random.choice(tiles_available)
tiles_available.remove(computers_move)
board_tiles.insert(computers_move, computer)
board_tiles.remove(computers_move)
return computers_move
# create a function that checks if the chosen spot is available and draws it to the board
def draw_mark(player, computer):
while tiles_available:
players_move = int(input('Where would you like to move? '))
if players_move in tiles_available:
tiles_available.remove(players_move)
board_tiles.insert(players_move, player)
board_tiles.remove(players_move)
computer_move(computer)
draw_board()
score()
else:
print('{players_move} has already been taken')
return player
# define what is a win/lose/tie
def score():
if board_tiles[0] == board_tiles[1] == board_tiles[2] or \
board_tiles[3] == board_tiles[4] == board_tiles[5] or \
board_tiles[6] == board_tiles[7] == board_tiles[8] or \
board_tiles[0] == board_tiles[3] == board_tiles[6] or \
board_tiles[1] == board_tiles[4] == board_tiles[7] or \
board_tiles[2] == board_tiles[5] == board_tiles[8] or \
board_tiles[0] == board_tiles[4] == board_tiles[8] or \
board_tiles[2] == board_tiles[4] == board_tiles[6]:
print('YOU WIN!!!')
play_again()
if len(tiles_available) == 0:
print('It is a tie!')
play_again()
def play_again():
replay = input("Would you like to play again? \n"
"Type 'y' for yes and 'n' for no: ").lower()
if replay == 'y':
game()
else:
print('Come back!')
quit()
def game():
playing = True
player, computer = choose_mark()
while playing:
draw_board()
draw_mark(player, computer)
game()

Related

Python doesn't take my input but there is no error (code continues running)

I continue learning the basics of Python by extending my TicTacToe game. It now lets the player choose difficulty. It seems that it works (finally), but sometimes I experience a strange issue.
Note that I use Google Colab (in case that is relevant).
This is a turn-based game, meaning I play my turn, then computer plays, then me etc until someone wins or we get to a tie (the order depends on what you input in the beginning, sometimes computer plays first). But sometimes, when I'm asked for my input and I give it, the input line disappears but nothing happens. My input is not shown on the board, the input line disappears, and the computer doesn't play because it's waiting for me to finish my turn. The code continues running (and Google Colab marks the code is currently at human_move(), meaning it's waiting for my input). It doesn't give an error message on its own, but see below for what's shown when I interrupt it manually.
I don't really know how to recreate the issue, other than playing many times in Colab (ony my own computer, the issue repeats almost always). So far it's happened on medium and hard difficulty. Here's how the last board looked when it got stuck (I played Os, computer played Xs). For my next move I pressed 4, then the input line disappeared without playing my move:
+-------+-------+-------+
| | | |
| O | 2 | 3 |
| | | |
+-------+-------+-------+
| | | |
| 4 | X | X |
| | | |
+-------+-------+-------+
| | | |
| 7 | 8 | O |
| | | |
+-------+-------+-------+
I'm attaching my full code. I know it's long and I'm sorry, but look below for an error message to maybe make it more clear.
# I need these functions to make everything work
from IPython.core.display import clear_output
from random import randrange
# Sets the board at the beginning
official_board = [1, 2, 3, 4, 5, 6, 7, 8, 9]
# Just displays the current board
def display_board(board):
print(
"\n+-------+-------+-------+",
"\n| | | |",
"\n| ",board[0]," | ",board[1]," | ",board[2]," |",
"\n| | | |",
"\n+-------+-------+-------+",
"\n| | | |",
"\n| ",board[3]," | ",board[4]," | ",board[5]," |",
"\n| | | |",
"\n+-------+-------+-------+",
"\n| | | |",
"\n| ",board[6]," | ",board[7]," | ",board[8]," |",
"\n| | | |",
"\n+-------+-------+-------+"
)
# Asks player to define who plays first (human or computer). Impacts the order of turns.
def who_plays_first():
global first_player
while True:
first_player = int(input("Choose who plays first: 1 for human, 2 for computer"))
if first_player == 1 or first_player == 2:
break
print("invalid input, read the instruction")
if first_player == 1:
first_player = "human"
else:
first_player = "computer"
return(first_player)
# Asks player to set difficulty. Impacts how computer decides on its move.
def choose_difficulty():
global difficulty
while True:
difficulty = int(input("Choose difficulty: 1 = easy, 2 = medium, 3 = hard"))
if difficulty == 1 or difficulty == 2 or difficulty == 3:
break
print("invalid input, read the instruction")
if difficulty == 1:
difficulty = "easy"
elif difficulty == 2:
difficulty = "medium"
else:
difficulty = "hard"
return(difficulty)
# Makes a list of free fields. Used in other functions.
def make_list_of_free_fields(board):
list_of_free_fields = []
for field in range(1,10):
if field in board:
list_of_free_fields.append(field)
return(list_of_free_fields)
# Checks whether the player (defined by the sign) won.
def victory_for(sign, board):
if (board[0] == sign and board[1] == sign and board[2] == sign or
board[3] == sign and board[4] == sign and board[5] == sign or
board[6] == sign and board[7] == sign and board[8] == sign or
board[0] == sign and board[3] == sign and board[6] == sign or
board[1] == sign and board[4] == sign and board[7] == sign or
board[2] == sign and board[5] == sign and board[8] == sign or
board[0] == sign and board[4] == sign and board[8] == sign or
board[2] == sign and board[4] == sign and board[6] == sign):
return True
else:
return False
# Asks the human player to make their move.
def human_move():
while True:
human_input = int(input("Choose a field"))
if human_input in make_list_of_free_fields(official_board):
break
print("You must choose one of the free fields on the board by typing 1-9")
official_board[human_input-1] = "O"
# This is how the computer makes its move.
# Depends on the difficulty.
def computer_move():
# This is how the computer plays on easy
if difficulty == "easy":
# Computer plays a random move out of the list of available fields
while True:
computer_input = randrange(10)
if computer_input in make_list_of_free_fields(official_board):
break
official_board[computer_input-1] = "X"
# this is how the computer plays on medium
# (or hard if less than 2 turns available for computer)
elif difficulty == "medium" or len(make_list_of_free_fields(official_board)) < 3:
# Check whether there's a (list of) move(s) that would guarantee computer victory
# if yes, play a random move out of that list and end the function
# if not, move to the next part of the function
brings_computer_victory = []
for field in make_list_of_free_fields(official_board):
temp_board = official_board[:]
temp_move = field
temp_board[temp_move-1] = "X"
if victory_for("X", temp_board) == True:
brings_computer_victory.append(temp_move)
if brings_computer_victory != []:
while True:
computer_input = randrange(10)
if computer_input in brings_computer_victory:
break
official_board[computer_input-1] = "X"
return
# Check whether there's a (list of) move(s) that would guarantee human victory
# Prevent human from winning by playing a random move out of that list and end function
# if there is no such move, move to the next part of the function
brings_human_victory = []
for field in make_list_of_free_fields(official_board):
temp_board = official_board[:]
temp_move = field
temp_board[temp_move-1] = "O"
if victory_for("O", temp_board) == True:
brings_human_victory.append(temp_move)
if brings_human_victory != []:
while True:
computer_input = randrange(10)
if computer_input in brings_human_victory:
break
official_board[computer_input-1] = "X"
return
# if you got to here, it means there were no moves that would
# guarantee computer or human victory, so
# play a random field as if you were playing on easy.
while True:
computer_input = randrange(10)
if computer_input in make_list_of_free_fields(official_board):
break
official_board[computer_input-1] = "X"
# this is how the computer plays on hard (assuming more than 2 turns available)
# the first part is the same as on medium, i.e.
# if it's possible to win, use to opportunity, if not
# check whether human will be able to win and stop him.
# if none of that is possible, don't play random (like on medium)
# but be smart (see further code and comments for details)
else:
# Check whether there's a (list of) move(s) that would guarantee computer victory
# if yes, play a random move out of that list and end the function
# if not, move to the next part of the function
brings_computer_victory = []
for field in make_list_of_free_fields(official_board):
temp_board = official_board[:]
temp_move = field
temp_board[temp_move-1] = "X"
if victory_for("X", temp_board) == True:
brings_computer_victory.append(temp_move)
if brings_computer_victory != []:
while True:
computer_input = randrange(10)
if computer_input in brings_computer_victory:
break
official_board[computer_input-1] = "X"
return
# Check whether there's a (list of) move(s) that would guarantee human victory
# Prevent human from winning by playing a random move out of that list and end function
# if there is no such move, move to the next part of the function
brings_human_victory = []
for field in make_list_of_free_fields(official_board):
temp_board = official_board[:]
temp_move = field
temp_board[temp_move-1] = "O"
if victory_for("O", temp_board) == True:
brings_human_victory.append(temp_move)
if brings_human_victory != []:
while True:
computer_input = randrange(10)
if computer_input in brings_human_victory:
break
official_board[computer_input-1] = "X"
return
# if you got to here, it means there were no moves that would
# guarantee computer or human victory, so we move to next step.
# We'll look two moves in advance to see if playing something now
# creates opportunities for later.
# We start by checking opportunities for the computer.
# We will have two new lists:
# a) one saying which moves give two winning options in the next turn.
# b) one saying which moves give one winning option in the next turn.
# if the list of moves giving 2 options is not empty, we randomly pick a move from there.
# else, if the list of moves with 1 option is not empty, we randomly draw from there.
# if we did one of the two previous options, we end the function.
# First, let's create the lists to determine which moves would give
# computer one or two winning options in the turn after.
gives_two_options = []
gives_one_option = []
for first_move in make_list_of_free_fields(official_board):
board_after_first_move = official_board[:]
board_after_first_move[first_move-1] = "X"
opportunities = 0
for second_move in make_list_of_free_fields(board_after_first_move):
board_after_second_move = board_after_first_move[:]
board_after_second_move[second_move-1] ="X"
if victory_for("X", board_after_second_move) == True:
opportunities += 1
if opportunities > 1:
gives_two_options.append(first_move)
if opportunities == 1:
gives_one_option.append(first_move)
# if there's a list of moves which would give computer two winning options,
# play a random move from that list and end function.
# If not, check whether there's list of moves which would give one
# winning option (and play randomly from there) and end function.
# If no such lists exist, go on with the code.
if gives_two_options != []:
while True:
computer_input = randrange(10)
if computer_input in gives_two_options:
break
official_board[computer_input-1] = "X"
return
if gives_one_option != []:
while True:
computer_input = randrange(10)
if computer_input in gives_one_option:
break
official_board[computer_input-1] = "X"
return
# if we're here, it means there were no good opportunities for computer.
# so let's check if there are any for the human, and then prevent them.
# Let's create the lists to determine which moves would give
# human one or two winning options in the turn after.
gives_two_options = []
gives_one_option = []
for first_move in make_list_of_free_fields(official_board):
board_after_first_move = official_board[:]
board_after_first_move[first_move-1] = "O"
opportunities = 0
for second_move in make_list_of_free_fields(board_after_first_move):
board_after_second_move = board_after_first_move[:]
board_after_second_move[second_move-1] ="O"
if victory_for("O", board_after_second_move) == True:
opportunities += 1
if opportunities > 1:
gives_two_options.append(first_move)
if opportunities == 1:
gives_one_option.append(first_move)
# if there's a list of moves which would give human two winning options,
# play a random move from that list and end function.
# If not, check whether there's list of moves which would give one
# winning option (and play randomly from there) and end function.
# If no such lists exist, go on with the code.
if gives_two_options != []:
while True:
computer_input = randrange(10)
if computer_input in gives_two_options:
break
official_board[computer_input-1] = "X"
return
if gives_one_option != []:
while True:
computer_input = randrange(10)
if computer_input in gives_one_option:
break
official_board[computer_input-1] = "X"
return
# if you got to here, it means there were no moves that would
# create meaningful opportunities for computer or the human, so
# play a random field as if you were playing on easy.
while True:
computer_input = randrange(10)
if computer_input in make_list_of_free_fields(official_board):
break
official_board[computer_input-1] = "X"
# This is the final piece of code that connects all the functions.
who_plays_first()
choose_difficulty()
clear_output()
if first_player == "human":
display_board(official_board)
while True:
human_move()
clear_output()
display_board(official_board)
if victory_for("O", official_board) == True:
print("You won!")
break
if len(make_list_of_free_fields(official_board)) == 0:
print("it's a tie")
break
computer_move()
clear_output()
display_board(official_board)
if victory_for("X", official_board) == True:
print("You lost!")
break
else:
while True:
computer_move()
clear_output()
display_board(official_board)
if victory_for("X", official_board) == True:
print("You lost!")
break
if len(make_list_of_free_fields(official_board)) == 0:
print("it's a tie")
break
human_move()
clear_output()
display_board(official_board)
if victory_for("O", official_board) == True:
print("You won!")
break
After further inspection and many tries to recreate the problem in Colab, I failed to reach anything. But then I decided to run the code on my own computer (Anaconda, Visual Studio Code, Jupiter, not sure if relevant). There, the problem occurs much more frequently (almost on every move I make). Python doesn't raise an error on its own, but the code seems to be stuck in a loop. When I stop it manually, I get this error:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
c:\Users\Divo\Downloads\TicTacToe_2.ipynb Cell 10 in <cell line: 6>()
37 print("it's a tie")
38 break
---> 39 human_move()
40 clear_output()
41 display_board(official_board)
c:\Users\Divo\Downloads\TicTacToe_2.ipynb Cell 10 in human_move()
2 def human_move():
3 while True:
----> 4 human_input = int(input("Choose a field"))
5 if human_input in make_list_of_free_fields(official_board):
6 break
ValueError: invalid literal for int() with base 10: ''
The error tells you what is wrong, you are trying to parse something that can't be interpreted as an integer, in this case an empty string ''. It is generally very dangerous to parse human input as an integer, without first checking that it can actually be converted to an integer. First you could check if it is numeric, and then if it is in the desired range (and then that it is in a free spot, like you do):
if human_input.isnumeric():
if human_input in range(1, 10):

Get a single character in Python as input without having to press Enter (Similar to getch in C++)

First of all, I am totally new in Python, having just started to learn it. I know a lot of stuff about C++ however and I am just trying to implement some of those in Python.
I have done quite a search on it but I couldn't find any solution that fits my requirement. Please see the following code,
import os
class _Getch:
"""Gets a single character from standard input. Does not echo to the
screen."""
def __init__(self):
try:
self.impl = _GetchWindows()
except:
print("Error!")
def __call__(self): return self.impl()
class _GetchWindows:
def __init__(self):
import msvcrt
def __call__(self):
import msvcrt
return msvcrt.getch()
def mainfun():
check = fh = True
while check:
fh = True
arr = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
print ("Welcome to Tic Tac Toe Game!!!\n\n")
print("Enter 1 to Start Game")
print("Enter 2 to Exit Game")
a = _Getch()
if a == "1":
while fh:
os.system("cls")
drawboard()
playermove()
fh = checkresult()
elif a == "2":
break
As you can see, What I am trying to do here is asking the user to press a number from 1 and 2 and then store that number in "a" and then use it for my requirements.
Now, I first tried using this,
input('').split(" ")[0]
But this didn't work. It required me to always Press Enter after having typed 1 or 2. So, that didn't work.
Then I found this class of Getch and I implemented it. Long story short, it entered me into a never ending loop and my result is something like this now,
Welcome to Tic Tac Toe Game!!!
Enter 1 to Start Game
Enter 2 to Exit Game
Press Enter to Continue....
Welcome to Tic Tac Toe Game!!!
Enter 1 to Start Game
Enter 2 to Exit Game
Press Enter to Continue....
Welcome to Tic Tac Toe Game!!!
Enter 1 to Start Game
Enter 2 to Exit Game
Press Enter to Continue....
And it is a never ending loop... Even if I press any key like "1" or "2", it still doesn't stop and keep on performing this and don't enter any function.
What I want is a function similar to this,
It should work on PYCHARM Console (I am practicing and I don't want to practice on Terminal. I am used to using the console of the IDE I am working on)
It pauses and waits for the user to enter any input (like input does)
It accepts and stores the very first key entered by the user into the variable. Like in this case, if user presses "1" then it should store that character in "a" and simply move on. You don't have to Press "ENTER" to move on.
If the user presses any other button like "a" or "b" or anything like this, it will simply not do anything and keep on asking for the input until the required number "1" or "2" is entered (and I think that can very easily be handled in this while loop)
In other words, I just want an alternative to getch() command of C++ in Python. I have tried a lot to find it, but I couldn't. Please refer to me a question which provides a solution to this exact question or provide a solution here. Thank you.
Edit: Please note this isn't the complete code. I have only provided the code which is relevant. If anyone needs to see the whole code, I am happy to share that as well.
Complete code is as follows,
import os
import keyboard
def getch():
alphabet = list(map(chr, range(97, 123)))
while True:
for letter in alphabet: # detect when a letter is pressed
if keyboard.is_pressed(letter):
return letter
for num in range(10): # detect numbers 0-9
if keyboard.is_pressed(str(num)):
return str(num)
arr = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
playerturn = 1
def drawboard():
global playerturn
print("Player 1 (X) - Player 2 (O)\n")
print("Turn: Player " + str(playerturn))
print("\n")
for i in range(3):
print (" ", end='')
for j in range(3):
print(arr[i][j], end='')
if j == 2:
continue
print(" | ", end='')
if i == 2:
continue
print("")
print("____|____|____")
print(" | | ")
def playermove():
global playerturn
row = col = 0
correctmove = False
print("\n\nMake your Move!\n")
while not correctmove:
row = int(input("Enter Row: "))
col = int(input("Enter Col: "))
if (3 > row > -1) and (-1 < col < 3):
for i in range(3):
for j in range(3):
if arr[row][col] == 0:
correctmove = True
if playerturn == 1:
arr[row][col] = 1
else:
arr[row][col] = 2
playerturn += 1
if playerturn > 2:
playerturn = 1
if not correctmove:
print ("Wrong Inputs, please enter again, ")
def checkwin():
for player in range(1, 3):
for i in range(3):
if arr[i][0] == player and arr[i][1] == player and arr[i][2] == player: return player
if arr[0][i] == player and arr[1][i] == player and arr[2][i] == player: return player
if arr[0][0] == player and arr[1][1] == player and arr[2][2] == player: return player
if arr[0][2] == player and arr[1][1] == player and arr[2][0] == player: return player
return -1
def checkdraw():
for i in range(3):
for j in range(3):
if arr[i][j] == 0:
return False
return True
def checkresult():
check = checkwin()
if check == 1:
os.system('cls')
drawboard()
print("\n\nPlayer 1 has won the game!!\n")
elif check == 2:
os.system('cls')
drawboard()
print("\n\nPlayer 2 has won the game!!\n")
elif check == 3:
os.system('cls')
drawboard()
print("\n\nThe game has been drawn!!\n")
else:
return True
return False
def mainfun():
check = fh = True
while check:
os.system("cls")
fh = True
arr = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
print ("Welcome to Tic Tac Toe Game!!!\n\n")
print("Enter 1 to Start Game")
print("Enter 2 to Exit Game")
a = getch()
if a == "1":
while fh:
os.system("cls")
drawboard()
playermove()
fh = checkresult()
elif a == "2":
break
print ("Press any key to continue...")
getch()
mainfun()
EDIT2: Problem is resolved by using Keyboard module... The next issue here is how do I remove the data stored in input buffer after the getch() function is called? Because the data in buffer is getting displayed on the next input (when I am taking in the row and column) and I don't want that to happen. I fonud a solution for Linux but not for Windows (or for Pycharm)
It looks like this feature isn't in the standard python library but you can recreate it.
First, install the module 'keyboard'
$ pip3 install keyboard
Then you can use keyboard.is_pressed() to see if any one character is pressed.
import keyboard # using module keyboard
import string # use this to get the alphabet
print("Input a character")
def getch():
alphabet = list(string.ascii_lowercase)
while True:
for letter in alphabet: # detect when a letter is pressed
if keyboard.is_pressed(letter):
return letter
for num in range(10): # detect numbers 0-9
if keyboard.is_pressed(str(num)):
return str(num)
answer = getch()
print("you choose " + answer)
Edit: For unix you need to run with the script with sudo. This code should work fine on windows.
For EDIT-2:
Use below code to flush the screen:
sys.stdout.flush()

How do I eliminate the "'str' object is not callable"?

I get the following error on the code below, and have no idea what is going on. I'm very much a beginner and need some help. I am trying to make a very basic game of tic-tac-toe in the console, and am having trouble.
Traceback (most recent call last):
File "D:/Eric/Projects/Tic Tac Toe/Tic Tac Toe.py", line 68, in <module>
printboard()
File "D:/Eric/Projects/Tic Tac Toe/Tic Tac Toe.py", line 15, in printboard
print("",c[0],"|",c[1],"|",c[2],"\n-----------\n",c[3],"|",c[4],"|",c[5],"\n-----------\n",c[6],"|",c[7],"|",c[8])
TypeError: 'str' object is not callable
Code:
import random, time
#Variables
c = [str(i) for i in range(1,10)] #Cells
cpuletter = "string input"
coinoptions = ["heads", "tails"]
coinflip = random.choice(coinoptions)
play = ""
playercell = 0
#Functions
def printboard(): #Prints the gameboard with the cell variables in the spaces
print("",c[0],"|",c[1],"|",c[2],"\n-----------\n",c[3],"|",c[4],"|",c[5],"\n-----------\n",c[6],"|",c[7],"|",c[8])
return
#Introduction
print("Welcome to Tic Tac Toe. Below is the playing table.") #Welcome + Explanation
printboard()
print("The playing spaces are numbered 1 through 9.\nYou will use these numbers to refer to the places you would like to play your piece.\n")
#X or O?
playerletter = input("Would you like to be X's or O's?\n")
playerletter = playerletter.capitalize()
playerletter = playerletter[0]
while playerletter not in ["X", "O"]: #Confirm choice == "X" or "O." If not, ask again.
playerletter = input("""Sorry, that's not a valid option. Please choose "X" or "O."\n""")
playerletter = playerletter.capitalize()
playerletter = playerletter[0]
if playerletter == "X":
cpuletter = "O"
elif playerletter == "O":
cpuletter = "X"
#Who goes first?
playercoin = input("Randomizing who goes first:\nDo you choose heads or tails?\n") #Asking for "heads" or "tails"
playercoin = playercoin.lower()
while playercoin not in ["heads", "tails"]: #Confirm choice == "Heads" or "Tails." If not, ask again.
playercoin = input("""Sorry, that's not a valid option. Please choose "heads" or "tails."\n""")
playercoin = playercoin.lower()
print("...")
time.sleep(1) #Waits 1 seconds
if coinflip != playercoin: #Tells player who goes first
print("It landed " + coinflip + "! I will go first.")
play = 0
elif coinflip == playercoin:
print("It landed " + coinflip + "! You will go first.")
play = 1
#Game
input("""Ready to play? Press "Enter" to begin!\n""")
if play == 0:
random_index = random.randrange(9) #Randomly selects a cell to change to cpuletter
c[random_index] = cpuletter
print = ("Here is my move.")
printboard()
elif play == 1: #Allows player to choose cell to change to playerletter
printboard()
playercell = int(input("It's your turn. Type a cell number to choose where you play.\n"))
playercell = playercell - 1
c[playercell] = playerletter
printboard()
Edit: Forgot to say that this only happens when the computer goes first, and not the player. I fixed the print = ("Here is my move.") but am still having problems.
print = "Here is my move."
That line reassigns the builtin print function to a string. Don't do that.
Why make such a complex printing function? Format would come very handy right about now:
def printboard(): #Prints the gameboard with the cell variables in the spaces
table = \
'''
{} | {} | {}
----------
{} | {} | {}
----------
{} | {} |
'''
print(table.format(c[1],c[2],c[3],c[4],c[5],c[6],c[7],c[8]))
return
And finally to fix your error, change line 65:
move = ("Here is my move")
I ran your code, but I did not get any errors. This particular TypeError is usually caused by programmers mistakenly switching out square brackets with parentheses (therefore "calling" it as if the string was a function, which it's not.). Please check and run your code again.
EDIT: Solution: Change the variable name of print = "Here is my move." on line 65 to something else, like movePrint = "Here is my move".

Checking for a draw in Tic Tac Toe [Python]

I have this Python program that plays tic tac toe between two human players. If Player A or Player B ever wins, it is announced and the program terminates. However, if the program ends in a draw, it will keep requesting user input.
I'm not sure how to check for a draw. Does it have to be within the while loop or does it require it's own separate function?
import sys
## Define and create tic tac toe gameboard
board = range(0,9)
def show_board():
print board[0], '|', board[1], '|', board[2]
print '---------'
print board[3], '|', board[4], '|', board[5]
print '---------'
print board[6], '|', board[7], '|', board[8]
# Function used to check for winner
def line(char, box1, box2, box3):
if board[box1] == char and board[box2] == char and board[box3] == char:
return True
# Function used to automate process for checking every possible way to win
def all(char):
# Horizontal check
if line(char, 0, 1, 2):
return True
if line(char, 3, 4, 5):
return True
if line(char, 6, 7, 8):
return True
# Vertical check
if line(char, 0, 3, 6):
return True
if line(char, 1, 4, 7):
return True
if line(char, 2, 5, 8):
return True
# Diagnol check
if line(char, 0, 4, 8):
return True
if line(char, 2, 4, 6):
return True
show_board()
# Initial while loop will ask for player A input and show the board as well
# check conditions to see whether or not player A wins. If player A wins,
# the program will terminate so it does not ask for player B input after.
while True:
player_a = int(raw_input('Player A, please select a spot that is not taken \
(0-8): '))
# Checks for empty spot and places an 'X' if it exists, otherwise
# asks again.
if board[player_a] != 'X' and board[player_a] != 'O':
board[player_a] = 'X'
show_board()
# Check to see if Player A wins.
if all('X') == True:
print "Player A wins."
sys.exit()
break;
# While loop to ask for player B input and display the board as well as check
# the conditions as to whether or not player B wins. If player B wins, the
# program will terminate so it does not ask for player A input after.
while True:
player_b = int(raw_input('Player B, please select a spot that is \
not taken (0-8): '))
# Checks for empty spot and places an 'O' if it exists, otherwise
# asks again.
if board[player_b] != 'O' and board[player_b] != 'X':
board[player_b] = 'O'
# Check to see if Player B wins.
if all('O') == True:
show_board()
print "Player B wins."
sys.exit()
break;
break;
show_board()
Without extensively going through the code, I can tell you that a draw is occurs after 9 turns, and only if both Player A and B do not receive a win on that final turn. For your simple program, what I would do is create a global variable called ELAPSED_TURNS or something of the sort, that increments each time a player enters a character, and then after checking both of the players' win conditions, and if there is no win, check ELAPSED_TURNS. If it is equal to 9, then the game must be a draw.
Here's the function that does what you want.
def is_tie():
for position in board:
if isinstance(position, int):
return False
print "The game is a tie."
sys.exit()
Put a call to is_tie() directly after both while loops like this...
while True:
is_tie()
player_a = int(raw_input(...
while True:
is_tie()
player_b = int(raw_input(...
If this is a learning exercise for you I would recommend refactoring your code to find a way wrap all your logic blocks into functions and getting everything to flow without the use of sys.exit(). Doing so will increase the readability and make it easier to splice in new logic.
EDIT to your comment:
You can create an integer test function using just try / except statements like this...
def is_int(s):
try:
int(s)
return True
except ValueError:
return False
Credit here: Python: Check if a string represents an int, Without using Try/Except?
Your is_tie() function would then look like this:
def is_tie():
for position in board:
if is_int(position):
return False
print "The game is a tie."
sys.exit()

Beginner to Python - why the heck is my while loop not working?

I am trying to write a program for an assignment where you input a specific command and you can play Rock-Paper-Scissors-Lizard-Spock against the computer.
It was done and working until I realized that the assignment instructions wanted me to make it so that you keep playing the game until one person gets five wins.
So I thought, no big deals, let's throw in a while loop and some variables to track the wins. But when I run the program, it only runs once still. I don't know what I am doing wrong - as this should work. This is my first time working with Python (version 3.3) and this IDE, so I really need some help. Usually I'd just debug but I can't figure out how to work the one in this IDE.
Here is my code. The trouble while-loop is at the way bottom. I am nearly positive everything inside the class works. I would like to note that I already tried while(computerWins < 5 and userWins < 5), so I don't think the condition is the problem.
import random
computerWins = 0
userWins = 0
print ('SELECTION KEY:\nRock = r\nPaper = p\nScissors = sc\nLizard = l\nSpock = sp')
class rockPaperScissorsLizardSpock:
#Two methods for converting from strings to numbers
#convert name to number using if/elif/else
#also converts abbreviated versions of the name
def convertName(name):
if(name == 'rock' or name == 'r'):
return 0
elif(name == 'Spock' or name == 'sp'):
return 1
elif(name == 'paper' or name == 'p'):
return 2
elif(name == 'lizard' or name == 'l'):
return 3
elif(name == 'scissors' or name == 'sc'):
return 4
else:
print ('Error: Invalid name')
#convert number to a name using if/elif/else
def convertNum(number):
if(number == 0):
return 'rock'
elif(number == 1):
return 'Spock'
elif(number == 2):
return 'paper'
elif(number == 3):
return 'lizard'
elif(number == 4):
return 'scissors'
else:
print ('Error: Invalid number')
#User selects an option, and their selection is saved in the 'choice' variable
#Using a while loop so that the user cannot input something other than one of the legal options
prompt = True
while(prompt):
i = input('\nEnter your selection: ')
if(i=='r' or i=='p' or i=='sc' or i=='l' or i=='sp'):
prompt = False
else:
print('Invalid input.')
prompt = True
#Convert the user's selection first to a number and then to its full string
userNum = convertName(i)
userChoice = convertNum(userNum)
#Generate random guess for the computer's choice using random.randrange()
compNum = random.randrange(0, 4)
#Convert the computer's choice to a string
compChoice = convertNum(compNum)
print ('You chose', userChoice)
print ('The computer has chosen', compChoice)
#Determine the difference between the players' number selections
difference = (compNum - userNum) % 5
#Use 'difference' to determine who the winner of the round is
if(difference == 1 or difference == 2):
print ('The computer wins this round.')
computerWins = computerWins+1
elif (difference == 4 or difference == 3):
print ('You win this round!')
userWins = userWins+1
elif(difference == 0):
print ('This round ended up being a tie.')
#Plays the game until someone has won five times
while(computerWins != 5 and userWins != 5):
rockPaperScissorsLizardSpock()
if(computerWins == 5 and userWins != 5):
print ('The computer wins.')
elif(computerWins != 5 and userWins == 5):
print ('You win!')
The essential problem is that rockpaperscissorslizardspock is a class, where you expect it to be a function. The code inside it runs exactly once, when the whole class definition is parsed, rather than each time you call the class as you seem to expect.
You could put the relevant code into an __init__ method - this is a fairly direct analogue of a Java constructor, and hence is is run each time you call the class. But in this case, you probably don't need it to be in a class at all - calling the class creates a new instance (like doing new MyClass() in Java), which you don't use. You would also in this case (or if you made it into a function) need to make some more modifications to make sure the game state persists properly.
The easiest actual solution is to:
delete the line class rockpaperscissorslizardspock: (and unindent everything below it)
Take all the code that was under the class but not in a function - everything from the player makes a selection to determining the winner of the round - and paste it in place of the call to rockpaperscissorslizardspock() in the bottom loop.
The first thing is that you are using a class where you should probably be using a function.
Your code initially runs because python is loading the class.
However, the line rockPaperScissorsLizardSpock() is creating new anonymous instances of your class which calls a constructor that you haven't defined so it does nothing.
One of the interesting things about python is that it allows nested functions so if you change the class to a def you're almost there.
After that, you'll run into trouble with global variables in a local context. That problem is already explained in another StackOverflow question: Using global variables in a function other than the one that created them.
Here is my suggestion for the skeleton to a more simple solution. Use some ideas from here if you like.
import random
legal_shapes = ['r', 'p', 'sc', 'sp', 'l']
scoreboard = [0, 0]
print('SELECTION KEY:\nRock = r\nPaper = p\nScissors = sc\nLizard = l\n'
'Spock = sp')
while(max(scoreboard) < 5):
print("\nScore is {}-{}".format(*scoreboard))
# pick shapes
p1_shape = input('Enter your selection: ')
if p1_shape not in legal_shapes:
print('Not legal selection!')
continue
p2_shape = random.choice(legal_shapes)
print('\np1 plays {} and p2 plays {}'.format(
p1_shape.upper(), p2_shape.upper()))
# determine int values and result indicator
p1_shape_int = legal_shapes.index(p1_shape)
p2_shape_int = legal_shapes.index(p2_shape)
res = (p1_shape_int - p2_shape_int) % 5
if res != 0:
res = abs((res % 2) - 2)
# Print winner
if res == 0:
print(' -> Draw!!')
else:
print(' -> p{} wins'.format(res))
scoreboard[res-1] += 1
print("\nThe game is over!!")
print("p{} won with score {}-{}".format(res, *scoreboard))
It outputs something like
(env)➜ tmp python3 rsp.py
SELECTION KEY:
Rock = r
Paper = p
Scissors = sc
Lizard = l
Spock = sp
Score is 0-0
Enter your selection: T
Not legal selection!
Score is 0-0
Enter your selection: l
p1 plays L and p2 plays SP
-> p2 wins
Score is 0-1
Enter your selection: l
p1 plays L and p2 plays SC
-> p2 wins
...
The game is over!!
p2 won with score 2-5

Categories

Resources