putting in a loop and how to repeat - python

I've just started learning and I've only learnt the basics but this is my current code. I need to put it in a loop and ask the user to place the number for up to 8 times.
num_list = ['1','2','3','4','5',]
import random
num = random.choice(num_list)
table = [[' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ']]
ss = {"W1":[0,0],
"W2":[1,0],
"W3":[2,0],
"W4":[3,0],
"X1":[0,1],
"X2":[1,1],
"X3":[2,1],
"X4":[3,1],
"Y1":[0,2],
"Y2":[1,2],
"Y3":[2,2],
"Y4":[3,2],
"Z1":[0,3],
"Z2":[1,3],
"Z3":[2,3],
"Z4":[3,3]}
ans = input('where would you like to place it: ')
index_ = ss[ans][0]
columns_ = ss[ans][1]
table[index_][columns_] = num
print(table)
This code below here is supposed to make sure the user is placing the number adjacent to another number.
How do I make sure it only starts to check on the 2nd turn onwards? And how do I get it to repeat the turn if it is not adjacent? I also wanted to put the code above into functions and call it at the end to make it neater but I'm not sure what to put in and what to not.
def moveandclip(n, x, y):
n[0] = max(0, min(n[0] + x, 3))
n[1] = max(0, min(n[1] + y, 3))
return n
above = moveandclip(ss[ans], 0 ,1)
below = moveandclip(ss[ans], 0 ,-1)
left = moveandclip(ss[ans], -1 ,0)
right = moveandclip(ss[ans], 1 ,0)
if above == '' and below == '' and left == '' and right == '':
print('It must be placed adjacent to another number.')
repeat the turn
else:
continue to next turn

If you want to run the code 8 times, you can do like this:
def moveandclip(n, x, y):
n[0] = max(0, min(n[0] + x, 3))
n[1] = max(0, min(n[1] + y, 3))
return n
above = moveandclip(ss[ans], 0 ,1)
below = moveandclip(ss[ans], 0 ,-1)
left = moveandclip(ss[ans], -1 ,0)
right = moveandclip(ss[ans], 1 ,0)
for _ in range(8):
if above == '' and below == '' and left == '' and right == '':
print('It must be placed adjacent to another number.')
else:
# Do whatever you want to
# Add more code if you want to run some more statements regardless of the condition

while True:
# Turn code
if above == '' and below == '' and left == '' and right == '':
print('It must be placed adjacent to another number.')
else:
break

Related

I try to do a TicTacToe project myself, but the py close after i enter the very first input

the window of game.py I try out some of the python beginner project to practise my sense of coding.
And after i followed the youtube video step by step, i started to debug and play the
TicTacToe. It closed right after i input my first square/input. But i don't understand
where it goes wrong. I just start fighting with coding, i don't mind to get slap right out
of my face right now. Please, go easy on me. It keeps drive me to the wall.
#Player.py ||||
import math
import random
class Player:
def __init__(self,letter):
self.letter = letter
def get_move(self,game):
pass
class RandomComputerPlayer(Player):
def __init__(self, letter):
super().__init__(letter)
def get_move(self,game):
square = random.choice(game.available_moves())
return square
class HumanPlayer(Player):
def __init__(self, letter):
super().__init__(letter)
def get_move(self,game):
valid_square = False
val = None
while not valid_square:
square = input(self.letter + '\'s turn. Input move (0-8):')
try:
val = int(square)
if val not in game.available_moves():
raise ValueError
valid_square = True
except ValueError:
print('Invalid square. Try again.')
return val
And here's game.py:
#game.py ||||
import time
from player import HumanPlayer, RandomComputerPlayer
class TicTacToe:
def __init__(self):
self.board = [' ' for _ in range(9)]
self.current_winner = None
def print_board(self):
for row in [self.board[i*3:(i+1)*3] for i in range(3)]:
print('| ' + ' | ' .join(row) + ' |')
#staticmethod
def print_board_nums():
# 0 | 1 | 2 etc
number_board = [[str(i) for i in range(j*3, (j+1)*3)] for j in range (3)]
for row in number_board:
print('| ' + ' | '.join(row) + ' |')
def available_moves(self):
moves = []
for (i, x) in enumerate(self.board):
if spot == ' ':
moves.append(i)
def empty_squares(self):
return ' ' in self.board
def num_empty_squares(self):
return len(self.available_moves())
def make_move(self, square, letter):
if self.board[square] == ' ':
self.board[square] = letter
if self.winner(square, letter):
self.current_winner = letter
return True
return False
def winner(self, square, letter):
# winner if 3 in a row anywhere, check all of the possiblity
row_ind = square // 3
row = self.board[row_ind*3 : (row_ind + 1) * 3]
if all ([spot == letter for spot in row]):
return True
col_ind = square % 3
column = [self.board[col_ind + i*3] for i in range(3)]
if all ([spot == letter for spot in column]):
return True
# check diagonals
if square % 2 == 0:
diagonal1 = [self.board[i] for i in[0,4,8]]
if all ([spot == letter for spot in diagonal1]):
return True
diagonal2 = [self.board[i] for i in[2,4,6]]
if all ([spot == letter for spot in diagonal2]):
return True
# if all of the possibility not happen
return False
def play(game, x_player, o_player, print_game = True):
# returns the winner of the game! or None for a tie
if print_game:
game.print_board_nums()
letter = 'X'
while game.empty_squares():
if letter == '0':
square = o_player.get_move(game)
else:
square = x_player.get_move(game)
if game.make_move(square, letter):
if print_game:
print(letter + ' makes a move to square {square}')
game.print_board()
print('') # empty line
if game.current_winner:
if print_game:
print(letter + 'wins!')
return letter
letter = 'O' if letter == 'X' else 'X'
# if letter == 'X':
# letter = 'O'
# else:
# letter = 'X'
time.sleep(0.8)
if print_game:
print('It\'s a tie!')
if __name__ == '__main__':
x_player = HumanPlayer('X')
o_player = RandomComputerPlayer('O')
t = TicTacToe()
play(t, x_player, o_player, print_game = True)
When I copied the code and ran it locally on my computer, the traceback showed that there was an error in game.py, specifically in your available_moves() function.
def available_moves(self):
moves = []
for (i, x) in enumerate(self.board):
if spot == ' ':
moves.append(i)
The traceback specifically says, NameError: name 'spot' is not defined, which is true since spot is not defined. I am assuming spot and x are supposed to mean the same here since you are looking at the square on your Tic-Tac-Toe board. Also, this function should probably return moves; otherwise, any other function calling available_moves() is going to get a value of type None instead of the list of available moves.
def available_moves(self):
moves = []
# iterate through all spots on board
for (i, spot) in enumerate(self.board):
# if a spot is empty, add its index to moves
if spot == ' ':
moves.append(i)
return moves
Also I've been absolutely crushing myself against myself playing this game so thanks for that!
Edit: Just noticed after posting this that Tim Roberts basically summed up my answer. Oops.

why are my winning conditions not respected (tictactoe)

total begginner here.
I am trying to write a complete tic-tac-toe program based on the automate boring stuff exercise. I got it working before like this:
theBoard = {'top-L': ' ', 'top-M': ' ', 'top-R': ' ',
'mid-L': ' ', 'mid-M': ' ', 'mid-R': ' ',
'low-L': ' ', 'low-M': ' ', 'low-R': ' '}
def printBoard(board): #function to print board
print(board['top-L'] + '|' + board['top-M'] + '|' + board['top-R'])
print('-+-+-')
print(board['mid-L'] + '|' + board['mid-M'] + '|' + board['mid-R'])
print('-+-+-')
print(board['low-L'] + '|' + board['low-M'] + '|' + board['low-R'])
print('''
Hi! This is my tic-tac-toe text based game.
To make your move, write where you want to play:
top-L top-M top-R
mid-L mid-M mid-R
low-L low-M low-R
''')
turn= 'X' #starting
while True:
printBoard(theBoard)
print(f'Turn for {turn}. Where will you play?')
try:
move = input()
if theBoard[move] == ' ':
theBoard[move] = turn
if turn == 'X':
turn = 'O'
else:
turn = 'X'
else:
print('That move is not possible!')
continue
except KeyError:
print('''Wrong input.
To make your move, write where you want to play:
top-L top-M top-R
mid-L mid-M mid-R
low-L low-M low-R
''')
continue
if ((theBoard['top-L']==theBoard['top-M']==theBoard['top-R']) and theBoard['top-L']!=' ')\
or ((theBoard['mid-L']==theBoard['mid-M']==theBoard['mid-R']) and theBoard['mid-R']!=' ')\
or ((theBoard['low-L']==theBoard['low-M']==theBoard['low-R']) and theBoard['low-L']!=' ')\
or ((theBoard['top-L']==theBoard['mid-M']==theBoard['low-R']) and theBoard['top-L']!=' ')\
or ((theBoard['low-L']==theBoard['mid-M']==theBoard['top-R']) and theBoard['low-L']!=' ')\
or ((theBoard['top-L']==theBoard['mid-L']==theBoard['low-L']) and theBoard['top-L']!=' ')\
or ((theBoard['top-M']==theBoard['mid-M']==theBoard['low-M']) and theBoard['top-M']!=' ')\
or ((theBoard['top-R']==theBoard['mid-R']==theBoard['low-R']) and theBoard['top-R']!=' '):
break
if turn == 'X':
turn = 'O'
else:
turn = 'X'
print(f'Good Job {turn}, you won!')
This worked well and i turned to codereview for some improvements.
I stored the strings 'X' and 'O' as I discovered that those were considered magic strings and make my code less clean.
Next, I wanted to store all the win conditions in a variable called conditions. But when I do this my program will now not get out of the loop when I get a winning move. Why could this be?
theBoard = {'top-L': ' ', 'top-M': ' ', 'top-R': ' ',
'mid-L': ' ', 'mid-M': ' ', 'mid-R': ' ',
'low-L': ' ', 'low-M': ' ', 'low-R': ' '}
def printBoard(board):
print(board['top-L'] + '|' + board['top-M'] + '|' + board['top-R'])
print('-+-+-')
print(board['mid-L'] + '|' + board['mid-M'] + '|' + board['mid-R'])
print('-+-+-')
print(board['low-L'] + '|' + board['low-M'] + '|' + board['low-R'])
conditions = (((theBoard['top-L'] == theBoard['top-M'] == theBoard['top-R']) and theBoard['top-L'] != ' ') \
or ((theBoard['mid-L'] == theBoard['mid-M'] == theBoard['mid-R']) and theBoard['mid-R'] != ' ') \
or ((theBoard['low-L'] == theBoard['low-M'] == theBoard['low-R']) and theBoard['low-L'] != ' ') \
or ((theBoard['top-L'] == theBoard['mid-M'] == theBoard['low-R']) and theBoard['top-L'] != ' ') \
or ((theBoard['low-L'] == theBoard['mid-M'] == theBoard['top-R']) and theBoard['low-L'] != ' ') \
or ((theBoard['top-L'] == theBoard['mid-L'] == theBoard['low-L']) and theBoard['top-L'] != ' ') \
or ((theBoard['top-M'] == theBoard['mid-M'] == theBoard['low-M']) and theBoard['top-M'] != ' ') \
or ((theBoard['top-R'] == theBoard['mid-R'] == theBoard['low-R']) and theBoard['top-R'] != ' '))
print('''
Hi! This is my tic-tac-toe text based game.
To make your move, write where you want to play:
top-L top-M top-R
mid-L mid-M mid-R
low-L low-M low-R
''')
playerX = 'X'
playerO = 'O'
turn= playerX
while True:
printBoard(theBoard)
print(f'Turn for {turn}. Where will you play?')
try:
move = input()
if theBoard[move] == ' ':
theBoard[move] = turn
if turn == playerX:
turn = player0
else:
turn = playerX
else:
print('That move is not possible!')
continue
except KeyError:
print('''Wrong input.
To make your move, write where you want to play:
top-L top-M top-R
mid-L mid-M mid-R
low-L low-M low-R
''')
continue
if conditions == True:
printBoard(theBoard)
break
if turn == playerX:
turn = player0
else:
turn = playerX
print(f'Good Job {turn}, you won!')
That is because conditions is a bool value. It is calculated when it is set. That is to say - it not a function that makes its computations when it is called. In your case conditions is set to False and it will remain to be False. It is a constant.
Wrap it in a function like this:
def check():
conditions = (((theBoard['top-L'] == theBoard['top-M'] == theBoard['top-R']) and theBoard['top-L'] != ' ') \
or ((theBoard['mid-L'] == theBoard['mid-M'] == theBoard['mid-R']) and theBoard['mid-R'] != ' ') \
or ((theBoard['low-L'] == theBoard['low-M'] == theBoard['low-R']) and theBoard['low-L'] != ' ') \
or ((theBoard['top-L'] == theBoard['mid-M'] == theBoard['low-R']) and theBoard['top-L'] != ' ') \
or ((theBoard['low-L'] == theBoard['mid-M'] == theBoard['top-R']) and theBoard['low-L'] != ' ') \
or ((theBoard['top-L'] == theBoard['mid-L'] == theBoard['low-L']) and theBoard['top-L'] != ' ') \
or ((theBoard['top-M'] == theBoard['mid-M'] == theBoard['low-M']) and theBoard['top-M'] != ' ') \
or ((theBoard['top-R'] == theBoard['mid-R'] == theBoard['low-R']) and theBoard['top-R'] != ' '))
return conditions
And call this function instead of conditions in the if statement:
if check() == True:
printBoard(theBoard)
break

Replace a single character in a string

I am trying to make a function that automatically generated a response to a selection of an action in a text adventure game. My problem is that I have to replace every second '_' with ' '. However I have tried everything I have though of and whenever I google the question the only solution I get is to use .replace(). However .replace() replaces every instance of that character. Here is my code, could you please fix this for me and explain how you fixed it.
example_actions = ['[1] Search desk', '[2] Search Cupboard', '[3] Search yard'
def response(avaliable_actions):
for i in avaliable_actions:
print(i, end=' ')
x = avaliable_actions.index(i)
avaliable_actions[x] = avaliable_actions[x][4:]
avaliable_actions = ' '.join(avaliable_actions)
avaliable_actions = avaliable_actions.lower()
avaliable_actions = avaliable_actions.replace(' ', '_')
avaliable_actions = list(avaliable_actions)
count = 0
for i in avaliable_actions:
if count == 2:
count = 0
index = avaliable_actions.index(i)
avaliable_actions[index] = ' '
elif i == '_':
count += 1
avaliable_actions = ' '.join(avaliable_actions)
print('\n\n' + str(avaliable_actions)) #error checking
Here's one approach:
s = 'here_is_an_example_of_a_sentence'
tokens = s.split('_')
result = ' '.join('_'.join(tokens[i:i+2]) for i in range(0,len(tokens),2))
print(result)
The result:
here_is an_example of_a sentence
Did I understand you correct, that you wanna produce something like this?
this_is_a_test -> this is_a test or this_is a_test?
If so, adapt the following for your needs:
s = "this_is_just_a_test"
def replace_every_nth_char(string, char, replace, n):
parts = string.split(char)
result = ""
for i, part in enumerate(parts):
result += part
if i % n == 0:
result += replace
else:
result += char
return ''.join(result)
res = replace_every_nth_char(s, "_", " ", 2)
print(s, "->", res)
# "this_is_just_a_test" -> "this is_just a_test"

python - how to print Tic Tac Toe game board using for loop

I am new to python. Would like to print the game board for the tic tac toe. May I know how to print using for loop?
Here is my code:
`
board = {
1: ' ', 2: ' ', 3: ' ',
4: ' ', 5: ' ', 6: ' ',
7: ' ', 8: ' ', 9: ' '
}
def printBoard():
print(board[1] + '|'+ board[2]+'|'+board[3])
print('-----')
print(board[4] + '|'+board[5]+'|' + board[6])
print('-----')
print(board[7] + '|'+board[8]+'|' + board[9])
return
`
Your code is fine. You just need to call the function at the end of the script so that it actually gets executed. And the return keyword is not needed as the function doesn't return any value, only prints the board.
board = {
1: ' ', 2: ' ', 3: ' ',
4: ' ', 5: ' ', 6: ' ',
7: ' ', 8: ' ', 9: ' '
}
def printBoard():
print(board[1] + '|'+ board[2]+'|'+board[3])
print('-----')
print(board[4] + '|'+board[5]+'|' + board[6])
print('-----')
print(board[7] + '|'+board[8]+'|' + board[9])
printBoard()
You can make a Tic Tac Toe game using the folowing code :
import random
class TicTacToe:
def __init__(self):
self.board = []
def create_board(self):
for i in range(3):
row = []
for j in range(3):
row.append('-')
self.board.append(row)
def get_random_first_player(self):
return random.randint(0, 1)
def fix_spot(self, row, col, player):
self.board[row][col] = player
def is_player_win(self, player):
win = None
n = len(self.board)
# checking rows
for i in range(n):
win = True
for j in range(n):
if self.board[i][j] != player:
win = False
break
if win:
return win
# checking columns
for i in range(n):
win = True
for j in range(n):
if self.board[j][i] != player:
win = False
break
if win:
return win
# checking diagonals
win = True
for i in range(n):
if self.board[i][i] != player:
win = False
break
if win:
return win
win = True
for i in range(n):
if self.board[i][n - 1 - i] != player:
win = False
break
if win:
return win
return False
for row in self.board:
for item in row:
if item == '-':
return False
return True
def is_board_filled(self):
for row in self.board:
for item in row:
if item == '-':
return False
return True
def swap_player_turn(self, player):
return 'X' if player == 'O' else 'O'
def show_board(self):
for row in self.board:
for item in row:
print(item, end=" ")
print()
def start(self):
self.create_board()
player = 'X' if self.get_random_first_player() == 1 else 'O'
while True:
print(f"Player {player} turn")
self.show_board()
# taking user input
row, col = list(
map(int, input("Enter row and column numbers to fix spot: ").split()))
print()
# fixing the spot
self.fix_spot(row - 1, col - 1, player)
# checking whether current player is won or not
if self.is_player_win(player):
print(f"Player {player} wins the game!")
break
# checking whether the game is draw or not
if self.is_board_filled():
print("Match Draw!")
break
# swapping the turn
player = self.swap_player_turn(player)
# showing the final view of board
print()
self.show_board()
# starting the game
tic_tac_toe = TicTacToe()
tic_tac_toe.start()
You can use two generator expression, one for row and one for each cell. You can add the separators by using the generators in join()
def print_board():
print('\n-----\n'.join(('|'.join(board[i + j] for i in range(1, 4)) for j in range(0, len(board), 3))))

Python input statement

I have created a battleship like game, and have it all completed except for one detail.
I have the following input statement:
x, y = input("Enter two numbers here: ").split()
with the 2 numbers being entered corresponding to the players chosen coordinates. I also need to be able to handle the entry of 'q' or 'h' for the quit or help options. However, since i am taking two variables from this statement when only a q or h is entered i get the error that the statement needs 2 elements to unpack, which makes sense. Any pointers on how to get around this?
import random, math
class oceanTreasure:
def __init__(self):
self.board = self.board()
self.found = 0
self.left = 3
self.sonarsLeft = 20
self.chests= []
self.chest()
def board(self):
board = []
for x in range(16): # the main list is a list of 60 lists
board.append([])
for y in range(61): # each list in the main list has 15 single-character strings.
board[x].append('~')
return board
def chest(self):
chest1 = [random.randint(0,60), random.randint(0,15)]
chest2 = [random.randint(0,60), random.randint(0,15)]
chest3 = [random.randint(0,60), random.randint(0,15)]
self.chests = [chest1, chest2, chest3]
def getChestsLeft(self):
return self.found
def getChests(self):
return self.chests
def getTreasuresLeft(self):
return self.left
def getSonarsLeft(self):
return self.sonarsLeft
def dropSonar(self,x,y):
ySonar = ['a','b','c','d','e','f','g']
whichAxis, axis = self.checkDistance(x,y)
if whichAxis == True:
sonar = axis
if whichAxis == 'xaxis':
sonar = axis
elif whichAxis == 'yaxis':
sonar = ySonar[axis-1]
elif whichAxis == None:
sonar = axis
self.board[int(y)][int(x)] = sonar
self.sonarsLeft -=1
return axis
def checkDistance(self,x,y):
closest = self.chests[0]
distance = 100
for chest in self.chests:
temp = math.sqrt(math.pow((chest[0]-int(x)),2) + math.pow((chest[1]-int(y)),2))
if temp < distance:
closest = chest
distance = temp
xaxis =math.fabs((closest[0] - int(x)))
yaxis = math.fabs((closest[1]-int(y)))
if yaxis == 0 and xaxis == 0:
self.chests.remove(closest)
self.found +=1
self.left -=1
return True, 'X'
elif xaxis <= 9 and yaxis <=5 :
if yaxis == 0 :
return 'xaxis',int(math.fabs(xaxis))
if xaxis == 0 :
return 'yaxis',int(math.fabs(yaxis))
if min(xaxis//2,yaxis) ==(xaxis//2) :
return 'xaxis', int(math.fabs(xaxis))
elif min(xaxis//2,yaxis) == (yaxis) or xaxis == 0 :
return 'yaxis', int(math.fabs(yaxis))
else: return None,0
def drawBoard(self):
firstLine = ' '
for i in range(1,7):
firstLine += (' '*9) + str(i)
print(firstLine)
secondLine = ' '
secondLine += ('0123456789' *6)
print(secondLine)
print()
i = 0
for i in range(0,16):
boardRow = ''
for x in range(0,61):
boardRow += str(self.board[i][x])
if i < 10:
print(str(i) +' ' + str(boardRow) + str(i))
if i >= 10:
print(str(i) +' ' + str(boardRow) + str(i))
print()
print(secondLine)
print(firstLine)
device = 'devices'
if self.sonarsLeft ==1:
device = 'device'
print('You have %s sonar %s availabe. You have found %s treasures and have %s left' %(self.sonarsLeft, device, self.found, self.left))
ocean = oceanTreasure()
ocean.drawBoard()
gameOver = False
instructionsList = ['This is a treasure hunting game.' , 'You begin the game with 20 sonar devices available (each device has a range of 9 units in the x axis and 5 in the y axis).','When you place a device, if an "O" is displayed that means there are no chests in range.', 'If a number from 1-9 is displayed, the closest chest is within n units away on the X axis.', 'If a letter from a-e is displayed, the closest chest is n units away on the Y axis (a =1, b =2 and so on...).', 'The game ends when you run out of sonar devices, all the treasure is found or you enter "q" to quit.', 'Thanks for playing and happy hunting!']
while ocean.getTreasuresLeft() != 0 and ocean.getSonarsLeft() >0 and gameOver == False:
response = False
coordinate = False
while response == False:
inputString = input("Enter two numbers seperated by a space (X Y): ")
if inputString == 'q':
gameOver = True
response = True
elif inputString == 'h':
for instruction in instructionsList:
print(instruction)
response = True
else:
try:
x,y = inputString.split()
assert int(x) <=60 and int(y) <=15
response = True
coordinate = True
except AssertionError:
print('Please enter a valid move')
if gameOver == True:
break
#whichAxis, axis =ocean.checkDistance(x,y)
#print(axis)
if coordinate == True:
axis = ocean.dropSonar(x,y)
ocean.drawBoard()
if axis == 'X':
print('Congratulations, you have found a treasure!')
if ocean.getTreasuresLeft() == 0:
print('Congratulations, you found all the treasure')
elif ocean.getSonarsLeft() == 0:
print('Sorry, you ran out of sonar devices, the remaining chests were: %s ' % str(ocean.getChests()))
How about separating the tests to be a little clearer:
input_string = input("Enter two numbers here: ")
if input_string == 'q':
do_quit()
elif input_string == 'h':
do_help()
else:
x,y = input_string.split()
That way you can test for your special cases, and process the x and y if they are not found.
may be this, for example:
a = input("text")
b = a.split()
if len(b) == 1:
if b[0] == 'q':
return
elif b[0] == 'h':
print 'it is help ... '
elif len(b) == 2:
# process for two inputted numbers
You can just separate the input:
# get the input
ipt = input("Enter two numbers here: ")
# check if your option is entered
if ipt == 'q' or ipt == 'h':
# do something
else:
x,y = ipt.split()

Categories