""" peg.py An implementation of tringular peg solitaire[1] using Zelle's graphics library[2]. [1] https://en.wikipedia.org/wiki/Peg_solitaire [2] https://mcsp.wartburg.edu/zelle/python/ Jim Mahoney | cs.marlboro.college | MIT License | Nov 2019 """ from graphics import * from math import sqrt # peg geometry # # +-----------------------+ y=0 # | | + # | * | |\ # | * * | sqrt(3) | \ 1 # | * * * | ------ | \ # | * * * * | 2 +---+ # | * * * * * | 1/2 # | * * * * * * | # | | # +-----------------------+ y=WINDOW_SIZE # # x=0 x=WINDOW_SIZE # I'll denote global constants by CAPITAL_LETTER_NAMES . WINDOW_SIZE = 1000 # width & height in pixels WINDOW_BORDER = 100 # space around the peg array in pixels N_PEGS = 6 # number of pegs on each side of the triangle # Calculate distances between pegs & peg size from the previous constants. PEG_X_APART = (WINDOW_SIZE - 2 * WINDOW_BORDER) // (N_PEGS - 1) PEG_Y_APART = int( sqrt(3)/2 * PEG_X_APART) PEG_RADIUS = int( PEG_X_APART / 2.5 ) PEG_COLOR = { 'background' : 'blue', 'border' : 'black', 'hover' : 'purple', 'click' : 'cyan', } class Peg: def __init__(self, x, y, window): self.circle = Circle(Point(x, y), PEG_RADIUS) self.circle.setFill(PEG_COLOR['background']) self.circle.setOutline(PEG_COLOR['border']) self.window = window def draw(self): self.circle.draw(self.window) class Board: def __init__(self, size=6): # size is the number of pegs in each side of of the triangle self.window = GraphWin('Peg Solitarie', WINDOW_SIZE, WINDOW_SIZE) self.pegs = self.make_pegs() def draw(self): for peg in self.pegs: peg.draw() def make_pegs(self): """ Return a list of the pegs """ pegs = [] for (x, y) in self.peg_positions(): pegs.append(Peg(x, y, self.window)) return pegs def peg_positions(self): """ Return a list of (x,y) peg coordinates at the triangle coords """ # The approach here is # (1) put one peg in the top row (row=0), x at center, y down by border # (2) for remaining row=1 to (N_PEGS-1), # put 0.. pegs a bit below and to left of last ones # put one more at the end that row # i.e. if the previous row has three pegs * * * # then the next row has four 2 1 0 * positions = [ (WINDOW_SIZE//2, WINDOW_BORDER + PEG_RADIUS) ] # top peg for row in range(1, N_PEGS): (x_old, y_old) = positions[-1] # (x,y) for last peg in prev row x_new = x_old - PEG_X_APART // 2 y_new = y_old + PEG_Y_APART for column in range(row): positions.append( (x_new - column * PEG_X_APART, y_new) ) positions.append( (x_new + PEG_X_APART, y_new) ) return positions def play(self): self.draw() wait = input('OK? ') class User: pass def main(): Board().play() if __name__ == '__main__': import doctest doctest.testmod() main()