class Window(wx.Window): def __init__(self, parent): wx.Window.__init__(self, parent) self.colors = { 0: (204, 192, 179), 2: (238, 228, 218), 4: (237, 224, 200), 8: (242, 177, 121), 16: (245, 149, 99), 32: (246, 124, 95), 64: (246, 94, 59), 128: (237, 207, 114), 256: (237, 207, 114), 512: (237, 207, 114), 1024: (237, 207, 114), 2048: (237, 207, 114), 4096: (237, 207, 114), 8192: (237, 207, 114), 16384: (237, 207, 114), 32768: (237, 207, 114), 65536: (237, 207, 114), 131072: (237, 207, 114), 262144: (237, 207, 114), 524288: (237, 207, 114), 1048576: (237, 207, 114), 2097152: (237, 207, 114), 4194304: (237, 207, 114), 8388608: (237, 207, 114), 16777216: (237, 207, 114), 33554432: (237, 207, 114), 67108864: (237, 207, 114), 134217728: (237, 207, 114), 268435456: (237, 207, 114), 536870912: (237, 207, 114), 1073741824: (237, 207, 114), 2147483648: (237, 207, 114), 4294967296: (237, 207, 114), 8589934592: (237, 207, 114), 17179869184: (237, 207, 114), 34359738368: (237, 207, 114), 68719476736: (237, 207, 114), 137438953472: (237, 207, 114), 274877906944: (237, 207, 114), 549755813888: (237, 207, 114), 1099511627776: (237, 207, 114), 2199023255552: (237, 207, 114), 4398046511104: (237, 207, 114), 8796093022208: (237, 207, 114), 17592186044416: (237, 207, 114), 35184372088832: (237, 207, 114), 70368744177664: (237, 207, 114), 140737488355328: (237, 207, 114), 281474976710656: (237, 207, 114), 562949953421312: (237, 207, 114), 1125899906842624: (237, 207, 114), 2251799813685248: (237, 207, 114), 4503599627370496: (237, 207, 114), 9007199254740992: (237, 207, 114), 18014398509481984: (237, 207, 114), 36028797018963968: (237, 207, 114), 72057594037927936: (237, 207, 114) } self.initGame() self.initBuffer() self.Bind(wx.EVT_SIZE, self.onSize) # use wx.BufferedPaintDC self.Bind(wx.EVT_PAINT, self.onPaint) self.Bind(wx.EVT_KEY_DOWN, self.onKeyDown) def loadScore(self): if os.path.exists("bestscore.ini"): ff = open("bestscore.ini") self.bstScore = eval(ff.read()) ff.close() def saveScore(self): ff = open("bestscore.ini", "w") ff.write(str(self.bstScore)) ff.close() def initGame(self): self.bgFont = wx.Font(50, wx.SWISS, wx.NORMAL, wx.BOLD, face=u"Roboto") self.scFont = wx.Font(36, wx.SWISS, wx.NORMAL, wx.BOLD, face=u"Roboto") self.smFont = wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, face=u"Roboto") self.curScore = 0 self.bstScore = 0 self.loadScore() self.data = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] count = 0 while count < 2: row = random.randint(0, len(self.data) - 1) col = random.randint(0, len(self.data[0]) - 1) if self.data[row][col] != 0: continue if random.randint(0, 1): self.data[row][col] = 2 else: self.data[row][col] = 4 count += 1 self.mm = CDLL("mm.dll") def initBuffer(self): w, h = self.GetClientSize() self.buffer = wx.EmptyBitmap(w, h) def onSize(self, event): self.initBuffer() self.drawAll() def onPaint(self, event): dc = wx.BufferedPaintDC(self, self.buffer) def putTile(self): available = [] for row in range(len(self.data)): for col in range(len(self.data[0])): if self.data[row][col] == 0: available.append((row, col)) if available: row, col = available[random.randint(0, len(available) - 1)] if random.randint(0, 1): self.data[row][col] = 2 else: self.data[row][col] = 4 return True return False def slideUpDown(self, up): score = 0 numCols = len(self.data[0]) numRows = len(self.data) oldData = [[0 for i in range(numCols)] for j in range(numRows)] for row in range(numRows): for col in range(numCols): oldData[row][col] = self.data[row][col] for col in range(numCols): cvl = [] for row in range(numRows): value = self.data[row][col] if value != 0: cvl.append(value) if len(cvl) >= 2: flags = [True] * len(cvl) #reserve flags i = 1 while i < len(cvl): if cvl[i - 1] == cvl[i]: flags[i - 1] = False cvl[i] *= 2 score += cvl[i] i += 1 i += 1 temp = [] for i in range(len(cvl)): if flags[i]: temp.append(cvl[i]) cvl = temp for i in range(numRows - len(cvl)): if up: cvl.append(0) else: cvl.insert(0, 0) for row in range(numRows): self.data[row][col] = cvl[row] return oldData != self.data, score def slideLeftRight(self, left): score = 0 numRows = len(self.data) numCols = len(self.data[0]) oldData = [[0 for i in range(numCols)] for j in range(numRows)] for row in range(numRows): for col in range(numCols): oldData[row][col] = self.data[row][col] for row in range(numRows): rvl = [] for col in range(numCols): value = self.data[row][col] if value != 0: rvl.append(value) if len(rvl) >= 2: flags = [True] * len(rvl) #reserve flags i = 1 while i < len(rvl): if rvl[i - 1] == rvl[i]: flags[i - 1] = False rvl[i] *= 2 score += rvl[i] i += 1 i += 1 temp = [] for i in range(len(rvl)): if flags[i]: temp.append(rvl[i]) rvl = temp for i in range(numCols - len(rvl)): if left: rvl.append(0) else: rvl.insert(0, 0) for col in range(numCols): self.data[row][col] = rvl[col] return oldData != self.data, score def isGameOver(self): numRows = len(self.data) numCols = len(self.data[0]) copyData = [[0 for i in range(numCols)] for j in range(numRows)] #[[0]*numCols]*numRows X error for row in range(numRows): for col in range(numCols): copyData[row][col] = self.data[row][col] flag = False if not self.slideUpDown(True)[0] and not self.slideUpDown( False)[0] and not self.slideLeftRight( True)[0] and not self.slideLeftRight(False)[0]: flag = True if not flag: self.data = copyData return flag def doMove(self, move, score): if move: self.mm.AsyncPlaySoundW(u"musics\\move.wav") self.putTile() self.drawChange(score) if score: self.mm.AsyncPlaySoundW(u"musics\\merge.wav") if self.isGameOver(): self.mm.AsyncPlaySoundW(u"musics\\over.wav") if wx.MessageBox("游戏结束,是否重新开始?", "哈哈", wx.YES_NO | wx.ICON_INFORMATION) == wx.YES: bstScore = self.bstScore self.initGame() self.bstScore = bstScore self.drawAll() def onKeyDown(self, event): keyCode = event.GetKeyCode() if keyCode == wx.WXK_UP: self.doMove(*self.slideUpDown(True)) elif keyCode == wx.WXK_DOWN: self.doMove(*self.slideUpDown(False)) elif keyCode == wx.WXK_LEFT: self.doMove(*self.slideLeftRight(True)) elif keyCode == wx.WXK_RIGHT: self.doMove(*self.slideLeftRight(False)) def drawBg(self, dc): dc.SetBackground(wx.Brush((250, 248, 239))) dc.Clear() dc.SetBrush(wx.Brush((187, 173, 160))) dc.SetPen(wx.Pen((187, 173, 160))) dc.DrawRoundedRectangle(15, 150, 475, 475, 5) def drawLogo(self, dc): dc.SetFont(self.bgFont) dc.SetTextForeground((119, 110, 101)) dc.DrawText(u"2048", 15, 26) def drawLabel(self, dc): dc.SetFont(self.smFont) dc.SetTextForeground((119, 110, 101)) dc.DrawText(u"Join the numbers and get to the 2048 tile!", 15, 114) dc.DrawText( u"HOW TO PLAY: Use your arrow keys to move the tiles. When two\ntiles with the same number touch, they merge into one!", 15, 639) def drawScore(self, dc): dc.SetFont(self.smFont) scoreLabelSize = dc.GetTextExtent(u"SCORE") bestLabelSize = dc.GetTextExtent(u"BEST") curScoreBoardMinW = 15 * 2 + scoreLabelSize[0] bstScoreBoardMinW = 15 * 2 + bestLabelSize[0] curScoreSize = dc.GetTextExtent(str(self.curScore)) bstScoreSize = dc.GetTextExtent(str(self.bstScore)) curScoreBoardNedW = 10 + curScoreSize[0] bstScoreBoardNedW = 10 + bstScoreSize[0] curScoreBoardW = max(curScoreBoardMinW, curScoreBoardNedW) bstScoreBoardW = max(bstScoreBoardMinW, bstScoreBoardNedW) dc.SetBrush(wx.Brush((187, 173, 160))) dc.SetPen(wx.Pen((187, 173, 160))) dc.DrawRoundedRectangle(505 - 15 - bstScoreBoardW, 40, bstScoreBoardW, 50, 3) dc.DrawRoundedRectangle(505 - 15 - bstScoreBoardW - 5 - curScoreBoardW, 40, curScoreBoardW, 50, 3) dc.SetTextForeground((238, 228, 218)) dc.DrawText( u"BEST", 505 - 15 - bstScoreBoardW + (bstScoreBoardW - bestLabelSize[0]) / 2, 48) dc.DrawText( u"SCORE", 505 - 15 - bstScoreBoardW - 5 - curScoreBoardW + (curScoreBoardW - scoreLabelSize[0]) / 2, 48) dc.SetTextForeground((255, 255, 255)) dc.DrawText( str(self.bstScore), 505 - 15 - bstScoreBoardW + (bstScoreBoardW - bstScoreSize[0]) / 2, 68) dc.DrawText( str(self.curScore), 505 - 15 - bstScoreBoardW - 5 - curScoreBoardW + (curScoreBoardW - curScoreSize[0]) / 2, 68) def drawTiles(self, dc): dc.SetFont(self.scFont) for row in range(4): for col in range(4): value = self.data[row][col] color = self.colors[value] if value == 2 or value == 4: dc.SetTextForeground((119, 110, 101)) else: dc.SetTextForeground((255, 255, 255)) dc.SetBrush(wx.Brush(color)) dc.SetPen(wx.Pen(color)) dc.DrawRoundedRectangle(30 + col * 115, 165 + row * 115, 100, 100, 2) size = dc.GetTextExtent(str(value)) while size[0] > 100 - 15 * 2: self.scFont = wx.Font(self.scFont.GetPointSize() * 4 / 5, wx.SWISS, wx.NORMAL, wx.BOLD, face=u"Roboto") dc.SetFont(self.scFont) size = dc.GetTextExtent(str(value)) if value != 0: dc.DrawText(str(value), 30 + col * 115 + (100 - size[0]) / 2, 165 + row * 115 + (100 - size[1]) / 2) def drawAll(self): dc = wx.BufferedDC(wx.ClientDC(self), self.buffer) self.drawBg(dc) self.drawLogo(dc) self.drawLabel(dc) self.drawScore(dc) self.drawTiles(dc) def drawChange(self, score): dc = wx.BufferedDC(wx.ClientDC(self), self.buffer) if score: self.curScore += score if self.curScore > self.bstScore: self.bstScore = self.curScore self.drawScore(dc) self.drawTiles(dc) def __del__(self): pass
class Example(wx.Frame): def __init__(self, *args, **kwargs): wx.Frame.__init__(self, None, -1, style=wx.DEFAULT_FRAME_STYLE ^ wx.MAXIMIZE_BOX ^ wx.RESIZE_BORDER) self.InitUI() def InitUI(self): try: self.CreateMenuBar() self.CreateMain() self.CreateStatus() self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) self.Bind(wx.EVT_CLOSE, self.OnClose) self.SetBackgroundColour('#BBADA0') self.SetSize((480, 550)) self.SetTitle('2048') self.setIcon() self.Center() self.Show() except Exception as e: with open('error.log', 'w') as f: f.write(repr(e)) def CreateMenuBar(self): self.mb = wx.MenuBar() self.GameMenu = wx.Menu() self.GameMenu.Append(ID_MENU_NEW, u'新游戏(N)\t\tF2') self.GameMenu.AppendSeparator() self.GameMenu.Append(ID_MENU_UP, u'上一步(U)\tF3') self.GameMenu.Append(ID_MENU_DOWN, u'下一步(D)\tF4') self.GameMenu.AppendSeparator() self.GameMenu.Append(ID_MENU_EXIT, u'退出(X)') self.HelpMenu = wx.Menu() self.HelpMenu.Append(ID_MENU_ABOUT, u'关于2048(V)\tF1') self.mb.Append(self.GameMenu, u'&游戏(G)') self.mb.Append(self.HelpMenu, u'&帮助(H)') self.SetMenuBar(self.mb) self.Bind(wx.EVT_PAINT, self.OnPaint) self.Bind(wx.EVT_MENU, self.OnNew, id=ID_MENU_NEW) self.Bind(wx.EVT_MENU, self.OnUp, id=ID_MENU_UP) self.Bind(wx.EVT_MENU, self.OnDown, id=ID_MENU_DOWN) self.Bind(wx.EVT_MENU, self.OnExit, id=ID_MENU_EXIT) self.Bind(wx.EVT_MENU, self.OnAbout, id=ID_MENU_ABOUT) def insert(self, data): getZeroIndex = [] for i in range(4): for j in range(4): if data[i][j] == 0: getZeroIndex.append([i, j]) if getZeroIndex != []: randomZeroIndex = random.choice(getZeroIndex) data[randomZeroIndex[0]][randomZeroIndex[1]] = random.choice( [2, 4]) return data def CreateMain(self): self.data_left = [] self.data_right = [] self.show_time = [u"时间: ", "0"] self.show_list = [u"得分: ", "0", u"步数: ", "0"] self.colors = { 0: '#CCC0B4', 2: '#EEE4DA', 4: '#EDE0C8', 8: '#F2B179', 16: '#EC8D54', 32: '#F67C5F', 64: '#EA5937', 128: '#804000', 256: '#F1D04B', 512: '#E4C02A', 1024: '#EE7600', 2048: '#D5A500', 4096: '#E4C02A', 8192: '#804000', 16384: '#EA5937', 32768: '#EE7600' } self.scFont = wx.Font(36, wx.SWISS, wx.NORMAL, wx.BOLD, faceName=u"Roboto") self.data = [[0 for i in range(4)] for i in range(4)] self.data = self.insert(self.data) self.data = self.insert(self.data) self.mm = CDLL("mm.dll") def OnPaint(self, event): self.ShowWindow() def ShowWindow(self): dc = wx.ClientDC(self) dc.SetFont(self.scFont) for row in range(4): for col in range(4): value = self.data[row][col] color = self.colors[value] if value == 2 or value == 4: dc.SetTextForeground('#776e65') else: dc.SetTextForeground('#FFFFFF') dc.SetBrush(wx.Brush(color)) dc.SetPen(wx.Pen(color)) dc.DrawRoundedRectangle(15 + col * 115, 15 + row * 115, 100, 100, 2) size = dc.GetTextExtent(str(value)) while size[0] > 75: self.scFont = wx.Font(self.scFont.GetPointSize() * 9 / 10, wx.SWISS, wx.NORMAL, wx.BOLD, faceName=u"Roboto") dc.SetFont(self.scFont) size = dc.GetTextExtent(str(value)) if value != 0: dc.DrawText(str(value), 15 + col * 115 + (100 - size[0]) / 2, 15 + row * 115 + (100 - size[1]) / 2) self.ShowStatus(self.status) def CreateStatus(self): self.status = self.CreateStatusBar() self.status.SetFieldsCount(4) self.ShowStatus(self.status) def ShowStatus(self, status): self.status = status self.status.SetStatusText(self.show_time[0] + str(self.show_time[1]), 1) self.status.SetStatusText(self.show_list[0] + str(self.show_list[1]), 2) self.status.SetStatusText(self.show_list[2] + str(self.show_list[3]), 3) def ShowTime(self): global start_time global time_flag if time_flag: start_time = datetime.datetime.now() time_flag = False end_time = datetime.datetime.now() run_time = (end_time - start_time) self.show_time[1] = str(run_time.seconds) wx.CallLater(1000, self.ShowTime) self.ShowStatus(self.status) def OnKeyDown(self, event): self.ShowTime() if self.Over(self.data): self.mm.AsyncPlaySoundW(u"musics/over.wav") message = u" 不好意思,游戏结束。下次走运! \n\n 游戏时间:%s秒 游戏得分:%s分" % ( self.show_time[1], self.show_list[1]) dial = wx.MessageBox(message, u'游戏失败', wx.YES_NO | wx.NO_DEFAULT, self) if dial == wx.YES: self.Destroy() else: self.NewGame() keyCode = event.GetKeyCode() if keyCode == wx.WXK_UP: self.data = self.Move_Up(self.data) self.Move_Key(self.data) elif keyCode == wx.WXK_DOWN: self.data = self.Move_Down(self.data) self.Move_Key(self.data) elif keyCode == wx.WXK_LEFT: self.data = self.Move_Left(self.data) self.Move_Key(self.data) elif keyCode == wx.WXK_RIGHT: self.data = self.Move_Right(self.data) self.Move_Key(self.data) else: self.GameKey(keyCode, event) def GameKey(Code, event): if Code == wx.WXK_F1: self.OnAbout(event) elif Code == wx.WXK_F2: self.OnNew(event) elif Code == wx.WXK_F3: self.OnUp(event) elif Code == wx.WXK_F4: self.OnDown(event) def Move_Key(self, data): global Gamemusic self.mm.AsyncPlaySoundW(u"musics\\move.wav") if Gamemusic: self.mm.AsyncPlaySoundW(u"musics\\merge.wav") Gamemusic = 0 self.data = data Number = 1 + int(self.show_list[3]) self.show_list[3] = str(Number) self.data = self.insert(self.data) data_list = [] self.data_left.append(list([self.data, self.show_list])) del self.data_right[0:] self.ShowWindow() if play_flag: self.GameWin() def Over(self, matrix): for item_list in matrix: if 0 in item_list: return False for i in range(4): for j in range(4): if i < 4 - 1: if matrix[i][j] == matrix[i + 1][j]: return False if j < 4 - 1: if matrix[i][j] == matrix[i][j + 1]: return False return True def GameAppend(self, Name, Data, Show_list): data_list = [] if Name == 1: data_list.append(list([Data, Show_list])) return data_list elif Name == 2: data_list.append(list([Data, Show_list])) return data_list def Move_Right(self, matrix): right_list = [] for item_list in matrix: right_list.append(self.handle_list_item_right(item_list)) return right_list def Move_Left(self, matrix): right_list = [] for item_list in matrix: right_list.append(self.handle_list_item_left(item_list)) return right_list def Move_Down(self, matrix): down_list = [] config_list = [0, 0, 1, matrix] matrix = self.inversion_data_list(config_list) for item_list in matrix: down_list.append(self.handle_list_item_right(item_list)) config_list = [0, 0, 1, down_list] down_list = self.inversion_data_list(config_list) return down_list def Move_Up(self, matrix): up_list = [] config_list = [0, 0, 1, matrix] matrix = self.inversion_data_list(config_list) for item_list in matrix: up_list.append(self.handle_list_item_left(item_list)) config_list = [0, 0, 1, up_list] up_list = self.inversion_data_list(config_list) return up_list def handle_list_item_right(self, my_list): list_0 = self.del_item_0(my_list) list_0 = self.add_same_number(list_0, 'right') list_1 = self.del_item_0(list_0) list_1 = self.add_item_0(list_1, 'right') return list_1 def handle_list_item_left(self, my_list): list_0 = self.del_item_0(my_list) list_0 = self.add_same_number(list_0, 'left') list_1 = self.del_item_0(list_0) list_1 = self.add_item_0(list_1, 'left') return list_1 def del_item_0(self, my_list): list_0 = [] for item in my_list: if item != 0: list_0.append(item) return list_0 def add_item_0(self, my_list, direction): for i in range(4 - len(my_list)): if direction == 'right': my_list.insert(0, 0) elif direction == 'left': my_list.append(0) return my_list def add_same_number(self, my_list, direction): global Gamemusic if direction == 'right': for i in range(len(my_list) - 1, -1, -1): if i >= 1: if my_list[i - 1] == my_list[i]: Gamemusic = 1 Number = my_list[i] + int(self.show_list[1]) self.show_list[1] = str(Number) my_list[i - 1] = 0 my_list[i] = 2 * my_list[i] i += 1 else: for i in range(len(my_list)): if i >= 1: if my_list[i - 1] == my_list[i]: Gamemusic = 1 Number = my_list[i] + int(self.show_list[1]) self.show_list[1] = str(Number) my_list[i] = 0 my_list[i - 1] = 2 * my_list[i - 1] i += 1 return my_list def inversion_data_list(self, config_list): data_list = config_list[3] if config_list[2] == 1: new_list = [] for i in range(len(data_list[0])): temp_list = [] for j in range(len(data_list)): temp_list.append(data_list[j][i]) new_list.append(temp_list) data_list = new_list if config_list[0] == 1: new_list = [] for temp_list in data_list: new_list.insert(0, temp_list) data_list = new_list if config_list[1] == 1: new_list = [] for temp_list in data_list: new_list.append(temp_list[::-1]) data_list = new_list return data_list def NewGame(self): global time_flag time_flag = True self.data = [[0 for i in range(4)] for i in range(4)] self.data = self.insert(self.data) self.data = self.insert(self.data) self.show_list[1] = '0' self.show_list[3] = '0' del self.data_left[0:] self.ShowWindow() def OnNew(self, e): self.NewGame() def OnUp(self, e): print len(self.data_left) if len(self.data_left) == 1 or len(self.data_left) == 0: dial = wx.MessageDialog(None, u"不能再退了!!", u'警告', wx.OK | wx.ICON_EXCLAMATION) dial.ShowModal() else: self.data_right.append([self.data, self.show_list]) self.data_left.pop() self.data = self.data_left[-1][0] self.show_list = self.data_left[-1][1] self.ShowWindow() def OnDown(self, e): if len(self.data_right) == 0: dial = wx.MessageDialog(None, u"不能再退了!!", u'警告', wx.OK | wx.ICON_EXCLAMATION) dial.ShowModal() else: self.data = self.data_right[-1][0] self.show_list = self.data_right[-1][1] self.data_right.pop() self.data_left.append([self.data, self.show_list]) self.ShowWindow() def OnExit(self, e): self.Close() def OnClose(self, e): dial = wx.MessageDialog( None, u'您确定要退出游戏吗?', u'退出游戏', wx.YES_NO | wx.NO_DEFAULT | wx.ICON_EXCLAMATION) ret = dial.ShowModal() if ret == wx.ID_YES: self.Destroy() else: e.Veto() def setIcon(self): icon = wx.Icon("images/icon.ico", wx.BITMAP_TYPE_ICO) self.SetIcon(icon) def GameWin(self): global play_flag for item_list in self.data: if 2048 in item_list: dial = wx.MessageDialog( None, u'您赢了!\n您想继续玩吗?', u'游戏结束', wx.YES_NO | wx.NO_DEFAULT | wx.ICON_EXCLAMATION) ret = dial.ShowModal() if ret == wx.ID_YES: play_flag = False return else: self.Destroy() def OnAbout(self, event): a = MyDialog(self).Show()