首页 > 代码库 > 连点成图:享受创建图形的乐趣

连点成图:享受创建图形的乐趣

 

         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 wximport timefrom 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# utilsdef 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 allLinesdef 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 allLinesdef 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-1class 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.strategiesForlinkPointsclass 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)

 

连点成图:享受创建图形的乐趣