Skip to content

Instantly share code, notes, and snippets.

@gudnm
Last active June 22, 2016 21:31
Show Gist options
  • Save gudnm/49e7d75e9841d56a35f4ec71a80fff20 to your computer and use it in GitHub Desktop.
Save gudnm/49e7d75e9841d56a35f4ec71a80fff20 to your computer and use it in GitHub Desktop.
Gomoku game (also called Five in a Row)
class Gomoku:
def __init__(self, size):
self.size = size
self.board = ['-'] * size * size
self.inarow = 5
self.players = ['x', 'o']
self.curplayer = 1
def printboard(self):
s = self.size
b = self.board
print(' '.join(map(str, range(s+1)))) # print column numbers
for i in range(s):
# row number plus the row itself
# add spaces to make the board look square
print(str(i+1) + ' ' + ' '.join(b[i*s : (i+1)*s]))
def aimove(self): # IMPROVE!
import random
placed = False
# rudimentary AI, try and place an 'o' closer to most of the 'x's
count = 1
avgix = self.size/2 + 1 # initial estimate for row where 'x's congregate
avgjx = self.size/2 + 1 # initial estimate for column where 'x's congregate
for i in range(self.size):
for j in range(self.size):
index = i*self.size + j
if self.board[index] == 'x':
avgix = (avgix*count + i) / (count + 1)
avgjx = (avgjx*count + j) / (count + 1)
count += 1
sigma = 0.1 # normal distribution, sigma adjusted as space gets crowded
while not placed:
i, j = -1, -1
while not 0<=i<self.size:
i = int(random.gauss(avgix, sigma) + 1)
while not 0<=j<self.size:
j = int(random.gauss(avgjx, sigma) + 1)
index = i*self.size + j
if self.board[index] == '-':
placed = True
sigma += 0.1
return (i, j)
def win(self):
k = self.inarow
n = self.size
if n < k:
print("The board is too small, we can't play.")
return True
'''
rows
0,0 -> k ... 0,n-k
...
n-1,0 ... n-1,n-k
'''
for i in range(n):
for j in range(n-k+1):
index = i*n + j
match = True
for m in range(k-1):
# starting from index, check 5 to the right
cur = index + m
nxt = index + m+1
if (self.board[cur] != self.board[nxt]
or self.board[cur] == '-'):
match = False
break
if match:
return True
'''
columns
0,0 ... 0,n-1
|
k
...
n-k,0 ... n-k,n-1
'''
for i in range(n-k+1):
for j in range(n):
index = i*n + j
match = True
for m in range(k-1):
# starting from index, check 5 down
cur = index + m*n
nxt = index + (m+1)*n
if (self.board[cur] != self.board[nxt]
or self.board[cur] == '-'):
match = False
break
if match:
return True
'''
forward diagonals
0,0 ... 0,n-k
\
... k
n-k,0 ... n-k,n-k
'''
for i in range(n-k+1):
for j in range(n-k+1):
index = i*n + j
match = True
for m in range(k-1):
# starting from index, check 5 down and to the right
cur = index + m*(n+1)
nxt = index + (m+1)*(n+1)
if (self.board[cur] != self.board[nxt]
or self.board[cur] == '-'):
match = False
break
if match:
return True
'''
backwards diagonals
k
/
n-k,0 ... n-k,n-k
...
n-1,0 ... n-1,n-k
'''
for i in range(n-k, n):
for j in range(n-k+1):
index = i*n + j
match = True
for m in range(k-1):
# starting from index, check 5 up and to the right
cur = index + m*(-n+1)
nxt = index + (m+1)*(-n+1)
if (self.board[cur] != self.board[nxt]
or self.board[cur] == '-'):
match = False
break
if match:
return True
return False
def getnext(self):
i, j = 0, 0
if self.curplayer == 0: # AI's move
self.curplayer = 1
player = self.players[self.curplayer]
i, j = self.aimove()
cell = i*self.size + j
self.board[cell] = player
gomoku.printboard()
else: # human's move
self.curplayer = 0
player = self.players[self.curplayer]
placed = False
while not placed:
try:
j = int(raw_input("Column # for " + player + ", please: "))
i = int(raw_input("Row # for " + player + ", please: "))
except ValueError:
print("Must be a number. Try again?")
continue
if 0 <= i < self.size and 0 <= j < self.size:
index = i*self.size + j
if self.board[index] == '-':
self.board[index] = player
placed = True
gomoku.printboard()
else:
print("That wasn't a valid move. Try again? ")
else:
print("Must be a number between 1 and " + \
str(self.size + 1) + ". Try again? ")
if __name__ == '__main__':
assert Gomoku(1) != None
assert Gomoku(1).size == 1
assert Gomoku(1).win() == True
assert Gomoku(4).win() == True
g = Gomoku(5)
assert g.win() == False
print("All tests passed, let's play.")
gomoku = Gomoku(9)
gomoku.printboard()
while not gomoku.win():
gomoku.getnext()
gomoku.printboard()
print("Player " + gomoku.players[gomoku.curplayer] + " won the game!")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment