No7Ex Q No7Ex Q - 19 days ago 5
Python Question

Python: Trying to program a variant of connect four: Winning condition doesnt stop

I have been trying to programm a variant of connect four for my programming class. The board is 6x8 in size. In the variant Im 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 consecutively the same symbol 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 all in all pretty much done, the only thing I don't know how to impliment 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 ends in 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 kind of snippets ask for em.

Thank you in anticipation!

Answer

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')