i have a problem with creating a dict in python.
In my mainloop i call function 1 which should creat an empty dict.
function 1 calls function 2.
function 2 calls itself (loop through a game tree)
but i can not use the dict i created in f1.
and it is not possible to pass it as agrument.
i would like to have the dict globaly accessible
def f1(): # function 1
#test_dict = {} # this needs to be global scope
#test_dict["key"] = "value"
test_dict["key2"] = "value2"
print (test_dict)
f2()
def f2(): # function 2
# here starts a loop that calls f2 again and again -> global dict is needed
# dict needs to be created
print (test_dict)
test_dict = {} # only works without errors when i create it before calling f1
test_dict["key"] = "value"
f1()
Here is my "real" Code :)
The >>MinMaxComputerMove<< need to edit the dict.
but at the end of a nood i cant pass it because the for loop just goes on.
# [] [] []
# [] [] []
# [] [] []
#Input Layer:
#9 Punkte mit -1 (geg.) 0 (leer) 1 (eig.)
from time import sleep
from random import randint
from random import choice
from IPython.display import clear_output
def clearBoard():
board = [0] * 10
return (board)
def drawBoard(board, PlayerSymbol, ComputerSymbol, turn):
turn += 1
#clear_output()
Symbolboard = []
for index, value in enumerate(board):
if value == 1:
Symbolboard.append(PlayerSymbol)
elif value == -1:
Symbolboard.append(ComputerSymbol)
else:
Symbolboard.append(" ")
print ("Turn: " + str(turn))
print ("")
print (str(Symbolboard[7]) + " - " + str(Symbolboard[8]) + " - " + str(Symbolboard[9]))
print ("| \ | / |")
print (str(Symbolboard[4]) + " - " + str(Symbolboard[5]) + " - " + str(Symbolboard[6]))
print ("| / | \ |")
print (str(Symbolboard[1]) + " - " + str(Symbolboard[2]) + " - " + str(Symbolboard[3]))
return (validMoves(board), turn)
def validMoves(board):
#return list with valid indices
validMoveList = []
for index, value in enumerate(board):
if index > 0 and value == 0:
validMoveList.append(index)
return (validMoveList)
def Symbol():
#X always goes first
if randint(0, 1) == 0:
print ("X: YOU")
print ("O: COMPUTER")
return ("X"), ("O")
else:
print ("X: COMPUTER")
print ("O: YOU")
return ("O"), ("X")
def PlayerMove(validMoveList, PlayerSymbol):
PlayerInput = input("Welches Feld? (1-9):")
if int(PlayerInput) in validMoveList:
return (PlayerInput, PlayerSymbol)
else:
print("Falsche Eingabe." + PlayerInput + " kein möglicher Zug")
def ComputerMove(validMoveList, board, PlayerSymbol, ComputerSymbol, AI):
print("ComputerMove")
if AI == 1:
return RandomComputerMove(validMoveList, ComputerSymbol)
elif AI == 2:
path_dict = {}
return MinMaxComputerMove(validMoveList, board, PlayerSymbol, ComputerSymbol, depth = 1, firstrun = 1)
# more AIs
# ...
def ComputerThinking():
print("Computer is thinking", end = "")
sleep(0.5)
print(".", end = "")
sleep(0.5)
print(".", end = "")
sleep(0.5)
print(".")
sleep(1)
return
def RandomComputerMove(validMoveList, ComputerSymbol):
ComputerChoice = choice(validMoveList)
ComputerThinking()
print("ComputerChoice: " + str(ComputerChoice))
sleep(1.5)
print("RandomComputerMove Output: " + str((ComputerChoice, ComputerSymbol)))
return (ComputerChoice, ComputerSymbol)
def MinMaxComputerMove(validMoveList, board, PlayerSymbol, ComputerSymbol, depth, firstrun = 0, start_path = -1):
initial_validMoveList = validMoveList.copy()
initial_board = board.copy()
turns_left = len(initial_validMoveList)
#debug
print("firstrun: " + str(firstrun))
print("depth: " + str(depth))
if firstrun == 1: #first run of function
path_dict = {}
for path, field in enumerate(initial_validMoveList):
path_dict[path] = {}
for extent in range(3):
path_dict[path][extent+1] = 5
#debug
print("---MinMaxComputerMove---")
print("Start MinMaxComputerMove with depth: " + str(depth))
print("validMoveList: " + str(validMoveList) + str(id(validMoveList)))
print("board: " + str(board) + str(id(board)))
print("ComputerSymbol: " + str(ComputerSymbol))
print("start_path: " + str(start_path))
for path, field in enumerate(initial_validMoveList): #(2, 6, 8):
if firstrun == 1:
start_path = path
print("start_path: " + str(start_path))
# for every path in tree diagram create a key in dict with empty list
# goal: dict("path": [field, depth_1_(max)value, depth_2_(min)value, depth_3_(max)value])
#debug
print("depth: " + str(depth))
if depth % 2 == 1: # Computer:
ChoosenIndex = (str(field), ComputerSymbol)
else: # Player
ChoosenIndex = (str(field), PlayerSymbol)
new_board = updateBoard(initial_board.copy(), ChoosenIndex, PlayerSymbol) # copy() or initial_board would change
new_validMoveList = validMoves(new_board)
#debug
print("---For Loop---")
print("ChoosenIndex: " + str(ChoosenIndex) + str(id(ChoosenIndex)))
print("new_validMoveList: " + str(new_validMoveList) + str(id(new_validMoveList)))
print("new_board: " + str(new_board) + str(id(new_board)))
print("path_dict: " + str(path_dict))
print("depth: " + str(depth))
if checkWinner(new_board) == 0 and depth != 3 and turns_left >= 1: # no winner yet and game not over
print ("no winner yet and game not over")
# go deeper
path_dict[start_path][depth] = 0
MinMaxComputerMove(new_validMoveList, new_board, PlayerSymbol, ComputerSymbol, depth + 1, 0, start_path)
elif checkWinner(new_board) == 0 and depth == 3 and turns_left >= 1: # no winner yet and game not over and minmax ends (depth = 3)
print ("checkWinner(new_board) == 0 and depth == 3 and turns_left >= 1")
path_dict[start_path][depth] = 0
elif checkWinner(new_board) == -1: # computer wins
print ("elif checkWinner(new_board) == -1")
if depth % 2 == 1: # Computer -> MIN:
path_dict[start_path][depth] <= -1
else: # Player -> MAX
if path_dict[start_path][depth] > -1:
path_dict[start_path][depth] = -1
elif checkWinner(new_board) == 1: # player wins
print ("elif checkWinner(new_board) == 1")
path_dict[start_path][depth] = 1
elif depth >= 3 or turns_left < 1: # reached depth 3 or no more turns
print ("elif depth >= 3 or turns_left < 1:")
else:
print ("else")
print("--- END FOR PATH ---")
print("--- END FOR LOOP ---")
print(path_dict)
# return choise
return (2, ComputerSymbol)
def updateBoard(board, ChoosenIndex, PlayerSymbol): #[0, 1, -1, 0, ...],[5, "X"], "X"
if PlayerSymbol == ChoosenIndex[1]:
board[int(ChoosenIndex[0])] = 1
return (board)
else:
board[int(ChoosenIndex[0])] = -1
return (board)
def checkWinner(board):
if (board[7] == board[8] == board[9]) and 0 != board[7]: # top row
return board[7]
elif (board[4] == board[5] == board[6]) and 0 != board[4]: # mid row
return board[4]
elif (board[1] == board[2] == board[3]) and 0 != board[1]: # bot row
return board[1]
elif (board[7] == board[4] == board[1]) and 0 != board[7]: # left column
return board[7]
elif (board[8] == board[5] == board[2]) and 0 != board[8]: # mid row
return board[8]
elif (board[9] == board[6] == board[3]) and 0 != board[9]: # right row
return board[9]
elif (board[7] == board[5] == board[3]) and 0 != board[7]: # diagonal \
return board[7]
elif(board[1] == board[5] == board[9]) and 0 != board[1]: # diagonal /
return board[1]
else:
return 0
def GameLoop(AI, turn = 0, winner = 0):
#choose AI difficulty
#...
#...
#set first player (X)
PlayerSymbol, ComputerSymbol = Symbol()
sleep(3)
#init board with list 10 * 0
board = clearBoard()
#debug
board = [0, 1, 0, 1, -1, -1, 0, 1, 0, -1]
PlayerSymbol, ComputerSymbol = ("O", "X") # computer first
#draw current board
validMoveList, turn = drawBoard(board, PlayerSymbol, ComputerSymbol, turn)
while winner == 0 and turn <=9:
sleep(1.5)
if turn % 2 == 1: # "X" player move
if PlayerSymbol == "X":
#player move
ChoosenIndex = PlayerMove(validMoveList, PlayerSymbol)
#update current board
board = updateBoard(board, ChoosenIndex, PlayerSymbol)
#draw current board
validMoveList, turn = drawBoard(board, PlayerSymbol, ComputerSymbol, turn)
#check for winner
winner = checkWinner(board)
else:
#computer move
ChoosenIndex = ComputerMove(validMoveList, board, PlayerSymbol, ComputerSymbol, AI)
#update current board
board = updateBoard(board,ChoosenIndex, PlayerSymbol)
#draw current board
validMoveList, turn = drawBoard(board, PlayerSymbol, ComputerSymbol, turn)
#check for winner
winner = checkWinner(board)
else: # "O" player move
if PlayerSymbol == "O":
#player move
ChoosenIndex = PlayerMove(validMoveList, PlayerSymbol)
#update current board
board = updateBoard(board,ChoosenIndex, PlayerSymbol)
#draw current board
validMoveList, turn = drawBoard(board, PlayerSymbol, ComputerSymbol, turn)
#check for winner
winner = checkWinner(board)
else:
#computer move
ChoosenIndex = ComputerMove(validMoveList, board, PlayerSymbol, ComputerSymbol, AI)
#update current board
board = updateBoard(board,ChoosenIndex, PlayerSymbol)
#draw current board
validMoveList, turn = drawBoard(board, PlayerSymbol, ComputerSymbol, turn)
#check for winner
winner = checkWinner(board)
else:
if winner == 1:
print ("YOU WON!")
elif winner == -1:
print ("COMPUTER WON!")
else:
print ("DRAW!")
GameLoop(AI = 2)
The "return value" answer is:
def f1(test_dict): # function 1
#test_dict = {} # this needs to be global scope
#test_dict["key"] = "value"
test_dict["key2"] = "value2"
print ('In f1 {}'.format(test_dict))
f2(test_dict)
return test_dict
def f2(test_dict): # function 2
# here starts a loop that calls f2 again and again -> global dict is needed
# dict needs to be created
print ('In f2 {}'.format(test_dict))
return test_dict
test_dict = {} # only works without errors when i create it before calling f1
test_dict["key"] = "value"
test_dict = f1(test_dict)
which gives output of:
In f1 {'key2': 'value2', 'key': 'value'}
In f2 {'key2': 'value2', 'key': 'value'}
But at some level, you probably want to put some of this into a class and then have test_dict as a variable within the class. That allows f1 and f2 (assuming they are class methods) to access the class variable without passing it as a parameter to the two methods.
class Example:
def __init__(self):
self._test_dict = {}
self._test_dict["key"] = "value"
def f1(self): # function 1
self._test_dict["key2"] = "value2"
print ('In f1 {}'.format(self._test_dict))
self.f2()
def f2(self): # function 2
print ('In f2 {}'.format(self._test_dict))
example = Example()
example.f1()
Below is a very simply version of what your script is attempting. You need to consider what your function parameters should be (what is passed to the function), as well as what your function should be providing at the end of its execution (given to you with the return statement). This way you can manipulate objects without having to keep everything in global scope, and you can avoid having to initialize every conceivable variable at the start of the routine.
Python Functions
Return Statement
def f1():
f1_dict = {}
f1_dict = f2(f1_dict)
return f1_dict
def f2(dict_arg):
f2_dict = {}
for i in range(0,5):
f2_dict[str(i)] = i**i
return f2_dict
dictionary = f1()
print(dictionary)
Related
How do I stop input from asking data for the 10th time? I am trying to build a board and want X or O to be updated only 9 times for a string that has 10 elements. Element 0 been empty.
It seems I need to figure out a way to stop or break the while loop when test_board[9] != "" (in def space_check():). This position if filled by the first player but the while (in #Test Run) loop is still active and so the user input is requested for the 10th position for the 2nd player.
enter code here
#Board
def display_board(board):
print (board[7] + '|' + board[8] + '|' + board[9])
print (board[4] + '|' + board[5] + '|' + board[6])
print (board[1] + '|' + board[2] + '|' + board[3])
pass
#Player input slection
def player_input():
marker = ''
#Asking player 1 to choose X or O
while marker not in ["X","O"]:
marker = input('Player 1 choose X or O ')
#Assign Player 2 a marker
player1 = marker
if player1 == 'X':
player2 = 'O'
else:
player2 = 'X'
return (player1,player2)
#Player position selection
def user_position():
# variables
#Initial
position ="WRONG"
acceptable_range = range(1,10)
within_range = False
#Two condition to check Digit or within range
while position.isdigit() == False or within_range == False:
position = input("Please enter a number (1-10):")
#Digit check
if position.isdigit() == False:
print("Sorry that is not a digit!")
#Range check
if position.isdigit()==True:
if int(position) in acceptable_range:
within_range = True
else:
within_range =False
print("Sorry that is not acceptable range!")
return int(position)
def place_marker(board, marker, position):
board[position]=marker
#print (board[position])
pass
def space_check():
for i in range(1,10):
if test_board[i] =='':
empty_position = True
#print (f'{i}')
else:
empty_position = False
return bool(empty_position)
Test run
from IPython.display import clear_output
clear_output()
def test_game_run():
#get the player input
player1_marker, player2_marker = player_input()
#get player 1 position
position_p1 = 0
position_p2 = 0
empty_position = True
counter = 0
#while empty_position == True:
#
while (position_p1 == position_p2 or empty_position == True): #and (counter <8): # need to contunue the game
print("player 1 choose a position")
position_p1 = user_position()
place_marker(test_board,player1_marker,position_p1)
empty_position = space_check()
print("player 2 choose a position")
position_p2 = user_position()
place_marker(test_board,player2_marker,position_p2)
empty_position = space_check()
# counter =counter + 1
#print(f'{counter}')
#step3
#print position by player 1
print(len(test_board))
#function call
test_board =['']*10
test_game_run()
display_board(test_board)
Output
def get_input(prompt,max_tries,allowed_values):
for i in range(max_tries,-1,-1):
result = input(prompt):
if result in allowed_values:
return result
print(f"{i} tries left")
return "default"
Is one strategy for this
My tic-tac-toe doesn't seem to work properly. I have tried various things, but nothing changes.
You can run the script yourself, just to see that every time after asking the player's move the game makes a vertical line of X's at the desired column and ends there.
It's probably a problem with my implementation of minimax or the computedMove function, although i cannot locate any errors in there.
# Boardsize initialization
boardSize = 0
# Board initialization
board = []
person = 'X'
ai = 'O'
#This variable indicates the player who has their turn at the moment.
currentPlayer = ''
# This shows the board.
for n in range (boardSize):
for m in range (boardSize):
print (" - "),
print ("\n")
#Checking if somebody won (only horizontal or vertical)
def winLine(line, letter):
return all(n == letter for n in line)
#New list from diagonals
def winDiagonal(board):
return (board[n][n] for n in range (boardSize))
#The function universally checks whether somebody has won, or not.
def checkWinner (board):
#Liczenie wolnych pol
openSpots = 0
for n in range(boardSize):
for m in range(boardSize):
if board[n][m] == '0':
openSpots += 1
#Transposition of the board, so it's possible to use winline() here
for letter in (person, ai):
transPos = list(zip(*board))
#Horizontal check
if any(winLine(row, letter) for row in board):
return letter
#Vertical check
elif any (winLine(col, letter) for col in transPos):
return letter
#Diagonal check
elif any (winLine(winDiagonal(dummy), letter) for dummy in (board, transPos)):
return letter
elif openSpots == 0: return 'tie'
else: return 'N/A'
#This function returns the player's move
def playerMove (row, col):
#Checking if the field is clear
if board[row][col] == '0':
board[row-1][col-1] = person
else:
print('You cannot make that move.')
#Minimax constants
plusInf = float('inf')
minusInf = float('-inf')
#Lookup table for minimax scores
scores = {
'X': 10,
'O': -10,
'None': 0
}
#Minimax itself
def minimax(baord, depth, maximizes):
#Checking whether anybody has won
res = checkWinner(board)
if (res != 'N/A'):
return scores[res]
#Maximizing player
if maximizes:
minmaxBoard = board.copy()
maxTarget = minusInf
for n in range(boardSize):
for m in range(boardSize):
if minmaxBoard[n][m] == '0':
minmaxBoard[n][m] = ai
score = minimax(minmaxBoard, depth + 1, False)
maxTarget = max(score, maxTarget)
return maxTarget
#Minimizing player
else:
minTarget = plusInf
minmaxBoard = board.copy()
for n in range(boardSize):
for m in range(boardSize):
if minmaxBoard[n][m] == '0':
minmaxBoard[n][m] = person
score = minimax(minmaxBoard, depth + 1, True)
minTarget = min(score, minTarget)
return minTarget
#The computer uses this function to make its move
def computedMove():
computedTarget = minusInf
for n in range(boardSize):
for m in range(boardSize):
newBoard = board.copy()
if newBoard[n][m] == '0':
newBoard[n][m] = ai
score = minimax(newBoard, 0, False)
if score > computedTarget:
computedTarget = score
move = (n,m)
board[move[0]][move[1]] = ai
# Getting input for the player's move
def getPlayerMove():
res = input('Please type in your move on the form \"x y\", x being the number of the column and y the number of the row of your choosing.\n')
col, row = res.split(" ")
row = int(row)
col = int(col)
move = (row, col)
return move
# Drawing the board
def drawBoard():
for n in range(boardSize):
for m in range(boardSize):
if board[n][m] == '0':
print(' - ', end='')
else:
print(' '+board[n][m]+' ', end='')
print('\n')
# Current state of the game, False at first
playing = False
#The game loop
while True:
currentPlayer = person
boardSize = int(input("Please enter the size of the board. (one sie)\n"))
board = [['0']*boardSize]*boardSize
print("You go first.")
playing = True
while playing:
if currentPlayer == person:
drawBoard()
move = getPlayerMove()
playerMove(move[0]-1, move[1]-1)
if checkWinner(board) == person:
drawBoard()
print("Yaay, you won!")
playing = False
else:
if checkWinner(board) == 'tie':
drawBoard()
print('It\'s a tie!')
break
else:
currentPlayer = ai
if currentPlayer == ai:
computedMove()
if checkWinner(board) == ai:
drawBoard()
print('You lose!')
playing = False
else:
if checkWinner(board) == 'tie':
drawBoard()
print('It\'s a tie!')
break
else:
currentPlayer = person
if not input('Do you want to play again?').lower().startswith('y'):
break
Check out this statement:
board = [['0']*boardSize]*boardSize
You're essentially creating a list of references to the same list boardSize times. That's why when you're assigning something to board[i][j] element, it gets assigned to j-th elements of all rows (from board[0] to board[len(board)]), because all rows are referencing the same list.
Use this instead:
board = [['0'] * boardSize for _ in range(boardSize)]
There are other issues with this code though. I'm sure you're decrementing your (x, y) indexes multiple times, for example. I didn't check it further.
I'm trying to create a game called Connect Four with AI which uses the alpha-beta pruning algorithm in python. Here is the code I have managed to write:
# -*- coding: utf-8 -*-
import sys
class ConnectFour:
def __init__(self):
self.board = [[],[],[],[],[],[]]
for i in range(7):
for j in range(6):
self.board[j].append(" ")
self.moves = 0
self.colstack = [0,0,0,0,0,0,0]
self.node = 0
self.move = 0
def PrintGameBoard(self):
print(' 0 1 2 3 4 5 6')
for i in range(5, -1, -1):
print('|---|---|---|---|---|---|---|')
print("| ",end="")
for j in range(7):
print(self.board[i][j],end="")
if j != 6:
print(" | ",end="")
else:
print(" |")
print('`---------------------------´')
def CanPlay(self, col):
return self.colstack[col] < 6
def Play(self, col, board):
board[self.colstack[col]][col] = 2
self.colstack[col] += 1
self.moves += 1
return board
def IsWinning(self, currentplayer):
for i in range(6):
for j in range(4):
if self.board[i][j] == currentplayer and self.board[i][j+1] == currentplayer and self.board[i][j+2] == currentplayer and self.board[i][j+3] == currentplayer:
return True
for i in range(3):
for j in range(7):
if self.board[i][j] == currentplayer and self.board[i+1][j] == currentplayer and self.board[i+2][j] == currentplayer and self.board[i+3][j] == currentplayer:
return True
for i in range(3):
for j in range(4):
if self.board[i][j] == currentplayer and self.board[i+1][j+1] == currentplayer and self.board[i+2][j+2] == currentplayer and self.board[i+3][j+3] == currentplayer:
return True
for i in range(3,6):
for j in range(4):
if self.board[i][j] == currentplayer and self.board[i-1][j+1] == currentplayer and self.board[i-2][j+2] == currentplayer and self.board[i-3][j+3] == currentplayer:
return True
return False
def AlphaBeta(self, alpha, beta):
self.node += 1
if self.moves == 42:
return 0
for col in range(7):
if self.CanPlay(col) and self.IsWinning(2):
return (43 - self.moves)/2
max = (41 - self.moves)/2
if beta > max:
beta = max
if alpha >= beta:
return beta
for col in range(7):
if self.CanPlay(col):
self.board[self.colstack[col]][col] = 2
self.move = col
score = -self.AlphaBeta(-alpha, -beta)
if score >= beta:
return score
elif score > alpha:
alpha = score
self.board[self.colstack[col]][col] = " "
def Solve(self, table, week=False):
self.node = 0
self.board = table
if week:
self.AlphaBeta(-1, 1)
self.board = self.Play(self.move, table)
return self.board
else:
self.AlphaBeta(-21, 21)
self.board = self.Play(self.move, table)
return self.board
def PlayerMove(self, table):
self.board = table
try:
allowedmove = False
while not allowedmove:
print("Choose a column where you want to make your move (0-6): ",end="")
col =input()
if self.CanPlay(int(col)):
self.board[self.colstack[int(col)]][int(col)] = 1
self.moves += 1
self.colstack[int(col)] += 1
allowedmove = True
else:
print("This column is full")
except (NameError, ValueError, IndexError, TypeError, SyntaxError) as e:
print("Give a number as an integer between 0-6!")
else:
return self.board
def PlayerMark():
print("Player 1 starts the game")
mark = ''
while not (mark == "1" or mark == "2"):
print('Do you want to be 1 or 2: ',end="")
mark = input()
if mark == "1":
return 1
else:
return 2
def PlayAgain():
print('Do you want to play again? (yes or no) :',end="")
return input().lower().startswith('y')
def main():
sys.setrecursionlimit(2000)
print("Connect4")
while True:
mark = PlayerMark()
connectfour = ConnectFour()
if mark==1:
print("You are going to start the game\r\n\r\n")
else:
print("Computer (negamax) starts the game")
gameisgoing = True
table = [[],[],[],[],[],[]]
for i in range(7):
for j in range(6):
table[j].append(" ")
while gameisgoing:
connectfour.PrintGameBoard()
if mark == 1:
table = connectfour.PlayerMove(table)
if connectfour.IsWinning(1):
connectfour.PrintGameBoard()
print('You won the game!')
gameisgoing = False
else:
if connectfour.moves==42:
connectfour.PrintGameBoard()
print('Game is tie')
break
else:
mark = 2
else:
move = connectfour.Solve(table)
if connectfour.IsWinning(2):
connectfour.PrintGameBoard()
print('Computer won the game')
gameisgoing = False
else:
if connectfour.moves==42:
connectfour.PrintGameBoard()
print('Game is tie')
break
else:
mark = 1
if not PlayAgain():
print("Game ended")
break
if __name__ == '__main__':
main()
I'm not sure if the algorithm is working properly, but the problem is that I get RecursionError: maximum recursion depth exceeded in comparison. If I increase recursionlimit I get in around 10000 MemoryError: Stack Overflow. I think that the problem is that there is too many states to handle for my computer. That's why I changed the negamax algorithm to alpha-beta pruning, but there seem to be still to many states. Is there a effective technique that does algorithmic search, for example max depth 10 and still the computer is almost invincible? I'm waiting your solutions.
I am trying to have my program load a tree of every possible tic-tac-toe board and then when given a random board input it can print out all the possible next moves based on the tree. However, when I try to do this all of my nodes seem to return None, except the root node.
My code right now:
import random
def main():
root = createNode(board, None, "X")
setBoard = (" ", " ", " ",
" ", "X", "X",
" ", " ", "O")
nextMoves = find(root, setBoard)
print(nextMoves)
for child in nextMoves.children:
printBoard(child.boardState)
boardCases = set()
board = [" ", " ", " ", " ", " ", " ", " ", " ", " "]
def printBoard(board):
for i in range(3):
print(board[i*3], end="")
print("|", end="")
print(board[i*3+1], end="")
print("|", end="")
print(board[i*3+2], end="")
print("")
if i < 2:
print("-+-+-")
print("~~~~~~~~~~~~")
def checkForWin(board, c):
# all column cases
for i in range(3):
if board[i] == c and board[i+3] == c and board[i+6] == c:
#print(c + " wins!")
return True
#all row cases
for i in range(3):
if board[i*3] == c and board[i*3+1] == c and board[i*3+2] == c:
#print(c + " wins!")
return True
#all across cases
if board[0] == c and board[4] == c and board[8] == c:
#print(c + " wins!")
return True
if board[2] == c and board[4] == c and board[6] == c:
#print(c + " wins!")
return True
#no wins game tie
counter = 0
for i in range(9):
if board[i] == " ":
# no tie found ---> game countinues
return False
else:
counter += 1
if counter == 9:
#print("Tie Game!")
return True
class boardNode:
def __init__(self):
self.boardState = ()
self.children = []
self.winner = ""
def numChildren(self):
return len(self.availableMoves())
def availableMoves(self):
moves = set()
for i in range(9):
if self.boardState[i] == " ":
moves.add(i)
return moves
counter = 0
def createNode(currentBoard, posToFill, c):
global counter
newNode = boardNode()
board = list(currentBoard)
counter +=1
if posToFill != None:
board[int(str(posToFill))] = c
newNode.boardState = tuple(board)
if checkForWin(tuple(board), c) == False:
newNode.winner = None
if c == "X":
for pos in newNode.availableMoves():
newNode.children.append(createNode(newNode.boardState, pos, "O"))
else:
for pos in newNode.availableMoves():
newNode.children.append(createNode(newNode.boardState, pos, "X"))
else:
newNode.winner = c
if newNode.boardState not in boardCases:
boardCases.add(newNode.boardState)
return newNode
def find(node, boardToSearch):
if list(node.boardState) == list(boardToSearch):
return node
else:
for child in node.children:
return find(child, boardToSearch)
if __name__ == "__main__":
main()
Here is my output for my current case:
$ python ticTacToe.py
None
Traceback (most recent call last):
File "test.py", line 115, in <module>
main()
File "test.py", line 11, in main
for child in nextMoves.children:
AttributeError: 'NoneType' object has no attribute 'children'
import random
class Spinner(object):
#staticmethod
def getSpin():
newSpin = random.randint(1,6)
return newSpin
class Player(object):
def __init__(self,name):
self.position = 1
self.name = name
def setName(self,name):
self.name = name
def changePosition(self,number):
self.position = self.position + number
def setPosition(self,pos):
self.position = pos
return self.position
def getPosition(self):
return self.position
def getName(self):
return self.name
def spin(self):
newSpin = Spinner.getSpin()
self.position = self.position + newSpin
print(str(self.name) + "'s spin was: " + str(newSpin))
class Display():
def buildLadders():
ladders = [[0 for x in range(2)] for x in range(2)]
ladders[0][0] = 2
ladders[0][1] = 7
ladders[1][0] = 4
ladders[1][1] = 5
return ladders
def buildChutes():
chutes = [[0 for x in range(2)] for x in range(2)]
chutes[0][0] = 9
chutes[0][1] = 2
chutes[1][0] = 6
chutes[1][1] = 3
return chutes
class Check(Player):
def checkLadders(self):
ladders = Display.buildLadders()
for i in range(0,len(ladders),1):
if self.getPosition() == ladders[i][0]:
self.position = self.setPosition(ladders[i][1])
print(str(self.name) + " Landed on a Ladder! from " + \
str(ladders[i][0]) +" to " + str(ladders[i][1]))
def checkChutes(self):
chutes = Display.buildChutes()
for i in range(0,len(chutes),1):
if self.getPosition() == chutes[i][0]:
self.position = self.setPosition(chutes[i][1])
print(str(self.name) + " Landed on a Chutes! from " + \
str(chutes[i][0]) + " to " + str(chutes[i][1]))
def checkQuestions(num):
one = random.randint(num,num*10)
two = random.randint(num,num*10)
listqq = [one,two]
return listqq
class Controller(object):
def __init__(self,names):
self.winner = ''
self.players = []
for n in names:
p = Player(n)
self.players.append(p)
def move(self):
players = self.players
winner = self.winner
click = ''
count = 1
while True:
for i in range(0,len(players)):
if winner == '' and click != 'e':
print("----" + str(players[i].getName()) + "'s TURN----")
click = input("Press r to roll or e to exit: ")
while click != 'r' and click != 'e':
click = input("Press r to roll or e to exit: ")
if click == 'r' and click != 'e':
count = count + 1
listqq = Check.checkQuestions(count)
answer = input(str(listqq[0]) + ' + ' + str(listqq[1]) +' is:')
if answer == str(listqq[0]+listqq[1]):
print(str(players[i].getName()) + "'s initial position is " \
+ str(players[i].getPosition()))
View(players).display()
players[i].spin()
Check.checkLadders(players[i])
Check.checkChutes(players[i])
else:
pass
if players[i].getPosition() >= 12:
players[i].position = players[i].setPosition(12 - (players[i].getPosition() - 12))
print(str(players[i].getName()) + "'s new position is " \
+ str(players[i].getPosition()))
View(players).display()
if players[i].getPosition() == 12:
winner = players[i].getName()
if click == 'e' and click != 'r':
print('Bye')
break
if winner != '':
print(str(winner) + " is the winner!!!")
break
class View(Player):
def __init__(self,player):
self.players = player
def display(self):
players = self.players
listof = [9,10,11,12,8,7,6,5,1,2,3,4]
ladders = Display.buildLadders()
chutes = Display.buildChutes()
board = [[]] * 3
for i in range(len(players)):
for j in range(len(listof)):
if self.players[i].position == listof[j]:
listof[j] = 'X'
for j in range(len(listof)):
for i in range(len(ladders)):
if ladders[i][0] == listof[j]:
listof[j] = 'L'
for j in range(len(listof)):
for i in range(len(chutes)):
if chutes[i][0] == listof[j]:
listof[j] = 'C'
for i in range(0,4):
board[0] = board[0] + [listof[i]]
for i in range(4,8):
board[1] = board[1] + [listof[i]]
for i in range(8,12):
board[2] = board[2] + [listof[i]]
for row in board:
for num in row:
if num == 'X':
print(" X", end=" ")
if num == 'L':
print(" L", end= " ")
if num == 'C':
print(" C", end= " ")
if num != 'X' and num != 'L' and num != 'C':
if 10 <= num <= 20:
print(num,end=" ")
if num != 'X' and num != 'L' and num!= 'C':
if 1 <= num <= 9:
print(str(num).rjust(2), end= " ")
print()
def main():
n = input("Please enter number of players: ")
names = []
for i in range (0,int(n)):
name = input("Please input your name: ")
names.append(name)
game = Controller(names)
game.move()
while True:
ask = input("Do you want to play again? (y/n)")
if ask == 'y':
game = Controller(names)
game.move()
if ask == 'n':
print("Bye, see you again!")
break
main()
fixed version:
import random
class Player(object):
def __init__(self,name):
self.position = 1
self.name = name
def setName(self,name):
self.name = name
def changePosition(self,number):
self.position = self.position + number
def setPosition(self,pos):
self.position = pos
return self.position
def spin(self):
newSpin = self.getSpin()
self.position = self.position + newSpin
print(str(self.name) + "'s spin was: " + str(newSpin))
def checkLadders(self):
ladders = self.buildLadders()
for i in range(0,len(ladders),1):
if self.position == ladders[i][0]:
self.position = self.setPosition(ladders[i][1])
print(str(self.name) + " Landed on a Ladder! from " + \
str(ladders[i][0]) +" to " + str(ladders[i][1]))
def checkChutes(self):
chutes = self.buildChutes()
for i in range(0,len(chutes),1):
if self.position == chutes[i][0]:
self.position = self.setPosition(chutes[i][1])
print(str(self.name) + " Landed on a Chutes! from " + \
str(chutes[i][0]) + " to " + str(chutes[i][1]))
#staticmethod
def checkQuestions(num):
one = random.randint(num,num*10)
two = random.randint(num,num*10)
listqq = [one,two]
return listqq
#staticmethod
def getSpin():
newSpin = random.randint(1,6)
return newSpin
#staticmethod
def buildLadders():
ladders = [[0 for x in range(2)] for x in range(2)]
ladders[0][0] = 2
ladders[0][1] = 7
ladders[1][0] = 4
ladders[1][1] = 5
return ladders
#staticmethod
def buildChutes():
chutes = [[0 for x in range(2)] for x in range(2)]
chutes[0][0] = 9
chutes[0][1] = 2
chutes[1][0] = 6
chutes[1][1] = 3
return chutes
class Controller(object):
def __init__(self,names):
self.winner = ''
self.players = []
for n in names:
p = Player(n)
self.players.append(p)
def move(self):
players = self.players
winner = self.winner
click = ''
count = 1
while True:
for i in range(0,len(players)):
if winner == '' and click != 'e':
print("----" + str(players[i].name) + "'s TURN----")
click = input("Press r to roll or e to exit: ")
while click != 'r' and click != 'e':
click = input("Press r to roll or e to exit: ")
if click == 'r' and click != 'e':
count = count + 1
listqq = Player.checkQuestions(count)
answer = input(str(listqq[0]) + ' + ' + str(listqq[1]) +' is:')
if answer == str(listqq[0]+listqq[1]):
print(str(players[i].name) + "'s initial position is " \
+ str(players[i].position))
View(players).display()
players[i].spin()
Player.checkLadders(players[i])
Player.checkChutes(players[i])
else:
pass
if players[i].position >= 12:
players[i].position = players[i].setPosition(12 - (players[i].getPosition() - 12))
print(str(players[i].name) + "'s new position is " \
+ str(players[i].position))
View(players).display()
if players[i].position == 12:
winner = players[i].name
if click == 'e' and click != 'r':
print('Bye')
break
if winner != '':
print(str(winner) + " is the winner!!!")
break
class View():
def __init__(self,player):
self.players = player
def display(self):
players = self.players
listof = [9,10,11,12,8,7,6,5,1,2,3,4]
ladders = Player.buildLadders()
chutes = Player.buildChutes()
board = [[]] * 3
for i in range(len(players)):
for j in range(len(listof)):
if self.players[i].position == listof[j]:
listof[j] = 'X'
for j in range(len(listof)):
for i in range(len(ladders)):
if ladders[i][0] == listof[j]:
listof[j] = 'L'
for j in range(len(listof)):
for i in range(len(chutes)):
if chutes[i][0] == listof[j]:
listof[j] = 'C'
for i in range(0,4):
board[0] = board[0] + [listof[i]]
for i in range(4,8):
board[1] = board[1] + [listof[i]]
for i in range(8,12):
board[2] = board[2] + [listof[i]]
for row in board:
for num in row:
if num == 'X':
print(" X", end=" ")
if num == 'L':
print(" L", end= " ")
if num == 'C':
print(" C", end= " ")
if num != 'X' and num != 'L' and num != 'C':
if 10 <= num <= 20:
print(num,end=" ")
if num != 'X' and num != 'L' and num!= 'C':
if 1 <= num <= 9:
print(str(num).rjust(2), end= " ")
print()
def main():
n = input("Please enter number of players: ")
names = []
for i in range (0,int(n)):
name = input("Please input your name: ")
names.append(name)
game = Controller(names)
game.move()
while True:
ask = input("Do you want to play again? (y/n)")
if ask == 'y':
game = Controller(names)
game.move()
if ask == 'n':
print("Bye, see you again!")
break
main()
Is this following the MVC infrastructure? How to know if it fits the MVC structure or not? Thanks. Does we have to put each model,view,and controller in different module for it to be described as following the MVC structure?
First off the program is not really object oriented. View is instanciated every time when the game state has to be displayed just to call the one and only method. Classes with just the __init__() and one other method are a code smell because, like in this case, it's just a function crammed into a class for no good reason. The same can be said about Control — also just the __init__() and one additional method that get's called exactly once right after instanciating the object and directly after the call the object isn't used anymore.
Taking those ”fake” classes and considering the amount of static methods it seems you are under the impression classes automatically lead to object oriented programs — they don't. And there is nothing wrong with using functions instead of artificially introducing unnecessary complexity with classes that are just syntactically classes. Functions are objects too in Python, so when you have a display function it's okay to pass that around as „view” part of an MVC pattern. It's a callable object.
Which brings us to the MVC question: Supposing Player is the model then it should not interact with the user by printing stuff. Display and input is for the view to handle. So Control isn't a controller because the function in disguise also heavily interacts with the user via print() and input().