I have a problem with my "Game of life" on python - python

I don't know why but my "def" that checks 3 rules of "Game of live" doesn't work correctly. I have 2 lists that contains 0 and some 1 to check the program. 3 points that should give this image but instead it gives this
def upd(mass,screen,WHITE,mass1):
BLACK = (0,0,0)
for i in range(len(mass)-1):
for j in range(len(mass[i])-1):
if mass[i][j] == 0:
if near(mass,i,j) == True:
mass1[i][j]=1
print("case1")
if mass[i][j] == 1:
if (near(mass,i,j)==False):
mass1[i][j]=0
print("case 2")
if (near(mass,i,j)==False):
mass1[i][j]=0
print("case 3")
for i in range(len(mass1)-1):
for j in range(len(mass1[i])-1):
if mass1[i][j] == 1:
p.draw.rect(screen, (WHITE), Rect((j*10,i*10), (10,10)))
else:
p.draw.rect(screen, (BLACK), Rect((j*10,i*10), (10,10)))
mass=mass1
def near(mass,i,j):
counter = 0
if mass[i][j+1]==1:
counter+=1
if mass[i][j-1]==1:
counter+=1
if mass[i+1][j]==1:
counter+=1
if mass[i-1][j]==1:
counter+=1
if mass[i+1][j+1]==1:
counter+=1
if mass[i-1][j+1]==1:
counter+=1
if mass[i+1][j-1]==1:
counter+=1
if mass[i-1][j-1] == 1:
counter+=1
if counter<2 or counter == 0:
return False
if counter > 3:
return False
if counter == 3:
return True
log that repeats every circle
I am not good in python so I think this code is quite scarry:)
I'll be very grateful for any advice

mass = mass1 does not copy the contents of the grid, it just puts a reference to mass1 in mass (actually only in the local variable mass in scope of upd). You must deep copy the grid:
for i in range(len(mass1)):
for j in range(len(mass1[i])):
mass[i][j] == mass1[i][j]

Related

My Tic Tac Toe with use of the minimax algorithm is not working

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.

Check if there is a character that appears 5 consecutive times

