Python Forum
Connect Four Win Check Function
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Connect Four Win Check Function
#1
I am creating a Connect Four game and was wondering on how to create a function to determine if a player has won.

This is my board:
"|   |   |   |   |   |   |   |"
"|   |   |   |   |   |   |   |"
"|   |   |   |   |   |   |   |"
"|   |   |   |   |   |   |   |"
"|   |   |   |   |   |   |   |"
"|   |   |   |   |   |   |   |"
The nth term between each counter space is 4n-2.

I have started with something like this:
def wincheck(alist):
    x=0
    y=0
    pos=(4*x)-2
My board is stored as a 2d array, so the function will use that.

Any suggestions?
Reply
#2
BUMP Big Grin
Reply
#3
Quote:My board is stored as a 2d array, so the function will use that.
Your board is a list of strings; that's different than a 2-d array. I may sound like a pedantic ass, but it's important to be precise when talking about code. It also explains why you have to calculate the position with this pos=(4*x)-2.

Putting that aside, when someone adds a checker start with the position of the new checker and see if it makes a vertical, horizontal, or diagonal line. I would break the code up into individual functions for each check:

def check_for_win(board, starting_pos):
    if check_vertical(board, start_pos):
        return True
    if check_horizontal(board, starting_pos):
        return True
    if check_diagonal(board, starting_pos):
        return True
    return False
You could, of course, combine those with an or but I think this is easier to read. Each check_* function then just has a loop that changes the appropriate index to check of the counter is the same as the one in starting_pos.
Reply
#4
(Jan-04-2018, 01:59 PM)mpd Wrote: You could, of course, combine those with an or
or use any, e.g.

def check_for_win(board, starting_pos):
    checks = [check_vertical, check_horizontal, check_diagonal]
    return any([check(board, starting_pos) for check in checks])
Reply
#5
Sorry about the 2d array, of course it's just a list of strings. Wall

I like the idea of a win function with horizontal, vertical, and diagonal functions within. It's the same idea I had.
I don't know about the use of any, but thanks for the suggestion.

What if I just constantly checked every horizontal, vertical and diagonal every turn? If I used the top counter as the main index, and the other three were like a tail.(if it was a diagonal).

"| x |   |   |   |   |   |   |"
"|   | x |   |   |   |   |   |"
"|   |   | x |   |   |   |   |"
"|   |   |   | x |   |   |   |"
"|   |   |   |   |   |   |   |"
"|   |   |   |   |   |   |   |"
So the top left x is the main index one, and the other ones would follow it, so that diagonal would be checked like this:
"|   | x |   |   |   |   |   |"
"|   |   | x |   |   |   |   |"
"|   |   |   | x |   |   |   |"
"|   |   |   |   | x |   |   |"
"|   |   |   |   |   |   |   |"
"|   |   |   |   |   |   |   |"
And when the bottom right when "touches" the end the index moves down. Like a space invader sort or thing.
Please tell me that makes sense. Think
Reply
#6
(Jan-04-2018, 03:31 PM)ShadowWarrior17 Wrote: Sorry about the 2d array, of course it's just a list of strings. Wall

I like the idea of a win function with horizontal, vertical, and diagonal functions within. It's the same idea I had.
I don't know about the use of any, but thanks for the suggestion.

What if I just constantly checked every horizontal, vertical and diagonal every turn? If I used the top counter as the main index, and the other three were like a tail.(if it was a diagonal).

"| x |   |   |   |   |   |   |"
"|   | x |   |   |   |   |   |"
"|   |   | x |   |   |   |   |"
"|   |   |   | x |   |   |   |"
"|   |   |   |   |   |   |   |"
"|   |   |   |   |   |   |   |"
So the top left x is the main index one, and the other ones would follow it, so that diagonal would be checked like this:
"|   | x |   |   |   |   |   |"
"|   |   | x |   |   |   |   |"
"|   |   |   | x |   |   |   |"
"|   |   |   |   | x |   |   |"
"|   |   |   |   |   |   |   |"
"|   |   |   |   |   |   |   |"
And when the bottom right when "touches" the end the index moves down. Like a space invader sort or thing.
Please tell me that makes sense. Think

I'm not sure what you're referring to with "top counter". Whichever is the last checker (i.e., piece) played, start there and move in both directions, counting how many checkers are in the row.

Here's a start to how I'd do it using a board of numbers instead of the strings. You'll have to change the indexing for your board implementation...

# create a 7X7 board of 0's; 
board = [ [0 for x in range(7)] for y in range(7)]

def get_players_move():
   """This function prompts the user for a move.
   :return:  The x,y position of the resulting checker (i.e., playing piece)
   """
   # do whatever,
   return x,y

def player_won(board, pos):
   if check_vertical(board, pos):
      return True

def check_vertical(board, pos):
   """checking vertical is easy because there are no checkers above the one just played.
   This assumes the board indices grow down (lowest checker is highest index)
   """
   x,y = pos  # pos is the x,y position of the last checker played
   checker = board[x][y]  
   y += 1
   while y < len(board[x]):
      if checker == board[x][y]:
          count += 1
          y += 1
      else:
         break
    return count == 4

while gameOn:
   pos = get_players_move()
   if player_won(board, pos):
       print("You WIN")
       gameOn = False
For horizontal and diagonal checks, you'd have to change the indices differently. But it's mostly just loops.

I'm not sure if that's what your looking for... hope it helps.
Reply
#7
Essentially, my idea was to check every possible vertical, horizontal and diagonal possibility on the board after a player has "placed" a counter. However, that seems inefficient.

I like your idea, and may try to adapt it, but I'd like to keep my board in strings.

I'll probably do a function with three other functions within it(horizontal win check, vertical.....), and each of those functions will use a nested for loop to detect if the counter that has just been placed, triggers a win.
Reply
#8
(Jan-04-2018, 05:41 PM)ShadowWarrior17 Wrote: Essentially, my idea was to check every possible vertical, horizontal and diagonal possibility on the board after a player has "placed" a counter. However, that seems inefficient.

I like your idea, and may try to adapt it, but I'd like to keep my board in strings.

I'll probably do a function with three other functions within it(horizontal win check, vertical.....), and each of those functions will use a nested for loop to detect if the counter that has just been placed, triggers a win.

It's very inefficient when you consider the fact that once a piece is played, it could only create 4 possible "wins": horizontal, vertical, and two diagonals. You could even postpone the checking until a player has played at least 4 pieces.

I didn't expect you to use my stuff verbatim, I just wanted to give you an idea of how I'd approach it.

Have fun!
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Date format and past date check function Turtle 5 4,226 Oct-22-2021, 09:45 PM
Last Post: deanhystad
  Is there any way to check if a function is user-defined? dullboy 11 10,335 Oct-06-2016, 03:42 AM
Last Post: dullboy

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020