vsc
vsc

Reputation: 359

Connect4 w/ AI Bots: Best Move Diagonally (python)

I am currently trying to code for a function that will pick the best column to drop the piece so there be a connect 4 diagonally. So from the given game_board, the function should return winning_col = 4. But I'm sure what to do and this is what I've started.

game_board = 
[['_','_','_','-','-'],
['-','-','-','-','-'],
['_','_','_','o','o'],
['-','-','o','x','x'],
['-','o','o','x','o']]

num_row= 5
num_col= 5
num_piece = 3
game_piece = 'o'

for rows in range(num_row - num_piece + 1):
  for cols in range(num_piece - 1, num_col):
    index = 0
  for counts in range(num_piece):
    if game_board[rows + index][cols - index] == game_piece and game_board[rows + index][cols] == game_piece:
      index += 1
      winning_col = cols
    else:
      break
    if index == num_piece:
      print (winning_col)

Upvotes: 1

Views: 329

Answers (1)

Samwise
Samwise

Reputation: 71464

A typical way to handle the general problem of finding the winning move in a board game is first to write a function that will tell you if a given board setup is a win. Take a look at this answer for some ideas on how to do that:

Finding neighbor cells in a grid with the same value. Ideas how to improve this function?

So, starting with the do_we_have_a_winner function from that question (which will work for any "N in a row" type game, e.g. tic tac toe or connect 4), I'm going to add another helper, which is a function specifically for connect-4 that drops a piece into the board:

def drop_piece(
    board: List[List[str]],
    piece: str,
    col: int
) -> List[List[str]]:
    """Drops the piece into the board, returning the modified board."""
    new_board = [[p for p in row] for row in board]
    for row in reversed(new_board):
        if row[col] is None:
            row[col] = piece
            return new_board
    raise ValueError(f"Column {col} is full!")

And now I'm going to set up my board and define a nice way to print it:

def print_board(board: List[List[str]]):
    for row in board:
        print("".join(p if p else '-' for p in row))


game_board = [
    [p if p not in {'_', '-'} else None for p in row]
    for row in [
        ['_', '_', '_', '-', '-'],
        ['-', '-', '-', '-', '-'],
        ['_', '_', '_', 'o', 'o'],
        ['-', '-', 'o', 'x', 'x'],
        ['-', 'o', 'o', 'x', 'o']
    ]
]
game_piece = 'o'

Now that I've done that setup, the problem is easy: for each column, see what the board would look like if we dropped a piece there, and then see if that makes us a winner!

print_board(game_board)
print(f"Looking for a winning move for {game_piece}...")
for col in range(len(game_board[0])):
    test_board = drop_piece(game_board, game_piece, col)
    if do_we_have_a_winner(test_board, 4) == game_piece:
        print(f"Winning move is column {col}!")
        print_board(test_board)
        break
-----
-----
---oo
--oxx
-ooxo
Looking for a winning move for o...
Winning move is column 4!
-----
----o
---oo
--oxx
-ooxo

Upvotes: 1

Related Questions