Skip to content

Instantly share code, notes, and snippets.

@poke
Created October 11, 2013 13:39
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save poke/6934842 to your computer and use it in GitHub Desktop.
Save poke/6934842 to your computer and use it in GitHub Desktop.
A simple Connect Four game in Python.
#! /usr/bin/env python3
from itertools import groupby, chain
NONE = '.'
RED = 'R'
YELLOW = 'Y'
def diagonalsPos (matrix, cols, rows):
"""Get positive diagonals, going from bottom-left to top-right."""
for di in ([(j, i - j) for j in range(cols)] for i in range(cols + rows -1)):
yield [matrix[i][j] for i, j in di if i >= 0 and j >= 0 and i < cols and j < rows]
def diagonalsNeg (matrix, cols, rows):
"""Get negative diagonals, going from top-left to bottom-right."""
for di in ([(j, i - cols + j + 1) for j in range(cols)] for i in range(cols + rows - 1)):
yield [matrix[i][j] for i, j in di if i >= 0 and j >= 0 and i < cols and j < rows]
class Game:
def __init__ (self, cols = 7, rows = 6, requiredToWin = 4):
"""Create a new game."""
self.cols = cols
self.rows = rows
self.win = requiredToWin
self.board = [[NONE] * rows for _ in range(cols)]
def insert (self, column, color):
"""Insert the color in the given column."""
c = self.board[column]
if c[0] != NONE:
raise Exception('Column is full')
i = -1
while c[i] != NONE:
i -= 1
c[i] = color
self.checkForWin()
def checkForWin (self):
"""Check the current board for a winner."""
w = self.getWinner()
if w:
self.printBoard()
raise Exception(w + ' won!')
def getWinner (self):
"""Get the winner on the current board."""
lines = (
self.board, # columns
zip(*self.board), # rows
diagonalsPos(self.board, self.cols, self.rows), # positive diagonals
diagonalsNeg(self.board, self.cols, self.rows) # negative diagonals
)
for line in chain(*lines):
for color, group in groupby(line):
if color != NONE and len(list(group)) >= self.win:
return color
def printBoard (self):
"""Print the board."""
print(' '.join(map(str, range(self.cols))))
for y in range(self.rows):
print(' '.join(str(self.board[x][y]) for x in range(self.cols)))
print()
if __name__ == '__main__':
g = Game()
turn = RED
while True:
g.printBoard()
row = input('{}\'s turn: '.format('Red' if turn == RED else 'Yellow'))
g.insert(int(row), turn)
turn = YELLOW if turn == RED else RED
@C0D3TT3
Copy link

C0D3TT3 commented Sep 28, 2016

Hi, I've tried this but it comes up with these errors: Traceback (most recent call last):
File "C:\Users\owner\Desktop\Documents\AA KalMan html\python\python 3.3.3\more different code from web c4.py", line 74, in
g.insert(int(row), turn)
File "C:\Users\owner\Desktop\Documents\AA KalMan html\python\python 3.3.3\more different code from web c4.py", line 37, in insert
self.checkForWin()
File "C:\Users\owner\Desktop\Documents\AA KalMan html\python\python 3.3.3\more different code from web c4.py", line 44, in checkForWin
raise Exception(w + ' won!')
Exception: R won!

@atherishispida
Copy link

That's how the code displays the winner. However, I noticed that R is the only piece that gets put on the board. Why does that happen?

@ilyes495
Copy link

ilyes495 commented Feb 20, 2018

This is the best winner check implementation, I just want to understand diagonalsPos and diagonalsNeg do?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment