Posts: 18
Threads: 4
Joined: Dec 2017
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?
Posts: 18
Threads: 4
Joined: Dec 2017
BUMP
Posts: 100
Threads: 3
Joined: Dec 2017
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.
Posts: 8,160
Threads: 160
Joined: Sep 2016
(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])
Posts: 18
Threads: 4
Joined: Dec 2017
Sorry about the 2d array, of course it's just a list of strings.
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.
Posts: 100
Threads: 3
Joined: Dec 2017
(Jan-04-2018, 03:31 PM)ShadowWarrior17 Wrote: Sorry about the 2d array, of course it's just a list of strings.
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. 
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.
Posts: 18
Threads: 4
Joined: Dec 2017
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.
Posts: 100
Threads: 3
Joined: Dec 2017
(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!
|