1. 使用 wxpython 做基本的 GUI ;
2. 使用 Python 实现策略模式;
3. 点阵图的算法,使用程序生成, 既有趣也很锻炼算法思维连带激发创造力哦。
改进点: 生成更复杂更美妙的图案; 拖拽功能创作和保存; 关卡设置。你也来试试吧! 如果有兴趣做成移动游戏, 那就更棒了!
源程序:
linkpointsUI.py
# -*- coding: utf8 -*- # ------------------------------------------------------------------------------- # Name: linkpointsUI.py # Purpose: a game which join points to a gragh and enjoy # # Author: qin.shuq # # Created: 11/29/2014 # Copyright: (c) qin.shuq 2014 # Licence: ONLY BE USED FOR STUDY #------------------------------------------------------------------------------- import wx import time from LinkPointStrategy import * class LinkPointsFrame(wx.Frame): ‘‘‘ generate dotSize * dotSize dotted graph and app ui ‘‘‘ def __init__(self, parent, title, dotSize=18, uiSize=(840,560)): wx.Frame.__init__(self, parent, title=title, size=uiSize) self.mainPanel = None self.dc = None self.dotSize = dotSize self.displayDemoTimer = None bottomSpace = 50 uiWidth = uiSize[0] panelHeight = uiSize[1] - bottomSpace self.origin = 10 self.pointRadius = 2 self.intervalBetweenPoints = (panelHeight-self.origin*2) / (self.dotSize-1) self.mainPanelSize = (panelHeight, panelHeight) self.ctrlPanelSize = (uiWidth - self.mainPanelSize[0], panelHeight) self.initUI() def initUI(self): ### UI Design follows top-down thinking and down-top building bigPanel = wx.Panel(self, name="WhileWindow") font = wx.Font(12, wx.ROMAN, wx.NORMAL, wx.NORMAL) hboxLayout = wx.BoxSizer(wx.HORIZONTAL) self.mainpanel = wx.Panel(bigPanel, name="mainPanel", size=self.mainPanelSize) self.mainpanel.SetBackgroundColour(‘#fffff0‘) ctrlPanel = wx.Panel(bigPanel, name="ctrlPanel", size=self.ctrlPanelSize) hboxLayout.Add(self.mainpanel, 0, wx.EXPAND|wx.ALL, 10) hboxLayout.Add(ctrlPanel, 0, wx.EXPAND|wx.ALL, 10) bigPanel.SetSizer(hboxLayout) topPanel = wx.Panel(ctrlPanel, name="topPanel") staticText = wx.StaticText(topPanel, label=decodeUTF8("How to Play: \n\nJust link points to build a graph, \nSo Easy And Enjoy Yourself !")) staticText.SetFont(font) btnBoxSizer = wx.BoxSizer(wx.VERTICAL) createNewBtn = wx.Button(ctrlPanel, name="CreateNew", label=decodeUTF8("创作")) saveBtn = wx.Button(ctrlPanel, name="SaveWork", label=decodeUTF8("保存")) seeDemoBtn = wx.Button(ctrlPanel, name="seeDemo", label=decodeUTF8("欣赏")) self.Bind(wx.EVT_BUTTON, self.createNewDottedGraph, createNewBtn) self.Bind(wx.EVT_BUTTON, self.createDemoGraph, seeDemoBtn) btnBoxSizer.Add(createNewBtn) btnBoxSizer.Add(saveBtn) btnBoxSizer.Add(seeDemoBtn) vboxLayout = wx.BoxSizer(wx.VERTICAL) vboxLayout.Add(topPanel, 1, wx.EXPAND|wx.ALL, 5) vboxLayout.Add(btnBoxSizer, 1, wx.EXPAND|wx.ALL, 5) ctrlPanel.SetSizer(vboxLayout) self.Show(True) # show demo self.createDemoGraph() def createNewDottedGraph(self, event=None): if self.displayDemoTimer: self.displayDemoTimer.Stop() if self.dc: self.dc.Clear() self.dc = wx.ClientDC(self.mainpanel) self.dc.SetPen(wx.Pen(‘GREEN‘)) self.dc.SetBrush(wx.Brush(‘GREEN‘)) for xcoord in range(self.origin, self.mainPanelSize[0] + self.intervalBetweenPoints, self.intervalBetweenPoints): for ycoord in range(self.origin, self.mainPanelSize[1] + self.intervalBetweenPoints, self.intervalBetweenPoints): self.dc.DrawPoint(xcoord, ycoord) self.dc.DrawCircle(xcoord,ycoord, self.pointRadius) def drawGraph(self, allLines): ‘‘‘ a line is a tuple of ((x1,y1), (x2, y2)) ‘‘‘ #print ‘***************************************‘ for line in allLines: #print line[0][0], ‘ ‘, line[0][1], ‘ ‘, line[1][0], ‘ ‘, line[1][1] x1 = self.obtainRealCoords(line[0][0]) y1 = self.obtainRealCoords(line[0][1]) x2 = self.obtainRealCoords(line[1][0]) y2 = self.obtainRealCoords(line[1][1]) self.dc.DrawLine(x1, y1, x2, y2) def createDemoGraph(self, event=None): self.createNewDottedGraph() linkpointsStrategy = LinkPointStrategy(self.dotSize) allLines = linkpointsStrategy.obtainAllLinesByLinkPoints() self.drawGraph(allLines) try: anoStrategy = LinkPointStrategy.getStrategy("anoStrategy") except Exception, args: print args def myStrategy(allPoints, size): return [(point, (point[0]+1, point[1]+1)) for point in allPoints if (point[0] == point[1] and point[0]<size-1)] LinkPointStrategy.registerStrategy("my", myStrategy) LinkPointStrategy.setStrategy("my") self.createNewDottedGraph() self.drawGraph(linkpointsStrategy.obtainAllLinesByLinkPoints()) def displayDemo(*args, **kwargs): allStrategies = linkpointsStrategy.getAllStrategies() for strategyName in allStrategies.keys(): self.createNewDottedGraph() linkpointsStrategy.setStrategy(strategyName) self.drawGraph(linkpointsStrategy.obtainAllLinesByLinkPoints()) time.sleep(2) self.displayDemoTimer = wx.Timer(self) self.Bind(wx.EVT_TIMER, displayDemo, self.displayDemoTimer) self.displayDemoTimer.Start(3000, oneShot=False) def obtainRealCoords(self, localCoord): ‘‘‘ 将逻辑坐标 (x,y) 转换为 实际坐标 (real_x, real_y). eg. 假设原点坐标是 (15,15), 点间隔为 (30, 30), 则 (1,1) -> (45,45) 这样在绘图时就可以专注于以逻辑坐标来思考,摒弃实际坐标的细节干扰 ‘‘‘ return self.origin+localCoord*self.intervalBetweenPoints # utils def decodeUTF8(msg): return msg.decode(‘utf8‘) def main(): app = wx.App(False) frame = LinkPointsFrame(None, decodeUTF8(‘连点成图: 享受创建图形的乐趣‘)) app.MainLoop() if __name__ == ‘__main__‘: main()
LinkPointStrategy.py
# -*- coding: utf8 -*- # ------------------------------------------------------------------------------- # Name: LinkPointStrategy.py # Purpose: varieties of algorithms for linking points # # Author: qin.shuq # # Created: 11/29/2014 # Copyright: (c) qin.shuq 2014 # Licence: ONLY BE USED FOR STUDY # ------------------------------------------------------------------------------- def simpleLoopStrategyOfLinkpoints(allPoints, size): pairs = [] for i in range(size): if i*2 <= size-1: pairs.append((i, size-1-i)) allLines = [] for pair in pairs: allLines.append( ((pair[0], pair[0]), (pair[0], pair[1])) ) allLines.append( ((pair[0], pair[0]), (pair[1], pair[0])) ) allLines.append( ((pair[0], pair[1]), (pair[1], pair[1])) ) allLines.append( ((pair[1], pair[0]), (pair[1], pair[1])) ) return allLines def loopStrategyOfLinkpoints(allPoints, size): pairs = [] for i in range(size): if i*2 <= size-1: pairs.append((i, size-1-i)) allLines = [] for pair in pairs: begin = (pair[0], pair[0]) end = (pair[1], pair[1]) for localXCoord in range(pair[0], pair[1], 1): allLines.append(((pair[0], localXCoord), (pair[0], localXCoord+1))) allLines.append(((pair[1], localXCoord), (pair[1], localXCoord+1))) for localYCoord in range(pair[0], pair[1], 1): allLines.append(((localYCoord, pair[0]), (localYCoord+1, pair[0]))) allLines.append(((localYCoord, pair[1]), (localYCoord+1, pair[1]))) return allLines def defaultStrategyOfLinkpoints(allPoints, size): return [( point, (point[0]+1, point[1]+1) ) for point in allPoints if not isRightOrButtomBoundPoint(point, size)] def isRightOrButtomBoundPoint(point, size): localXCoord = point[0] localYCoord = point[1] return localXCoord == size-1 or localYCoord == size-1 class StrategyManager(object): def __init__(self): self.strategiesForlinkPoints = { ‘default‘: defaultStrategyOfLinkpoints, ‘loop‘: loopStrategyOfLinkpoints, ‘simpleLoop‘: simpleLoopStrategyOfLinkpoints } self.DEFAULT_STRATEGY = self.strategiesForlinkPoints[‘default‘] self.CURR_STRATEGY = self.DEFAULT_STRATEGY def getStrategy(self, strategyName): strategyForLinkPoints = self.strategiesForlinkPoints.get(strategyName) if strategyForLinkPoints is None: raise Exception(‘No stragegy named "%s". You can write one. ‘ % strategyName) return strategyForLinkPoints def registerStrategy(self, strategyName, strategyForLinkPoints): oldStrategy = self.strategiesForlinkPoints.get(strategyName) if oldStrategy: self.strategiesForlinkPoints[‘old_‘ + strategyName] = oldStrategy self.strategiesForlinkPoints[strategyName] = strategyForLinkPoints def setCurrStrategy(self, strategyName): self.CURR_STRATEGY = self.getStrategy(strategyName) def getCurrStratety(self): return self.CURR_STRATEGY def getAllStrategies(self): return self.strategiesForlinkPoints class LinkPointStrategy(object): ‘‘‘ just think in a dotted graph of (0,0) - (dotSize-1, dotSize-1) with interval of points = 1 (0,0), (0,1), ... , (0, dotSize-1) (1,0), (1,1), ... , (1, dotSize-1) ... , ... , ... , ... (dotSize-1,0), (dotSize-1, 1), ..., (dotSize-1, dotSize-1) and output a set of [((x1,y1), (x2,y2)), ..., ((xm,ym), (xn,yn))] ‘‘‘ strategyManager = StrategyManager() def __init__(self, dotSize): self.dotSize = dotSize self.allPoints = [] for localXCoord in range(dotSize): for localYCoord in range(dotSize): self.allPoints.append((localXCoord, localYCoord)) @classmethod def setStrategy(cls, strategyName): cls.strategyManager.setCurrStrategy(strategyName) @classmethod def getStrategy(cls, strategyName): return cls.strategyManager.getStrategy(strategyName) @classmethod def registerStrategy(cls, strategyName, strategyFunc): cls.strategyManager.registerStrategy(strategyName, strategyFunc) @classmethod def getAllStrategies(cls): return cls.strategyManager.getAllStrategies() def obtainAllLinesByLinkPoints(self): ‘‘‘ generate all lines between points according to given strategy which is a algorithm of linking points line: a tuple of (x1, y1, x2, y2) note: (x1, y1, x2, y2) are local coordinates which will be converted into real coordinates upon drawing ‘‘‘ currStrategy = LinkPointStrategy.strategyManager.getCurrStratety() return currStrategy(self.allPoints, self.dotSize)
时间: 2024-10-06 09:36:26