Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I'm very new to Python and I have to create a tic tac toe game with 3 players, 'X', 'O' and 'Y'. The grid has to be 6x6 instead of the normal 3x3. I have been having a lot of trouble with this and I'm very unsure how to do it. I have a 2 player 3x3 game working but implementing another player and validating the wins is becoming more tedious than I previously expected. I need help with validating a win. I haven't written the code to check for a diagonal win because I want to get everything else working before I do that. This is what I have so far but it's not correct. It's not printing out the values entered and when I do enter a value it says X has won straight away. I'd really appreciate it if you could help me. Thanks!
grid = [[0,0,0,0,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0,0]]
def get_state(grid, row, col):
occupant = grid[col-1][row-1]
if occupant == 1:
return 'X'
if occupant == 2:
return 'O'
if occupant == 3:
return 'Y'
return ' '
def set_state(grid, row, col, player):
if player == 'X':
occupant = 1
elif player == 'O':
occupant = 2
elif player == 'Y':
occupant = 3
grid[col-1][row-1] = occupant
def is_winner(grid):
if grid[0][0] == grid[0][1] == grid [0][2]:
return True
if grid[0][1] == grid[0][2] == grid [0][3]:
return True
if grid[0][2] == grid[0][3] == grid [0][4]:
return True
if grid[0][3] == grid[0][4] == grid [0][5]:
return True
if grid[1][0] == grid[1][1] == grid [1][2]:
return True
if grid[1][1] == grid[1][2] == grid [1][3]:
return True
if grid[1][2] == grid[1][3] == grid [1][4]:
return True
if grid[1][3] == grid[1][4] == grid [1][5]:
return True
if grid[2][0] == grid[2][1] == grid [2][2]:
return True
if grid[2][1] == grid[2][2] == grid [2][3]:
return True
if grid[2][2] == grid[2][3] == grid [2][4]:
return True
if grid[2][3] == grid[2][4] == grid [2][5]:
return True
if grid[3][0] == grid[3][1] == grid [3][2]:
return True
if grid[3][1] == grid[3][2] == grid [3][3]:
return True
if grid[3][2] == grid[3][3] == grid [3][4]:
return True
if grid[3][3] == grid[3][4] == grid [3][5]:
return True
if grid[4][0] == grid[4][1] == grid [4][2]:
return True
if grid[4][1] == grid[4][2] == grid [4][3]:
return True
if grid[4][2] == grid[4][3] == grid [4][4]:
return True
if grid[4][3] == grid[4][4] == grid [4][5]:
return True
if grid[5][0] == grid[5][1] == grid [5][2]:
return True
if grid[5][1] == grid[5][2] == grid [5][3]:
return True
if grid[5][2] == grid[5][3] == grid [5][4]:
return True
if grid[5][3] == grid[5][4] == grid [5][5]:
return True
if grid[0][0] == grid[1][0] == grid [2][0]:
return True
if grid[1][0] == grid[2][0] == grid [3][0]:
return True
if grid[2][0] == grid[3][0] == grid [4][0]:
return True
if grid[3][0] == grid[4][0] == grid [5][0]:
return True
if grid[0][1] == grid[1][1] == grid [2][1]:
return True
if grid[1][1] == grid[2][1] == grid [3][1]:
return True
if grid[2][1] == grid[3][1] == grid [4][1]:
return True
if grid[3][1] == grid[4][1] == grid [5][1]:
return True
if grid[0][2] == grid[1][2] == grid [2][2]:
return True
if grid[1][2] == grid[2][2] == grid [3][2]:
return True
if grid[2][2] == grid[3][2] == grid [4][2]:
return True
if grid[3][2] == grid[4][2] == grid [5][2]:
return True
if grid[0][3] == grid[1][3] == grid [2][3]:
return True
if grid[1][3] == grid[2][3] == grid [3][3]:
return True
if grid[2][3] == grid[3][3] == grid [4][3]:
return True
if grid[3][3] == grid[4][3] == grid [5][3]:
return True
if grid[0][4] == grid[1][4] == grid [2][4]:
return True
if grid[1][4] == grid[2][4] == grid [3][4]:
return True
if grid[2][4] == grid[3][4] == grid [4][4]:
return True
if grid[3][4] == grid[4][4] == grid [5][4]:
return True
if grid[0][5] == grid[1][5] == grid [2][5]:
return True
if grid[1][5] == grid[2][5] == grid [3][5]:
return True
if grid[2][5] == grid[3][5] == grid [4][5]:
return True
if grid[3][5] == grid[4][5] == grid [5][5]:
return True
return False
def print_grid(grid):
print_row(grid,1)
print('-----------')
print_row(grid,2)
print('-----------')
print_row(grid,4)
print('-----------')
print_row(grid,4)
print('-----------')
print_row(grid,5)
print('-----------')
print_row(grid,6)
def print_row(grid, row):
output = get_state(grid,row,1)
output += '|' + get_state(grid, row, 2)
output += '|' + get_state(grid, row, 3)
output += '|' + get_state(grid, row, 4)
output += '|' + get_state(grid, row, 5)
output += '|' + get_state(grid, row, 5)
print (output)
ongoing = True
currentPlayer = 'X'
spaces = 36
while ongoing:
print_grid(grid)
print (currentPlayer + "'s turn")
print("Column?")
col = int(input())
print("Row?")
row = int(input())
current = get_state(grid,row,col)
if current != ' ':
print ("That spot is taken!")
else:
set_state(grid, row, col, currentPlayer)
spaces -= 1
if is_winner(grid):
print (currentPlayer + "'s wins!")
ongoing = False
else:
if currentPlayer == 'X':
currentPlayer = 'O'
elif currentPlayer == 'O':
curentPlayer = 'Y'
elif currentPlayer == 'Y':
currentPlayer = 'X'
if spaces == 0:
print("Stalemate!")
ongong = False
The is_winner(grid) function checks if 3 of the grid cells are the same. You initialized the grid to be 0, so the first player would always 'win'. One fix I suggest would be to initialize the list with different values. Another one would be to check (after finding that 3 cells are same) the values of the grid:
if grid[0][0] == grid[0][1] == grid[0][2]:
return grid[0][0] in ['X', 'O', 'Y']
The answer given by chucksys is good, although I would do it in a slightly different way. You need to determine that the 3 cells are the same, and not empty - so just check against your default value.
if grid[0][0] == grid[0][1] == grid[0][2] != 0:
return True
good luck with your game it's fun !!!! You can leave the code as it is. just make a different grid. one that contains a different value in every cell. That will prevent you from rewriting a lot of the game. At the beginning add the following code:grid = []
inner = []
b = 10
for i in xrange(6):
for ii in xrange(6):
inner.append(b)
b += 1
grid.append(inner)
inner = list()
This will make your grid, error proof from your checker function is_winner
There is also one small bug. curentPlayer = 'Y' change to currentPlayer = 'Y' near the end of the code
Related
I'm trying to figure out why playing the tic tac toe game works fine until it needs to pick a winner vertically. I only do the first left side right and the other sides it ignores. Below is the function I used to make the game know a winner if all conditions are met.
def check_winner():
for row in range(3):
if buttons[row][0]['text'] == buttons[row][1]['text'] == buttons[row][2]['text'] != "":
buttons[row][0].config(bg="green")
buttons[row][1].config(bg="green")
buttons[row][2].config(bg="green")
return True
for column in range(3):
if buttons[0][column]['text'] == buttons[1][column]['text'] == buttons[2][column]['text'] != "":
buttons[0][column].config(bg="green")
buttons[1][column].config(bg="green")
buttons[2][column].config(bg="green")
return True
if buttons[0][0]['text'] == buttons[1][1]['text'] == buttons[2][2]['text'] != "":
buttons[0][0].config(bg="green")
buttons[1][1].config(bg="green")
buttons[2][2].config(bg="green")
return True
elif buttons[0][2]['text'] == buttons[1][1]['text'] == buttons[2][0]['text'] != "":
buttons[0][2].config(bg="green")
buttons[1][1].config(bg="green")
buttons[2][0].config(bg="green")
return True
elif empty_spaces() is False:
for row in range(3):
for column in range(3):
buttons[row][column].config(bg='yellow')
return "Tie"
else:
return False
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.
creating a minesweeper game in pygame and i am getting a recursion error when running my code. how do i mitigate this? This is the code I have that checks to see if the clicked grid square is empty and if it is then it reveals that grid square as well as all the adjacent squares. the section that is getting this error is below:
def reveal_empty(rn,c, grid, revealed,box):
if grid[rn][c] != '0' and grid[rn][c] != '*':
revealed[rn][c] = True
if grid[rn][c] == '0':
revealed[rn][c] = True
# change row above
if rn-1 > -1:
r = grid[rn-1]
if c-1 > -1:
if not r[c-1] == '*':
revealed[rn-1][c-1] = True
reveal_empty(rn-1,c-1, grid, revealed,box)
if not r[c] == '*':
revealed[rn-1][c] = True
reveal_empty(rn-1,c, grid, revealed,box)
if c+1 < 10:
if not r[c+1] == '*':
revealed[rn-1][c+1] = True
reveal_empty(rn-1,c+1, grid, revealed,box)
#change same row
r = grid[rn]
if c-1 > -1:
if not r[c-1] == '*':
revealed[rn][c-1] + True
reveal_empty(rn,c-1, grid, revealed,box)
if c+1 < 10:
if not r[c+1] == '*':
revealed[rn][c+1] = True
reveal_empty(rn,c+1, grid, revealed,box)
#change row below
if rn+1 < 11:
r = grid[rn + 1]
if c-1 > -1:
if not r[c-1] == '*':
revealed[rn+1][c-1] = True
reveal_empty(rn+1,c-1, grid, revealed,box)
if not r[c] == '*':
revealed[rn+1][c] = True
reveal_empty(rn+1,c, grid, revealed,box)
if c+1 < 11:
if not r[c+1] == '*':
revealed[rn+1][c+1] = True
reveal_empty(rn+1,c+1, grid, revealed,box)
I guess you have this problem because there is no quick exit-clause for your recursive function. I suspect that because you don't check to see if the cell is already revealed ( revealed[row][col] == True ), then it never exits - it keeps recursing for ones already half-done in the processing queue (stack).
Maybe a quick check at the beginning of the function will fix it:
def reveal_empty( row, col, grid, revealed, box ):
if ( revealed[row][col] == False ):
# do recursive check else here!
else:
print("Cell[%d][%d] is already revealed" % ( row, col ) )
I figured it out. I had to add a check to each step of the recursion to check if the value has been revealed yet. see below:
# change row above
if rn-1 > -1:
r = grid[rn-1]
if c-1 >= -1:
if not r[c-1] == '*' and revealed[rn-1][c-1] == False:
revealed[rn-1][c-1] = True
if grid[rn-1][c-1] == '0':
reveal_empty(rn-1,c-1, grid, revealed,box)
if not r[c] == '*' and revealed[rn-1][c] == False:
revealed[rn-1][c] = True
if grid[rn-1][c] == '0':
reveal_empty(rn-1,c, grid, revealed,box)
if c+1 < 10:
if not r[c+1] == '*' and revealed[rn-1][c+1] == False:
revealed[rn-1][c+1] = True
if grid[rn-1][c+1] == '0':
reveal_empty(rn-1,c+1, grid, revealed,box)
#change same row
r = grid[rn]
if c-1 > -1:
if not r[c-1] == '*' and revealed[rn][c-1] == False:
revealed[rn][c-1] + True
if grid[rn][c-1] == '0':
reveal_empty(rn,c-1, grid, revealed,box)
if c+1 < 10:
if not r[c+1] == '*' and revealed[rn][c+1] == False:
revealed[rn][c+1] = True
if grid[rn][c+1] == '0':
reveal_empty(rn,c+1, grid, revealed,box)
#change row below
if rn+1 < 11:
r = grid[rn + 1]
if c-1 > -1:
if not r[c-1] == '*' and revealed[rn+1][c-1] == False:
revealed[rn+1][c-1] = True
if grid[rn+1][c-1] == '0':
reveal_empty(rn+1,c-1, grid, revealed,box)
if not r[c] == '*' and revealed[rn+1][c] == False:
revealed[rn+1][c] = True
if grid[rn+1][c] == '0':
reveal_empty(rn+1,c, grid, revealed,box)
if c+1 < 11:
if not r[c+1] == '*' and revealed[rn+1][c+1] == False:
revealed[rn+1][c+1] = True
if grid[rn+1][c+1] == '0':
reveal_empty(rn+1,c+1, grid, revealed,box)
I am making a tic tac toe game and trying to create a function that checks if 3 of the same spots in a row have the same input 'x' or '0'. I am having trouble with the three_in_row function I am trying to make to trigger game over. I am trying to figure out how to do this in a simple way so all rows or columns will be triggers if 3 X's or 0's are played... Here's what I have so far. This is in python 2.7.13
(this is only part of the code I think should be relevant)
def setup_board(size):
board = []
for row in range(size):
board.append([])
for col in range(size):
board[row].append(empty)
return board
def three_in_row(b):
b[0][0] and b[0][1] and b[0][2] == 'x'
def game_over(b):
if three_in_row(b) == True:
print "Congratulations You Win!"
else:
return False
def tic_tac_toe():
b = setup_board(3)
run_game(b)
In my opinion, it might make more sense to store X's as +1 and O's as -1, so that you can easily do arithmetic to check if the game is over.
For example:
def three_in_row(b):
xWin = check_winner(b,3)
oWin = check_winner(b,-3)
return xWin | oWin
def check_winner(b, valToCheck):
foundWin = any(sum(r) in {valToCheck} for r in b) # check rows
# now check columns
for i in range(3):
foundWin = foundWin | (sum([b[j][i] for j in range(3)]) == valToCheck)
# now check diagonals
foundWin = foundWin | (sum([b[i][i] for i in range(3)]) == valToCheck)
foundWin = foundWin | (sum([b[i][2-i] for i in range(3)]) == valToCheck)
return foundWin
Thanks to Blender for the following more succinct method:
def three_in_row(b):
return any(sum(r) in {3, -3} for r in b)
def line_match(game):
for i in range(3):
set_r = set(game[i])
if len(set_r) == 1 and game[i][0] != 0:
return game[i][0]
return 0
#transposed column function for future use
#def column(game):
# trans = numpy.transpose(game)
# for i in range(3):
# set_r = set(trans[i])
# if len(set_r) == 1 and trans[i][0] != 0:
# return list(set_r)[0]
def diagonal_match(game):
if game[1][1] != 0:
if game[1][1] == game[0][0] == game[2][2]:
return game[1][1]
elif game[1][1] == game[0][2] == game[2][0]:
return game[1][1]
return 0
The correct syntax for the checks is either:
b[0][0] == 'x' and b[0][1] == 'x' and b[0][2] == 'x'
or (more succinctly):
b[0][0] == b[0][1] == b[0][2] == 'x'
You are also missing a return just before your check, like:
return b[0][0] == b[0][1] == b[0][2] == 'x'
Anyways, your code does not iterate over all the rows. A possible correction would be:
def three_in_row(b):
for row in rage(0, 3):
if b[row][0] == b[row][1] == b[row][2] == 'x':
return True
return False
Doing a three_in_column(b) should be fairly easy (changing b[row][n] in b[n][column]), so is also manually checking the two diagonals.
Hey everyone im new here and im trying to make a game called HiQ now i got the board drawn and everything and i can click on one of the pieces, but when i do the piece does change color and i get an error in the shell as well (listed below) im not sure why im getting this and i was hoping you guys could give me better insight. Ill provide my code below as well and it is coded in python 3, thank you
builtins.IndexError: list index out of range
boardcirc =[[0,0,0,1,1,1,0,0,0],
[0,0,0,1,1,1,0,0,0],
[0,0,0,1,1,1,0,0,0],
[1,1,1,1,1,1,1,1,1],
[1,1,1,1,2,1,1,1,1],
[1,1,1,1,1,1,1,1,1],
[0,0,0,1,1,1,0,0,0],
[0,0,0,1,1,1,0,0,0],
[0,0,0,1,1,1,0,0,0]]
def HiQ():
splash_screen()
make_board()
def make_board():
make_sqr()
make_circ()
get_click()
def get_click():
global count, boardcirc
while 1!=0:
count = count - 1
displaymessage("Pieces: " + str(count))
where = win.getMouse()
col = where.x//90
row = where.y//90
valid_move(row,col)
make_move(row,col)
def valid_move(row,col):
if boardcirc[row][col] == 0:
return False
if boardcirc[row-1][col] == 1 and boardcirc[row-2][col] == 1:
return True
if boardcirc[row+1][col] == 1 and boardcirc[row+2][col] == 1:
return True
if boardcirc[row][col-1] == 1 and boardcirc[row][col-2] == 1:
return True
if boardcirc[row][col+1] == 1 and boardcirc[row][col+2] == 1:
return True
def make_move(row,col):
while valid_move(row,col) == True:
col = (col*85)+42
row = (row*85)+42
circ = Circle(Point(col,row),35)
circ.setFill("white")
circ.draw(win)
thats everything that applies to the error
For your valid_move(row,col), you can't have all those if statements.
Instead of doing this, use elif's after the initial if statement, and don't forget to write an else statement
if boardcirc[row][col] == 0:
return False
if boardcirc[row-1][col] == 1 and boardcirc[row-2][col] == 1:
return True
elif boardcirc[row+1][col] == 1 and boardcirc[row+2][col] == 1:
return True
elif boardcirc[row][col-1] == 1 and boardcirc[row][col-2] == 1:
return True
elif boardcirc[row][col+1] == 1 and boardcirc[row][col+2] == 1:
return True
else:
return False