I'm making an isWin function that checks if there is a character that appears 5 consecutive times (either horizontally, vertically or diagonally).
I've tried using this code:
#VERTICAL WIN
count = 0
for row in range(1,grid_height):
print(row)
for col in range(1,grid_width):
print(col)
if grid[row][col-2] == p_char:
count += 1
if count == 5:
return True
else:
count = 0
continue
#HORIZONAL WIN
count=0
for col in range(0,grid_width):
for row in range(0,grid_height):
if grid[row][col-2] == p_char:
count += 1
if count == 5:
return True
else:
count = 0
continue
And this is where i place it in my main program:
def play():
grid,grid_height,grid_width,p1_name,p1_char,p2_name,p2_char=getGameSettings()
displayGrid(grid,grid_height,grid_width)
print('WELCOME TO THE GAME!')
playerA = Player(p1_name, PLAYING)
playerB = Player(p2_name, WAITING)
grid=[]
for row in range(grid_height): # FOR ROW
z =[]
for col in range(grid_width): # FOR COLUMN
z.append(" ")
grid.append(z)
numColFull = 0
turn=0
while turn < grid_height*grid_width:
player = playerA
if turn % 2 == 0 : #IF TURN IS AN ODD NUMBER, THEN IT IS player 1's turn, IF TURN IS EVEN, THEN IT IS player 2's turn
p_char= p1_char
player = playerA
playerA.setState(PLAYING)
playerB.setState(WAITING)
else :
p_char= p2_char
player = playerB
playerB.setState(PLAYING)
playerA.setState(WAITING)
print(".................................................. ")
print("User to play : ", player.playerInfo() , " SEQ : ", str(turn)) # TO COUNT THE TOTAL NUMBER OF MOVES
print(".................................................. ")
if numColFull == grid_width: #THE isDRAW function but embedded into the main function
# IF the numColFull is equal to gridwidth, it means that all of the columns has been occupied, meaning
#that every space has already been occupied, thus, game is over.
print('........All spaces had been occupied...........')
print('................THE GAME IS DRAW...............')
print('.................GAME OVER.....................')
break
else:
while True:
try:
move=int(input('Enter your move: '))
except ValueError:
print('Please enter a valid input.')
if move < 1 or move > grid_width:
print('Please enter a valid input.')
continue
break
updateGrid(grid,grid_height-1,grid_width,move,p_char)
while True:
if grid[0][move-2] == p_char: #IF THE TOP ROW OF A COLUMN HAS A PIECE IN IT, IT MEANS ITS ALREADY FULL
displayGrid(grid,grid_height, grid_width)
print('Column is full. Please choose another column for the next move.')
numColFull += 1
break
elif isWin == True: #IF THE IF CONDITION DIDNT HOLD TRUE, THEN THE FUNCTION CONTINUES AS USUAL
print(player, 'WINS!!!')
('.................GAME OVER.....................')
else:
displayGrid(grid,grid_height, grid_width)
break #GOES BACK TO THE THE WHILE CONDITION
turn += 1 #INCREMENTS 1 TO TURN SO IT WILL SWITCH BETWEEN BEING ODD AND EVEN
And this is my grid:
def displayGrid(grid,grid_height,grid_width):
for row in range(1,grid_height):
#print(row) #for checking
for col in range(grid_width):
print("|", end="")
print(str(grid[row-1][col-1]),end = "")
print("|")
print(" "+" ".join([str(i) for i in range(1, grid_width+1)]))
return grid
def updateGrid(grid,grid_height,grid_width,move,p_char):
for i in range(1,grid_height+1):
print(i)
#print(i) #ROW COUNTING STARTS FROM 1
if grid[grid_height-i][move-2] == " ":
grid[grid_height-i][move-2]= p_char #REPLACES THE " " TO THE CURRENT PLAYER'S CHARACTER (p_char)
else:
continue
break
return grid
I guess you are writing Five In a Row? But anyway, this code should work:
def isWin():
# Horizontal
for i in range(grid_height):
for j in range(grid_width - 4):
if set(grid[i][j:j+5]) == {p_char}:
return True
# Vertical
for i in range(grid_height - 4):
for j in range(grid_width):
if { grid[i+k][j] for k in range(5) } == {p_char}:
return True
# Diagonal
for i in range(grid_height - 4):
for j in range(grid_width - 4):
if { grid[i+k][j+k] for k in range(5) } == {p_char}:
return True
return False
# Simplified
def isWin():
return any(set(grid[i][j:j+5]) == {p_char} for i in range(grid_height) for j in range(grid_width - 4)) or \
any({ grid[i+k][j] for k in range(5) } == {p_char} for i in range(grid_height - 4) for j in range(grid_width)) or \
any({ grid[j+k][i+k] for k in range(5) } == {p_char} for i in range(grid_width - 4) for j in range(grid_width - 4))
Since set cannot have duplicates, using expressions like { grid[j+k][i+k] for k in range(5) } will put 5 consecutive pieces into a set. If there are 5 consecutive p_chars, then the set will become {p_char}.

Loop stops even though only 1 of 2 variables is true

So I'm attempting to make a Brainfuck interpreter, however in the while loop that I am using to execute the Brainfuck loop, it is breaking out even though only one condition is true.
Example:
+++[>+<-]
Should result in:
[0, 3]
However, when the loop begins at [, it will create a new cell so the structure goes from [3] to [3, 0]. Thus, the current working cell is 0 and the loop is breaking out. However, I have it to only break if it is 0 and the current character is ].
cells = [0] # Array of data cells in use
brainfuck = str(input("Input Brainfuck Code: ")) # Brainfuck code
workingCell = 0 # Data pointer position
count = 0 # Current position in code
def commands(command):
global cells
global workingCell
if command == ">":
workingCell += 1
if workingCell > len(cells) - 1:
cells.append(0)
elif command == "<":
workingCell -= 1
elif command == "+":
cells[workingCell] += 1
elif command == "-":
cells[workingCell] -= 1
elif command == ".":
print(chr(cells[workingCell]))
elif command == ",":
cells[workingCell] = int(input("Input: "))
def looper(count):
global cells
global workingCell
print("START LOOP", count)
count += 1
looper = loopStart = count
while brainfuck[looper] != "]" and cells[workingCell] != 0: # This line is causing trouble
if brainfuck[looper] == "]":
looper = loopStart
commands(brainfuck[looper])
count += 1
looper += 1
return count
while count < len(brainfuck):
if brainfuck[count] == "[":
count = looper(count)
print("END LOOP", count)
else:
commands(brainfuck[count])
count += 1
Thank you in advance.
I have it to only break if it is 0 and the current character is ]
If that's what you want, you have the logic in your while wrong. It should be:
while not (brainfuck[looper] == "]" and cells[workingCell] == 0):
And according to deMorgan's Laws, when you distribute not across and, you invert each of the conditions and change and to or, so it should be:
while brainfuck[looper] != "]" or cells[workingCell] != 0:
If this is confusing, you could just write:
while True:
if brainfuck[looper] == "]" and cells[workingCell] == 0:
break
This mirrors what you said in the description exactly.

List index out of range when coding a valid move for board game

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

Table tennis simulator

I edited my previous question because I came up with the code I think is correct.
The logic behind this should be:
while the set is not over and it's not a tie 10:10: player A starts serving and does it twice regardless he wins points or not, then player B takes serve and does it twice also. It continues until the set is over, except there is a tie 10:10 when servers change each point scored.
Can anyone check if the code is flawless? thank you.
def simOneSet(probA, probB):
serving = "A"
scoreA = scoreB = 0
while not setOver(scoreA, scoreB):
if scoreA != 10 and scoreB != 10:
if serving == "A":
for i in range(2):
if random() < probA:
scoreA += 1
else:
scoreB += 1
serving = "B"
else:
for i in range(2):
if random() < probB:
scoreB +=1
else:
scoreA += 1
serving = "A"
# when there is a tie 10:10
else:
if serving == "A":
if random() < probA:
scoreA += 1
serving = "B"
else:
scoreB += 1
serving = "B"
else:
if random() < probB:
scoreB += 1
serving = "B"
else:
scoreA += 1
serving = "A"
return scoreA, scoreB
I would use a dict to "switch" between players:
other = {'A':'B', 'B':'A'}
Then, if serving equals 'A', then other[serving] would equal 'B', and if serving equals 'B', then other[serving] would equal 'A'.
You could also use a collections.Counter to keep track of the score:
In [1]: import collections
In [2]: score = collections.Counter()
In [3]: score['A'] += 1
In [4]: score['A'] += 1
In [5]: score['B'] += 1
In [6]: score
Out[6]: Counter({'A': 2, 'B': 1})
Also notice how in this piece of code
if serving == "A":
for i in range(2):
if random() < probA:
scoreA += 1
else:
scoreB += 1
else:
for i in range(2):
if random() < probB:
scoreB +=1
else:
scoreA += 1
there are two blocks which are basically the same idea repeated twice. That's a sign that the code can be tightened-up by using a function. For example, we could define a function serve which when given a probability prob and a player (A or B) returns the player who wins:
def serve(prob, player):
if random.random() < prob:
return player
else:
return other[player]
then the above code would become
for i in range(2):
winner = serve(prob[serving], serving)
score[winner] += 1
Thus, you can compactify your code quite a bit this way:
import random
import collections
other = {'A':'B', 'B':'A'}
def serve(prob, player):
if random.random() < prob:
return player
else:
return other[player]
def simOneSet(probA, probB):
prob = {'A':probA, 'B':probB}
score = collections.Counter()
serving = "A"
while not setOver(score['A'], score['B']):
for i in range(2):
winner = serve(prob[serving], serving)
score[winner] += 1
if score['A'] == 10 and score['B'] == 10:
winner = serve(prob[serving], serving)
score[winner] += 1
serving = winner
return score['A'], score['B']
def setOver(scoreA, scoreB):
return max(scoreA, scoreB) >= 21
print(simOneSet(0.5,0.5))
Here is a hint:
If you have the roundnumber in the set and know which player started serving, you have everything you need to know who is serving.
Then a simple if statement at the start or end of your loop should be enough.
If this is too complicated, try starting by simulating a game where the server starts every round.
Something that might help is the syntax
var = 1 if var == 2 else 2
Which will make var be 1 if var is 2, and var be 2 if var is 1. I feel as though this is a school problem, so I don't want to totally give away the answer :)
Hint: You're on the right track with your thinking.
from random import *
P1=P2=0
while 1 :
p1=p2=0
while 2 :
if random() < 0.5 : p1 +=1
else : p2 +=1
if(p1 >=11 or p2 >=11) and abs(p1-p2) > 1: break
P1 += p1 > p2; P2 += p2 > p1
print "%2d : %2d (%d : %d)" % (p1, p2, P1, P2)
if P1 == 4 or P2 == 4 : break
i hope this helps, it worked for me

Categories