Reputation: 31
I've been working on a program that implements the game of connect 4 and I've hit a snag. Here's my output:
>>> ================================ RESTART ================================
>>>
Player 1 please pick a column: 5
-----------------------------
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
-----------------------------
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | x | |
-----------------------------
Player 2 please pick a column: 6
-----------------------------
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
-----------------------------
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | o |
-----------------------------
So basically the board isn't "updating" when alternating turns Essentially my code should end up looking like this:
-----------------------------
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
-----------------------------
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | x | o |
-----------------------------
I'm not too sure what I have to do to get the board to update properly. I've tried messing around with the print functions but the output ends up getting worse than before. Here is my code:
from player import *
def play_game(board, player1,player2):
b = ConnectFour()
f = Human(1)
g = Human(2)
while True:
f.play_turn(1)
if b.is_game_over() == None:
g.play_turn(2)
if b.is_game_over() == None:
pass
else:
print "Player 2 wins"
break
else:
print "Player 1 wins"
break
Basically: Player 1 plays, then we check if there's a winner if not player two plays, and so on. And this calls a separate class:
class Human(Player):
def play_turn(self,board):
super(Human, self).play_turn(board)
b = ConnectFour()
x = raw_input("Player %s please pick a column: " % self.playernum)
b.play_turn(self.playernum, int(x))
b.print_board()
Any ideas, input or advice would be greatly appreciated!
Upvotes: 2
Views: 2898
Reputation: 365807
The problem is that, although you're passing board
objects around, you ignore them and just create new ones everywhere.
First, look at Human.play_turn
:
def play_turn(self,board):
super(Human, self).play_turn(board)
b = ConnectFour()
x = raw_input("Player %s please pick a column: " % self.playernum)
b.play_turn(self.playernum, int(x))
b.print_board()
This passes board
to the super method Player.play_turn
, but then it creates a new board b = ConnectFour()
, and everything it does is to that board, not the original one.
Likewise, in play_game
, you take a board
, and a player1
and a player2
, but do nothing with them, and instead create new ones called b
, f
, and g
.
So, what you want is something like this:
def play_game(board, player1,player2):
while True:
player1.play_turn(board)
if board.is_game_over() == None:
player2.play_turn(board)
if board.is_game_over() == None:
pass
else:
print "Player 2 wins"
break
else:
print "Player 1 wins"
break
class Human(Player):
def play_turn(self,board):
super(Human, self).play_turn(board)
x = raw_input("Player %s please pick a column: " % self.playernum)
board.play_turn(self.playernum, int(x))
board.print_board()
That should fix your immediate problems—but I'm guessing you have very similar problems in all of your other functions.
Meanwhile, there are some odd things about your design.
For example, why are you checking if b.is_game_over() == None:
? A function called is_game_over
should probably be returning something truthy if the game is over, and something falsey if it's not. While None
is a reasonable "something falsey", False
is even more reasonable—and, either way, it's hard to imagine why you'd want to check for it explicitly, instead of just checking that it's falsey. (Plus, even if you do need to check specifically for None
for some reason, there's almost never a good reason to use == None
instead of is None
.)
Second, why do you need to create board
, player1
, and player2
outside of the play_game
function? It doesn't seem like they'd be all that useful outside this function.
Finally, even with just two players, I think your code would be simpler if you refactored the common parts:
def play_game(board, player1,player2):
while True:
for player in player1, player2:
player.play_turn(board)
if board.is_game_over():
print "Player {} wins".format(player.playernum)
break
One last thing: Your logic doesn't seem to account for the possibility that the game might be over because the current player has no move to make. I'm not sure if that's a tie or a loss in Connect 4, but I'm pretty sure it's not a win, is it?
Upvotes: 1