Skip to content

Instantly share code, notes, and snippets.

@alexeiz
Last active August 22, 2016 21:08
Show Gist options
  • Save alexeiz/df33d3c8702eab4765a1d7367e29a11b to your computer and use it in GitHub Desktop.
Save alexeiz/df33d3c8702eab4765a1d7367e29a11b to your computer and use it in GitHub Desktop.
stones game
#!/usr/bin/env python3
from pprint import pprint
from copy import deepcopy
import functools
import sys
import re
def hash_game(game):
return game.get_hash()
def memoize(obj):
cache = obj.cache = {}
@functools.wraps(obj)
def memoizer(*args, **kwargs):
key = hash_game(*args)
if key not in cache:
cache[key] = obj(*args, **kwargs)
return cache[key]
return memoizer
def minimax(game_state):
return max(
map(lambda move: (move, min_play(game_state.next_state(move))),
game_state.get_available_moves()),
key = lambda x: x[1])
@memoize
def min_play(game_state):
if game_state.is_gameover():
return game_state.evaluate()
return min(
map(lambda move: max_play(game_state.next_state(move)),
game_state.get_available_moves()))
@memoize
def max_play(game_state):
if game_state.is_gameover():
return game_state.evaluate()
return max(
map(lambda move: min_play(game_state.next_state(move)),
game_state.get_available_moves()))
class Stones(object):
def __init__(self, m, n):
self.m = m
self.n = n
self.stones = m * n
self.board = [[1 for y in range(n)] for x in range(m)]
self.side = 0 # white
self.moves = []
pass
def get_available_moves(self):
moves = []
for i,row in enumerate(self.board):
for j,cell in enumerate(row):
if cell:
moves.append((i, j))
return moves
def next_state(self, move):
succ = deepcopy(self)
succ.moves.append(move)
succ.side = 1 - self.side
for i in range(move[0], succ.m):
if succ.board[i][move[1]] == 0:
break
else:
for j in range(move[1], succ.n):
if succ.board[i][j] == 0:
break
else:
succ.board[i][j] = 0
succ.stones -= 1
return succ
def is_gameover(self):
return self.stones == 0
def evaluate(self):
return 1 if self.side == 0 else -1
def get_hash(self):
return str((self.board, self.side))
def display(self):
for j in range(self.n):
print("{:2} ".format(self.n - j), end="")
for i in range(self.m):
if self.board[i][self.n - j - 1]:
print('* ', end="")
else:
print(' ', end="")
print()
print(" ", end="")
for i in range(self.m):
print("{:2}".format(i + 1), end="")
print()
def ask_move():
move = input("Your move? ")
m = re.match(r"(\d+),\s*(\d+)", move)
if m:
return (int(m.group(1)) - 1, int(m.group(2)) - 1)
def main():
game = Stones(int(sys.argv[1]), int(sys.argv[2]))
while not game.is_gameover():
move = minimax(game)
print("{}, {} : {}".format(move[0][0] + 1, move[0][1] + 1, move[1]))
game = game.next_state(move[0])
game.display()
move = ask_move()
game = game.next_state(move)
game.display()
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment