I have created a multiplayer game of Noughts and Crosses using Python 3.
I have got all of my code to work except for the check loop.
The check loop will each time a new symbol is entered if it is a winning move or if the board is full.
Currently, my code does not finish after one player inputs 3 symbols in a row or the board becomes full.
This is my code so far:
import random
def start_player():
startplayer = random.randint(1,2)
if startplayer == 1:
turn = 'X'
print("Player One (X) will start the game.")
else:
startplayer == 2
turn = 'O'
print("Player Two (O) will start the game.")
return turn
def getmove():
row = int(input("Please enter a number between 0 and 2: "))
column = int(input("Please enter a number between 0 and 2: "))
while grid[row][column] != "":
print("Invalid move.")
row = int(input("Please enter a number between 0 and 2: "))
column = int(input("Please enter a number between 0 and 2: "))
return row, column
def mainturn(row, column):
global countmove
countmove = countmove + 1
global symbol
grid[row][column] = symbol
for y in range(0,(len(grid))):
print(grid[y])
if symbol == 'X':
symbol = 'O'
elif symbol == 'O':
symbol = 'X'
return countmove
def check_win(row, column, symbol):
if (grid[0][0] and grid[0][1] and grid[0][2] == symbol) or (grid[1][0] and grid[1][1] and grid[1][2] == symbol) or (grid[2][0] and grid[2][1] and grid[2][2] == symbol) or (grid[0][0] and grid[1][0] and grid[2][0] == symbol) or (grid[0][1] and grid[1][1] and grid[2][1] == symbol)or (grid[0][2] and grid[1][2] and grid[2][2] == symbol)or (grid[0][0] and grid[1][1] and grid[2][2] == symbol) or (grid[2][0] and grid[1][1] and grid[0][2] == symbol):
print("Well done!",symbol," won the game.")
return true
elif countmove == 9:
print("Board Full. Game over.")
#main program
grid = [["","",""],["","",""],["","",""]]
countmove = 0
win = 'false'
for y in range(0,(len(grid))):
print(grid[y])
symbol = start_player()
while countmove != 9 or win == 'false':
countmove = 0
row, column = getmove()
mainturn(row,column)
win = check_win(row,column, symbol)
It is because of two things. Firstly you are resetting count_move value in the loop, hence it is always zero and goes in an infinite loop. Secondly you are changing the symbol before checking if it is a win, check_win routine was checking for the next symbol not the current symbol of the player. Here is the working code:
while countmove != 9 or win == 'false':
row, column = getmove()
mainturn(row,column)
win = check_win(row,column, symbol)
symbol = change_symbol(symbol)
The sub-routine change_symbol is here:
def change_symbol(symbol):
if symbol == 'X':
symbol = 'O'
elif symbol == 'O':
symbol = 'X'
return symbol
As part of good coding practice, avoid using global variables inside subroutines, it will just add up the confusion.
I did my best to comment on why I did things and why I removed things. I hope this example helps you see why it cant be better to use classes when working with python. I added some other features that I think may help you as you continue to learn programming
import random
# Lets put all these functions into a class
class Game:
# Lets set up the game
def __init__(self, player_one="X", player_two="O"):
self.player_one = player_one
self.player_two = player_two
# Where the game board is stored
# Using periods instead of spaces so the players can see the possible moves
self.game_board = [
[".", ".", "."],
[".", ".", "."],
[".", ".", "."]
]
# This value is to check if the game is still going
self.running = True
# Whos turn is it?
self.active_player = ""
# The tasks we HAVE to do to make the game work
self.start_player()
self.run_game()
# The function is part of the Game class so we have to pass self into it.
def start_player(self):
# Randomly Choose a starting player
startplayer = random.randint(1,2)
if startplayer == 1:
# We declared the string values in the __init__ function
player = self.player_one
print("Player One ({}) will start the game.".format(player))
else:
startplayer == 2
player = self.player_two
print("Player Two ({}) will start the game.".format(player))
# Set the initial player
self.active_player = player
def get_move(self):
# Seems silly to have them enter the rows and columns one by one
#row = int(input("Please enter a number between 0 and 2: "))
#column = int(input("Please enter a number between 0 and 2: "))
# Show the player whos turn it is
input_data = input("Player ({}) please choose a Column and a Row: ".format(self.active_player))
# Default values that aren't in the game, if they arent changed they will be caught
row = -1
column = -1
# Users entry all types of funky data, lets make sure its right
try:
r, c = input_data.split(" ")
r = int(r)
c = int(c)
if r >= 0 and r <= 3:
row = int(r)
if c >= 0 and c <= 3:
column = int(c)
except:
print("Enter only two numbers (0, 1, or 2) seperated by a space")
return row, column
# This check for the grid should be its own function
#while grid[row][column] != "":
# print("Invalid move.")
# row = int(input("Please enter a number between 0 and 2: "))
# column = int(input("Please enter a number between 0 and 2: "))
def check_move(self, row, column):
if row == -1 or column == -1:
return False
# If the space is blank return True
if self.game_board[row][column] == ".":
return True
print("{} {} is an invalid move, try again".format(row, column))
return False
# Add another function to print out the board for us
def show_board(self):
for row in self.game_board:
row_string = ""
for cell in row:
row_string = "{} {} ".format(row_string, cell)
print(row_string)
#def mainturn(row, column):
# Try to avoid using globals. We'll store these in our class
#global countmove
#countmove = countmove + 1
#global symbol
#grid[row][column] = symbol
#for y in range(0,(len(grid))):
# print(grid[y])
#if symbol == 'X':
# symbol = 'O'
#elif symbol == 'O':
# symbol = 'X'
#return countmove
# This is one heck of an if statement. Lets turn it into a function
# if (grid[0][0] and grid[0][1] and grid[0][2] == symbol) or (grid[1][0] and grid[1][1] and grid[1][2] == symbol) or (grid[2][0] and grid[2][1] and grid[2][2] == symbol) or (grid[0][0] and grid[1][0] and grid[2][0] == symbol) or (grid[0][1] and grid[1][1] and grid[2][1] == symbol)or (grid[0][2] and grid[1][2] and grid[2][2] == symbol)or (grid[0][0] and grid[1][1] and grid[2][2] == symbol) or (grid[2][0] and grid[1][1] and grid[0][2] == symbol):
def check_win(self, symbol):
combinations = [
# horizontal
[(0,0), (1,0), (2,0)],
[(0,1), (1,1), (2,1)],
[(0,2), (1,2), (2,2)],
# vertical
[(0,0), (0,1), (0,2)],
[(1,0), (1,1), (1,2)],
[(2,0), (2,1), (2,2)],
# crossed
[(0,0), (1,1), (2,2)],
[(2,0), (1,1), (0,2)]
]
for coordinates in combinations:
letters = [self.game_board[x][y] for x, y in coordinates]
# If all the letters match
if "." not in letters:
if len(set(letters)) <= 1:
# returns corresponding letter for winner (X/O)
print("Well done {}! You won the game!".format(symbol))
self.running = False
return True
return False
# Lets try another method of checking if the board is full
#elif countmove == 9:
# print("Board Full. Game over.")
#main program
def board_full(self):
for row in self.game_board:
if "." in row:
return False
print("The game is a draw :( ")
# Stop the game
self.running = False
return True
def run_game(self):
# While the game is not over
while self.running != False:
# Show the player the board
self.show_board()
row, column = self.get_move()
# Is the move valid?
if self.check_move(row, column):
self.game_board[row][column] = self.active_player
# Did they win?
self.check_win(self.active_player)
# Change Players
if self.active_player == self.player_one:
self.active_player = self.player_two
else:
self.active_player = self.player_one
# Print the winning game board
self.show_board()
g = Game("X", "O")
# Handled this in the class
#grid = [["","",""],["","",""],["","",""]]
#countmove = 0
#win = 'false'
# Turned this code into the show_board function
#for y in range(0,(len(grid))):
#print(grid[y])
#symbol = start_player()
#while countmove != 9 or win == 'false':
# Shouldnt reset the countmove inside of the loop thats checking the countmove
#countmove = 0
#row, column = getmove()
#mainturn(row,column)
#win = check_win(row,column, symbol)
Example Output:
Player One (X) will start the game.
. . .
. . .
. . .
Player (X) please choose a Column and a Row: 0 1
. X .
. . .
. . .
Player (O) please choose a Column and a Row: 2 2
. X .
. . .
. . O
Player (X) please choose a Column and a Row: 0 0
X X .
. . .
. . O
Player (O) please choose a Column and a Row: 2 1
X X .
. . .
. O O
Player (X) please choose a Column and a Row: 0 2
Well done X! You won the game!
X X X
. . .
. O O
Related
I'm new to python and writing my first project. I'm trying to implement a check that if a space is already occupied, not to move there. I can't seem to figure out why my move_player method overwrites the index value of the board even though I am explicitly checking it (If it is O's turn and X has already been placed in the index O is trying to move to, it just overwrites it). I have tried hard coding the check for 'X' and 'O' instead of player.player as well but can't seem to figure it out. Does it have to do something with how Python works or am I implementing it wrong?
class Player:
def __init__(self, player):
self.player = player
class Board:
def __init__(self):
self.board = [[' ' for i in range(3)] for j in range(3)]
def display_board(self):
print('---------')
for row in self.board:
print('| ', end='')
for col in row:
print(f'{col} ', end='')
print('|')
print('---------')
def move_player(self, player):
try:
p1 = Player('X')
p2 = Player('O')
coordinates = [int(i) for i in input("Enter coordinates for move: ").split()]
xCoordinate = coordinates[0]
yCoordinate = coordinates[1]
if ((self.board[xCoordinate][yCoordinate] == p1.player) or
(self.board[xCoordinate][yCoordinate] == p2.player)):
print("That space is occupied, please choose another one.")
self.move_player(player)
else:
self.board[xCoordinate - 1][yCoordinate - 1] = player.player
except (ValueError, IndexError):
print("Please only enter numbers between 1 and 3.")
self.move_player(player)
def has_won(self, player):
if self.check_diagonal(player):
return True
elif self.check_across(player):
return True
elif self.check_down(player):
return True
return False
if __name__ == '__main__':
board = Board()
player1 = Player('X')
player2 = Player('O')
player = player1
while True:
board.display_board()
board.move_player(player)
if board.has_won(player):
board.display_board()
print(f'{player.player} wins!!!')
break
if player == player1:
player = player2
else:
player = player1
The code is very convoluted but from what I can see:
if ((self.board[xCoordinate][yCoordinate] == p1.player) or
(self.board[xCoordinate][yCoordinate] == p2.player)):
...
self.board[xCoordinate - 1][yCoordinate - 1] = player.player
You are checking [x,y] but assigning to [x-1,y-1].
I am making a connect four game with X's and O's. The code for checking for four in a row/column/diagonal works but I have a lot of if statements in my code. The game fully works right now but I'm wondering if there is an easier solution to the checking. Below, I have included all my code for context.
I have tried using coordinates. It seems kind of inefficient though. The function for checking is called check.
namex = input("Player X, enter your name. ") #asks for player 1 name
nameo = input("Player O, enter your name. ") #asks for player 2 name
game = [[".", ".", ".", ".", ".", "."], #gameboard
[".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", "."]]
loop = True
def output(matrix):
str1 = ""
str2 = ""
str3 = ""
str4 = ""
str5 = ""
str6 = ""
print("0 1 2 3 4 5 6 ") #print labels for columns in gameboard
for a in matrix:
row = 0
for b in a: #"a" is a column and "b" is a ./x/o
row += 1
if row == 1:
str1 += b
str1 += " "
if row == 2:
str2 += b
str2 += " "
if row == 3:
str3 += b
str3 += " "
if row == 4:
str4 += b
str4 += " "
if row == 5:
str5 += b
str5 += " "
if row == 6:
str6 += b
str6 += " "
print(str1) #print string for row 1
print(str2) #print string for row 2
print(str3) #print string for row 3
print(str4) #print string for row 4
print(str5) #print string for row 5
print(str6) #print string for row 6
def check(matrix): #function to check for four in row/column/diagonal to win
positionx = []
positiono = []
x = 0
for a in matrix:
y = 5
for b in a:
if b == "X":
positionx.append([x, y])
if b == "O":
positiono.append([x, y])
y -= 1
x += 1
for c1 in positionx:
'''check four in row/column/diagonal for x'''
for c2 in positionx:
for c3 in positionx:
for c4 in positionx:
if c4[0]-c3[0] == 1:#check for four in row
if c3[0]-c2[0] == 1:
if c2[0]-c1[0] == 1:
return "xwin"
if c4[1]-c3[1] == 1: #check for four in column
if c3[1]-c2[1] == 1:
if c2[1]-c1[1] == 1:
return "xwin"
if c4[0]-c3[0] == 1: #check four in diagonal
if c4[1]-c3[1] == 1:
if c3[0]-c2[0] == 1:
if c3[1]-c2[1] == 1:
if c2[0]-c1[0] == 1:
if c2[1]-c1[1] == 1:
return "xwin"
for d1 in positiono:
'''check four in row/column/diagonal for o'''
for d2 in positiono:
for d3 in positiono:
for d4 in positiono:
if d4[0]-d3[0] == 1: #check for four in row
if d3[0]-d2[0] == 1:
if d2[0]-d1[0] == 1:
return "owin"
if d4[1]-d3[1] == 1: #check for four in column
if d3[1]-d2[1] == 1:
if d2[1]-d1[1] == 1:
return "owin"
if d4[0]-d3[0] == 1: #check four in diagonal
if d4[1]-d3[1] == 1:
if d3[0]-d2[0] == 1:
if d3[1]-d2[1] == 1:
if d2[0]-d1[0] == 1:
if d2[1]-d1[1] == 1:
return "owin"
while loop == True:
xinput = input(namex + ", you're X. What column do you want to play in? Please enter a number 0-6 ")
xcolumn = int(xinput)
xrow = 5
occupied1 = False
while occupied1 == False:
if game[xcolumn][xrow] == ".": #if there is a "." change to "X"
game[xcolumn][xrow] = "X"
output(game)
occupied1 = True
xrow -= 1
if check(game) == "xwin":
loop = False
print(namex + " wins!")
break
if check(game) == "owin":
loop = False
print(nameo + " wins!")
break
oinput = input(nameo + ", you're O. What column do you want to play in? Please enter number 0-6 ")
ocolumn = int(oinput)
orow = 5
occupied2 = False
while occupied2 == False:
if game[ocolumn][orow] == ".": #if there is a "." change to "O"
game[ocolumn][orow] = "O"
output(game)
occupied2 = True
orow -= 1
if check(game) == "xwin":
loop = False
print(namex + " wins!")
break
if check(game) == "owin":
loop = False
print(nameo + " wins!")
break
I'm also open to any other suggestions to make my code for this game better. Thanks!
I had some spare time, so I rewrote your program. It's much more efficient now. Read the comments to understand how it works
cols = [[] for x in range(6)]
# I opted to have a matrix of COLUMNS rather than rows because you can easily
# append items to the end of the list to simulate a real tile being placed there
# it's more intuitive and saves us time, as you'll see
def checkWin(cols):
for i in range(6): # Each column
for j in range(6): # Each row
try: #check if the element at these coordinates exists yet
cols[i][j]
except IndexError:
break
# go back to next i - impossible that there's anything with a higher
# j because if a list is n items long, and we go to j (which is one
# higher than n and doesn't exist) then there can't be an element at
# index j + someNumber.
ret = False
try: #vertical: j is the index in each column, so this goes up the column
if cols[i][j] == cols[i][j+1] == cols[i][j+2] == cols[i][j+3] is not None:
ret = True
except IndexError: #one of the elements of the comparison doesn't exist
pass #We can't be sure that none of the other trials will return True
try: #horizontal
if cols[i][j] == cols[i+1][j] == cols[i+2][j] == cols[i+3][j] is not None:
ret = True
except IndexError:
pass
try: #diagonal
if cols[i][j] == cols[i+1][j+1] == cols[i+2][j+2] == cols[i+3][j+3] is not None:
ret = True
except IndexError:
pass
try: #other diagonal
if cols[i][j] == cols[i-1][j+1] == cols[i-2][j+2] == cols[i-3][j+3] is not None:
ret = True
except IndexError:
pass
if ret:
return cols[i][j]
return None # We've gone through every single possible element and there are NO matches
def printBoard(cols):
# Pretty intuitive function IMO - we swap i and j to go through rows.
returnstr = '\n1 2 3 4 5 6\n'
for i in range(6):
for j in range(6):
try:
cols[j][5-i]
except IndexError:
returnstr += '_ '
continue
returnstr += cols[j][5-i]+' '
returnstr += '\n'
print(returnstr)
playerX = input('Player X, input your name: ')
playerO = input('Player O, input your name: ')
if playerX == playerO:
print("Cannot have the same name!")
exit()
count = 0
while not checkWin(cols):
printBoard(cols)
i = input('{}, input your column (1-6): '.format(playerO if count else playerX))
try:
target = cols[int(i)-1]
if len(target) == 6:
print("Column {} is already full! Please pick another.".format(i))
continue
target.append('O' if count else 'X')
except ValueError:
print("'{}' is not a number! Try again.".format(i))
continue
except IndexError:
print("{} is not a valid column number! Please pick another.".format(i))
continue
count = (count+1) % 2
printBoard(cols)
if checkWin(cols) == 'X':
print('{} (Player X), you win!'.format(playerX))
else:
print('{} (Player O), you win!'.format(playerO))
A good start would be to write a generalized function that checks for a diagonal at an arbitrary location:
def diagonal(grid, x, y, piece):
'''
Return True if grid contains a four-in-a-row diagonal starting at coordinates
(x, y) and traveling downwards and to the right. Otherwise return False.
'''
for i in range(x, x+4):
# if this square does not contain the desired piece, return False
if grid[x+i][y+i] != piece
return False
# if we got all the way through the loop, this must be a diagonal
return True
Then you would call this function for every possible starting coordinate of a four square diagonal, for each player X and O.
To improve this function, you could add a way to check for diagonals that travel the other direction (up and to the right).
A few days ago a started making my simple board game. First of all, I generate a board for the game. It looks like this:
the gameboard generated for 13x13
Secondly, I place my character on the board, which is 'A':
The player placed
I made a dice for it which generates numbers from 1 to 6.
My goal right now is to get the 'A' character moving around by the dice on the '*' symbols, until it gets at the top left corner:
I need to get here by the dice
So here is my code that I tried:
import math
import random
import os
board= []
def generator(boardsize):
for row in range(boardsize+1):
brow = []
for column in range(boardsize+1):
if row == column == 0:
brow.append(' ')
elif row==0:
brow.append(str(column-1)[-1])
elif column==0:
brow.append(str(row-1)[-1])
elif ((math.ceil(boardsize/2)-1 )<= column) and(column <= (math.ceil(boardsize/2)+1)) or ((math.ceil(boardsize/2)-1 )<= row) and(row <= (math.ceil(boardsize/2)+1)):
if row == 1 or column == 1 or row == boardsize or column == boardsize:
brow.append('*')
else:
if row == (math.ceil(boardsize/2)) and column == (math.ceil(boardsize/2)):
brow.append('X')
elif row == (math.ceil(boardsize/2)) or column == (math.ceil(boardsize/2)):
brow.append('D')
else:
brow.append('*')
else:
brow.append(' ')
board.append(brow)
return board
def print_table(x):
os.system('cls')
for x in board:
print(' '.join(x))
number_from_dice= []
def dice():
min = 1
max = 6
x = random.randint(min, max)
number_from_dice[:]= [x]
return number_from_dice
def player1(x):
generator(x)
prev_char_y = 1
prev_char_x = math.ceil(x/2)+1
char_y= 1
char_x= math.ceil(x/2)+1
board[char_y][char_x] = "A"
print_table(x)
dice()
f = number_from_dice[0]
for i in range(f):
if(char_y<x):
if (board[char_y+1][char_x]) == '*':
char_y= char_y +1
board[char_y][char_x] = "A"
board[prev_char_y][prev_char_x] = '*'
prev_char_x = char_x
prev_char_y = char_y
print_table(x)
else:
if(char_x!=x):
char_x2 = char_x
if (board[char_y][char_x+1]=='*'):
char_x = char_x +1
board[char_y][char_x] = "A"
board[prev_char_y][prev_char_x] = '*'
prev_char_x = char_x
prev_char_y = char_y
print_table(x)
else:
if (board[char_y+1][char_x]) == '*':
char_y= char_y +1
board[char_y][char_x] = "A"
board[prev_char_y][prev_char_x] = '*'
prev_char_x = char_x
prev_char_y = char_y
print_table(x)
else:
if (board[char_y][char_x2-1]) == '*':
char_x2 = char_x2 -1
board[char_y][char_x2] = "A"
board[prev_char_y][prev_char_x] = '*'
prev_char_x = char_x2
prev_char_y = char_y
print_table(x)
else:
if (board[char_y+1][char_x2]) == '*':
char_y = char_y +1
board[char_y][char_x2] = "A"
board[prev_char_y][prev_char_x] = '*'
prev_char_x = char_x2
prev_char_y = char_y
print_table(x)
print('Number from dice: ', end='')
print(f)
player1(13)
Does the technic I used have potential? Or is it too complicated? How would you do it?
Just in a generic sense you've made it overly complicated.
Consider this - the board, as far as movement is concerned, is just a set of ordered spaces.
But right now you have information about how the board is created as part of the player code.
Best to separate this, and you will find that things get simpler.
Instead, have the player simply track it's progress, in other words, what numbered space is it on.
Then you can generate the board and, knowing the space numbers, you can see if it matches the player location.
And then take it one step further (and simpler still) and just draw the board on a 2D array, and then output that, instead of trying to figure out the board as you go line-by-line.
I have an excercise to do and I'm stuck. It's the board game Alak, not much known, that I have to code in python. I can link the execrcise with the rules so you can help me better. The code has the main part and the library with all the procedures and function.
from Library_alak import *
n = 0
while n < 1:
n = int(input('Saisir nombre de case strictement positif : '))
loop = True
player = 1
player2 = 2
removed = [-1]
board = newboard(n)
display(board, n)
while loop:
i = select(board, n, player, removed)
print(i)
board = put(board, player, i)
display(board, n)
capture(board, n, player, player2)
loop = True if again(board, n, player, removed) is True else False
if player == 1 and loop:
player, player2 = 2, 1
elif player == 2 and loop:
player, player2 = 1, 2
win(board, n)
print(win(board, n))
And here is the library:
def newboard(n):
board = ([0] * n)
return board
def display(board, n):
for i in range(n):
if board[i] == 1:
print('X', end=' ')
elif board[i] == 2:
print('O', end=' ')
else:
print(' . ', end=' ')
def capture(board, n, player, player2):
for place in range(n):
if place == player:
place_beginning = place
while board[place] != player:
place_end = place
if board[place + x] == player:
return board
else:
return board
def again(board, n, player, removed):
for p in board(0):
if p == 0:
if p not in removed:
return True
else:
return False
def possible(n, removed, player, i, board):
for p in range(n + 1):
if p == 1:
if board[p-1] == 0:
if p not in removed:
return True
else:
return False
def win(board, n):
piecesp1 = 0
piecesp2 = 0
for i in board(0):
if i == 1:
piecesp1 += 1
else:
piecesp2 += 1
if piecesp1 > piecesp2:
print('Victory : Player 1')
elif piecesp2 > piecesp1:
print('Victory : Player 2')
else:
return 'Equality'
def select(board, n, player, removed):
loop = True
while loop:
print('player', player)
i = int(input('Enter number of boxes : '))
loop = False if possible(n, removed, player, i, board)is True else True
return i
def put(board, player, i):
i -= 1
if board[i] == 0:
if player == 1:
board[i] = 1
return board
else:
board[i] = 2
return board
else:
put(board, player, i)
So my problems here are that I have few errors, the first one is that when I enter the number '1' when asked to enter a number of boxes ( which is the place to play on ) nothing happens. Then when entering any other number, either the error is : if board[place + x] == player:
NameError: name 'x' is not defined
or there seems to be a problem with the : if board[place + x] == player:
NameError: name 'x' is not defined
I would appreciate a lot if anyone could help me. I'm conscious that it might not be as detailed as it should be and that you maybe don't get it all but you can contact me for more.
Rules of the Alak game:
Black and white take turns placing stones on the line. Unlike Go, this placement is compulsory if a move is available; if no move is possible, the game is over.
No stone may be placed in a location occupied by another stone, or in a location where a stone of your own colour has just been removed. The latter condition keeps the game from entering a neverending loop of stone placement and capture, known in Go as ko.
If placing a stone causes one or two groups of enemy stones to no longer have any adjacent empty spaces--liberties, as in Go--then those stones are removed. As the above rule states, the opponent may not play in those locations on their following turn.
If placing a stone causes one or two groups of your own colour to no longer have any liberties, the stones are not suicided, but instead are safe and not removed from play.
You shouldn't use "player2" as a variable, there's an easier way, just use "player" which take the value 1 or 2 according to the player. You know, something like that : player = 1 if x%2==0 else 2
and x is just a increasing int from 0 until the end of the game.
I have been trying to program a variant of connect four for my programming class. The board is 6x8 in size. In the variant I'm trying to program, the winning condition is to essentially build an L.
This means any construction of the form
X
X
X X
is a winning condition.
I have been trying to make a function that checks every single column for the same symbol consecutively to build a pair. And a function to do the same for every row. With these two functions I would then check if 2 pairs are consecutive, because no matter how you combine a vertical and horizontal pair, it will always build an 'L'.
To make a clear board I'm using
def ClearBoardSingle():
global Board
Board = [['0' for i in range(8)] for i in range(6)]
BoardPrint()
PlayerMoveSingle()
And for my interface I'm using
def BoardPrint():
global Board
global GameMoves
global PlayerTurn
global Player1Symbol
global Player2Symbol
print('\n\nMoves done: ' + str(GameMoves))
print('To Restart: R | To Quit: Q')
print('Valid choices: 1, 2, 3, 4, 5, 6, 7, 8')
if PlayerTurn == 0:
print('It\'s ' +str(Player1Symbol) + '\'s Turn')
if PlayerTurn == 1:
print('It\'s ' +str(Player2Symbol) + '\'s Turn')
print(Board[0])
print(Board[1])
print(Board[2])
print(Board[3])
print(Board[4])
print(Board[5])
I already figured out how to change Variables inside the Board, and I'm pretty much done. The only thing I don't know how to implement is the winning condition. I tried this function for the Rows:
def VerticalList(Column):
global Board
global Choice
global Row0
Column = int(Column)
Choice = int(Choice)
print(Column,' C')
while Column > 0:
for Board[Column][Choice] in range(Column):
Row0.append(Board[Column][Choice])
if Column ==6 or Column == -1:
break
else:
VerticalList(Column-1)
if Column ==0:
break
else:
continue
if Column == 0:
Column += 1
while Column < 5:
Column +=1
if Row0[Column] == Row0[Column-1]:
print('Pair')
else:
print('No Pair')
pass
else:
pass
But it enters an endless Loop.
I have no ideas anymore on how to implement the winning condition. I'd appreciate any kind of help or ideas. If you want me to post the whole code or other kinds of snippets, ask for them.
Thank you in anticipation!
Cool problem, below looks like a lot of code, but it's not really. I haven't checked this extensively, so I'm not confident that it doesn't find false positives, but it seems to find L's that it should be finding. The main thing I did was use itertools.combinations to take all 4-sized groups of the positions of X's and then check if they looked like patterns I was expecting for L's. In check_four_group I look at the differences within the row and columns.
from itertools import combinations
def disp_board(board):
for row in board:
print(row)
def check_winning(board):
winning = False
#Find all row,col positions of the X's
x_poses = [(i,j) for i in range(6) for j in range(8) if board[i][j] == 'X']
#Loop through every combination of four X's since it takes four to make the 'L'
for group in combinations(x_poses,4):
if(check_four_group(group)):
winning = True
break
return winning
def check_four_group(group):
rows,cols = zip(*[(r,c) for r,c in group])
row_diffs = [rows[i+1]-rows[i] for i in range(len(rows)-1)]
col_diffs = [cols[i+1]-cols[i] for i in range(len(cols)-1)]
#Uncomment this to print the row and col diffs
#print(row_diffs)
#print(col_diffs)
# Finds:
# X
# X
# X X
if row_diffs == [1,1,0] and col_diffs == [0,0,1]:
return True
# Finds:
# X
# X
# X X
elif row_diffs == [1,1,0] and col_diffs == [0,-1,1]:
return True
# Finds:
# X X
# X
# X
elif row_diffs == [0,1,1] and col_diffs == [1,0,0]:
return True
# Finds:
# X X
# X
# X
elif row_diffs == [0,1,1] and col_diffs == [1,-1,0]:
return True
# Otherwise it's not there at all (not thinking about horizontal L's but could add that)
else:
return False
#Test case 1
def test_case_1():
board = [['0' for i in range(8)] for i in range(6)]
board[2][1] = 'X'
board[2][2] = 'X'
board[3][1] = 'X'
board[4][1] = 'X'
return board
#Test case 2
def test_case_2():
board = [['0' for i in range(8)] for i in range(6)]
board[2][1] = 'X'
board[2][0] = 'X'
board[3][1] = 'X'
board[4][1] = 'X'
return board
#Test case 3
def test_case_3():
board = [['0' for i in range(8)] for i in range(6)]
board[1][0] = 'X'
board[2][0] = 'X'
board[3][0] = 'X'
board[3][1] = 'X'
return board
#Test case 4
def test_case_4():
board = [['0' for i in range(8)] for i in range(6)]
board[1][2] = 'X'
board[2][2] = 'X'
board[3][2] = 'X'
board[3][1] = 'X'
return board
##################
#Start of program#
##################
board = test_case_1()
#board = test_case_2()
#board = test_case_3()
#board = test_case_4()
disp_board(board)
if check_winning(board):
print('Victory')
else:
print('Keep playing')