= How to create a game for wxPython - Part 3 (Phoenix) = '''Keywords :''' Minesweeper, Pentomino, Sudoku. <<TableOfContents>> -------- = Demonstrating : = __'''''Tested''' py3.x, wx4.x and Win10.''__ __'' ''__ Are you ready to use some samples ? ;) Test, modify, correct, complete, improve and share your discoveries ! (!) -------- == Minesweeper == {{attachment:img_minesweeper.png}} {{{#!python # minesweeper.py """ Author : ??? Website : https://www.programmersought.com/article/50683537740/ """ import wx from random import randint # class MyFrame #--------------------------------------------------------------------------- class MyFrame(wx.Frame): def __init__(self): # Set the window to a fixed size. wx.Frame.__init__(self, None, -1, 'Minesweeper', size=(515, 503), style=wx.SYSTEM_MENU | wx.MINIMIZE_BOX | wx.CLOSE_BOX | wx.CAPTION) self.time_count = 0 # Initialize the timing to 0. self.mine_last = 100 # Initialize the number of mines to 100. self.get_mine_set() # Get Ray's index collection. self.get_info_set() # Get prompt information (index and mine number) collection. self.del_index_set = set() # Store the deleted button index. self.get_bmp_list() # Get bitmap object list. self.SetIcon(wx.Icon(self.bmp_list[9])) # Set title icon. self.create_menu() # Generate menu bar. self.create_panel() # Generate artboard. self.create_timer() # Generate timer. self.create_text_info() # Generate prompt information (thunder and time). self.create_state_btn() # Generate status button. self.create_btn_list() # Generate all buttons. #----------------------------------------------------------------------- # Menu bar events. def e_menu_new(self, event): pass def e_menu_level1(self, event): pass def e_menu_level2(self, event): pass def e_menu_level3(self, event): pass def e_menu_custom(self, event): pass def e_menu_mark(self, event): pass def e_menu_color(self, event): pass def e_menu_sound(self, event): pass def e_menu_list(self, event): pass def e_menu_exit(self, event): self.Destroy() def e_menu_catalogue(self, event): pass def e_menu_search(self, event): pass def e_menu_help(self, event): pass def e_menu_about(self, event): dlg = wx.MessageDialog(self, "This is a small game.\n", "About Minesweeper", wx.OK | wx.CENTRE | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() def create_menu(self): menu_bar = wx.MenuBar() # Create menu bar. # Game menu. gm_menu = wx.Menu() # Create a menu object. new = gm_menu.Append(-1,"Start (N) \ tF2") # Add submenu to menu object. gm_menu.AppendSeparator() # Insert a dividing line. level1 = gm_menu.Append(-1,"Elementary (B)") level2 = gm_menu.Append(-1,"Intermediate (I)") level3 = gm_menu.Append(-1,"Advanced (E)") custom = gm_menu.Append(-1, "Custom (C) ...") gm_menu.AppendSeparator() # Insert a dividing line. mark = gm_menu.Append(-1,"Mark (?) (M)") color = gm_menu.Append(-1,"Color (L)") sound = gm_menu.Append(-1,"Sound (S)") gm_menu.AppendSeparator() rs_list = gm_menu.Append(-1, "League of Minesweeper (T) ...") exit_gm = gm_menu.Append(-1, "Exit (X)") menu_bar.Append(gm_menu,"& Game") # Add the File menu to the menu bar. # Help menu. self.help_menu = wx.Menu() catalogue = self.help_menu.Append(2,"Directory (C) \ tF1") self.help_menu.AppendSeparator() search_help = self.help_menu.Append(3,"Find Help Topic (S) ...") use_help = self.help_menu.Append(4,"Use Help (H)") self.help_menu.AppendSeparator() about = self.help_menu.Append(9,"About mine clearance (A) ...") menu_bar.Append(self.help_menu,"& Help (H)") # Setup menu bar. self.SetMenuBar(menu_bar) # Bind menu events. self.Bind(wx.EVT_MENU, self.e_menu_new, new) self.Bind(wx.EVT_MENU, self.e_menu_level1, level1) self.Bind(wx.EVT_MENU, self.e_menu_level2, level2) self.Bind(wx.EVT_MENU, self.e_menu_level3, level3) self.Bind(wx.EVT_MENU, self.e_menu_custom, custom) self.Bind(wx.EVT_MENU, self.e_menu_mark, mark) self.Bind(wx.EVT_MENU, self.e_menu_color, color) self.Bind(wx.EVT_MENU, self.e_menu_sound, sound) self.Bind(wx.EVT_MENU, self.e_menu_list, rs_list) self.Bind(wx.EVT_MENU, self.e_menu_exit, exit_gm) self.Bind(wx.EVT_MENU, self.e_menu_catalogue, catalogue) self.Bind(wx.EVT_MENU, self.e_menu_search, search_help) self.Bind(wx.EVT_MENU, self.e_menu_help, use_help) self.Bind(wx.EVT_MENU, self.e_menu_about, about) def create_panel(self): self.panel = wx.Panel(self) self.panel.Bind(wx.EVT_PAINT, self.e_paint) def get_mine_set(self): self.mine_set = set() while(len(self.mine_set)<100): self.mine_set.add(randint(0, 719)) def get_info_set(self): self.info_set = set() info_set = set() for i in self.mine_set: info_set.update({i-31, i-30, i-29, i-1, i+1, i+29, i+30, i+31}) for i in info_set: if i not in self.mine_set and i in range(0,720): count = 0 for j in [i-31, i-30, i-29, i-1, i+1, i+29, i+30, i+31]: if j in self.mine_set: count += 1 self.info_set.add((i,count)) def get_bmp_list(self): image_list = ['smile.png', 'oh.png', 'cry.png', 'com.png', 'flag.png', 'ques.png', 'mine.png', 'emine.png', 'redmine.png','icon.png'] self.bmp_list = [wx.Image(i, wx.BITMAP_TYPE_PNG).ConvertToBitmap() for i in image_list] def create_state_btn(self): self.state_btn = wx.BitmapButton(self.panel, -1, self.bmp_list[0], (240, 10), (25, 25)) self.state_btn.Bind(wx.EVT_BUTTON, self.e_restart) def create_text_info(self): self.mine_text = wx.StaticText(self.panel, -1, '100', (25, 10)) self.mine_text.SetFont(wx.Font(20, wx.DEFAULT, wx.FONTSTYLE_NORMAL, wx.NORMAL, faceName="Bold Body")) self.mine_text.SetForegroundColour(wx.RED) self.time_text = wx.StaticText(self.panel, -1, '000', (440, 10)) self.time_text.SetFont(wx.Font(20, wx.DEFAULT, wx.FONTSTYLE_NORMAL, wx.NORMAL, faceName="Bold Body")) self.time_text.SetForegroundColour(wx.RED) def create_timer(self): self.timer = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.e_time, self.timer) def draw_panel(self): self.dc = wx.ClientDC(self.panel) self.dc.SetBrush(wx.Brush(wx.Colour(192, 192, 192))) # Set fill color. self.dc.SetPen(wx.GREY_PEN) # Set line color. self.dc.DrawRectangle(9, 50, 480, 384) # Draw a frame. for i in range(1, 24): self.dc.DrawLine(9, 16 * i + 50, 480 + 9, 16 * i + 50) # Draw horizontal lines. for i in range(1, 30): self.dc.DrawLine(16 * i + 9, 50, 16 * i + 9, 384 + 50) # Draw a vertical line. for i in self.mine_set: self.dc.DrawBitmap(self.bmp_list[6],i % 30 * 16 + 10, i // 30 * 16 + 1 + 50) # Paint mine. text_color_dict = {1: '#0000ff', 2: '#008000', 3: '#ff0000', 4: '#000080', 5: '#800000', 6: '#e4007f', 7: '#6a3906', 8: '#000000'} # Quantity and color dictionary. for i in self.info_set: self.dc.SetTextForeground(text_color_dict[i[1]]) # Find the corresponding color. self.dc.DrawText(str(i[1]), i[0] % 30 * 16 + 5 + 9, i[0] // 30 * 16 + 1 + 50) # Show thunder. def create_btn_list(self): self.btn_list = [] index = 0 for i in range(0, 24): for j in range(0, 30): btn = wx.BitmapButton(self.panel,-1,self.bmp_list[3],(j * 16+9, i * 16+50),(17, 17)) btn.index = index btn.state = 0 self.btn_list.append(btn) index += 1 for i in self.btn_list: i.Bind(wx.EVT_LEFT_DOWN,self.e_left_down) i.Bind(wx.EVT_LEFT_UP,self.e_left_up) i.Bind(wx.EVT_RIGHT_DOWN,self.e_right_down) def stop_game(self,index): self.state_btn.SetBitmap(self.bmp_list[2]) self.timer.Stop() error_marked_set = set() for i, j in enumerate(self.btn_list): if i not in self.del_index_set: if i in self.mine_set: if j.state != 1: j.Destroy() self.del_index_set.add(i) else: if j.state == 1: j.Destroy() self.del_index_set.add(i) error_marked_set.add(i) if i not in self.del_index_set: j.Unbind(wx.EVT_LEFT_UP, handler=self.e_left_up) # The remaining buttons unbind all events. j.Unbind(wx.EVT_LEFT_DOWN, handler=self.e_left_down) j.Unbind(wx.EVT_RIGHT_DOWN, handler=self.e_right_down) self.panel.Unbind(wx.EVT_PAINT, handler=self.e_paint) # Unbind drawing events. self.draw_panel() # Regenerate the panel. self.dc.DrawBitmap(self.bmp_list[8],index % 30 * 16 + 10, index // 30 * 16 + 1 + 50) # Draw red fried mine. self.dc.SetBrush(wx.TRANSPARENT_BRUSH) self.dc.DrawRectangle(index % 30 * 16 + 9, index // 30 * 16 + 50, 16, 16) for i in error_marked_set: self.dc.DrawBitmap(self.bmp_list[7], i % 30 * 16 + 10, i // 30 * 16 + 1 + 50) # Paint mine. def del_btn(self,btn,index): self.state_btn.SetBitmap(self.bmp_list[0]) if index not in self.del_index_set and btn.state != 1: if index in [i[0] for i in self.info_set]: btn.Destroy() self.del_index_set.add(index) else: if index not in self.mine_set: btn.Destroy() self.del_index_set.add(index) for j in [index - 31, index - 30, index - 29, index - 1, index + 1, index + 29, index + 30, index + 31]: if j in range(0, 720) and j not in self.mine_set \ and j not in self.del_index_set \ and self.btn_list[j].state != 1: self.btn_list[j].Destroy() self.del_index_set.add(j) def e_paint(self, event): self.draw_panel() def e_time(self, event): self.time_count += 1 self.time_text.SetLabel('%03d'%self.time_count) def e_left_up(self, event): if not self.timer.IsRunning(): self.timer.Start(1000) btn = event.GetEventObject() index = btn.index if btn.state == 1: self.state_btn.SetBitmap(self.bmp_list[0]) else: if index in self.mine_set: self.stop_game(index) else: self.del_btn(btn,index) def e_left_down(self, event): self.state_btn.SetBitmap(self.bmp_list[1]) def e_right_down(self, event): btn = event.GetEventObject() index = btn.index label = btn.state if label == 0: btn.SetBitmap(self.bmp_list[4]) btn.state = 1 self.mine_last -= 1 self.mine_text.SetLabel('%03d' %self.mine_last) elif label == 1: btn.SetBitmap(self.bmp_list[5]) btn.state = 2 self.mine_last += 1 self.mine_text.SetLabel('%03d' % self.mine_last) else: btn.SetBitmap(self.bmp_list[3]) btn.state = 0 def e_restart(self, event): # End. if self.timer.IsRunning(): self.timer.Stop() # Clear timer. for i,j in enumerate(self.btn_list): if i not in self.del_index_set: j.Destroy() # Delete all buttons. # Restart. self.get_mine_set() self.get_info_set() self.panel.Bind(wx.EVT_PAINT, self.e_paint) self.time_count = 0 self.mine_last = 100 self.del_index_set = set() self.state_btn.SetBitmap(self.bmp_list[0]) self.mine_text.SetLabel('100') self.time_text.SetLabel('000') self.create_btn_list() #--------------------------------------------------------------------------- if __name__=='__main__': app = wx.App() frame = MyFrame() frame.Show() app.MainLoop() }}} -------- == Pentomino == {{attachment:img_pentomino.png}} {{{#!python # pentomino.py """ Pentomino puzzle solver Author : Jean-Claude Rimbault (pynokio.org, 2005) Modified for wx : 14-november-2011 by keiji imoto Website : https://www.nips.ac.jp/huinfo/documents/python/python_ex02.html Department of information physiology National institute for physiological sciences Okazaki, japan """ import wx # class MyPentomino # class MyFrame # class MyPanel #--------------------------------------------------------------------------- class MyPentomino(): def __init__(self, parent): self.parent = parent self.w = 10 self.h = 6 self.board = ['#'] * 160 for row in range(self.w): for col in range(self.h): self.board[row*10+col+11] = ' ' self.runmode = 0 self.n = 0 self.pieces = [ 'C', 'X', 'T', 'Y', 'F', 'W', 'P', 'I', 'S', 'L', 'V', 'N' ] self.shapes = { 'C': ((0, 1, 10, 20, 21), (0, 1, 11, 20, 21), (0, -10, -9, -8, 2), (0, 10, 11, 12, 2)), 'F': ((0, 1, -9, 2, 12), (0, 1, 11, 2, -8), (0, 10, 11, 21, 12), (0, -10, -9, -19, -8), (0, 1, 11, 21, 12), (0, 1, -9, -19, -8), (0, 1, 11, -9, 12), (0, 1, 11, -9, -8)), 'I': ((0, 1, 2, 3, 4), (0, 10, 20, 30, 40)), 'L': ((0, 1, 2, 3, 13), (0, 1, 2, 3, -7), (0, 10, 20, 30, 1), (0, -10, -20, -30, 1), (0, 1, 11, 21, 31), (0, 1, -9, -19, -29), (0, 10, 1, 2, 3), (0, -10, 1, 2, 3)), 'N': ((0, 1, 11, 12, 13), (0, 1, -9, -8, -7), (0, 1, 2, 12, 13), (0, 1, 2, -8, -7), (0, 10, 20, 21, 31), (0, 10, 20, 19, 29), (0, 10, 11, 21, 31), (0, 10, 9, 19, 29)), 'P': ((0, 1, 2, 11, 12), (0, 1, 2, -9, -8), (0, 1, 2, 10, 11), (0, 1, 2, -10, -9), (0, 1, 10, 11, 20), (0, 1, 10, 11, 21), (0, 1, -10, -9, -20), (0, 1, -10, -9, -19)), 'S': ((0, 1, 11, 21, 22), (0, 1, -9, -19, -18), (0, 10, 11, 12, 22), (0, -10, -9, -8, -18)), 'T': ((0, 1, 11, 21, 2), (0, 1, -9, -19, 2), (0, 1, 2, -8, 12), (0, 10, -10, 1, 2)), 'V': ((0, 1, 2, 12, 22), (0, 1, 2, -8, -18), (0, 1, 2, 10, 20), (0, 1, 2, -10, -20)), 'W': ((0, 1, 11, 12, 22), (0, 1, -9, -8, -18), (0, 10, 11, 21, 22), (0, -10, -9, -19, -18)), 'X': ((0, -9, 1, 11, 2),), 'Y': ((0, 1, 2, 3, 12), (0, 1, 2, 3, -8), (0, 10, 20, 30, 11), (0, -10, -20, -30, -9), (0, 1, 11, 21, -9), (0, 1, -9, -19, 11), (0, 11, 1, 2, 3), (0, -9, 1, 2, 3)) } #----------------------------------------------------------------------- def display(self): self.parent.statusbar.SetStatusText('n = ' + str(self.n)) self.panel.Refresh() self.panel.Update() # # main loop # def solve(self): for q in range(len(self.board)): try: if self.board[q] == ' ': for p in self.pieces: for s in self.shapes[p]: for c in s: for d in s: if self.board[q+d-c] != ' ': break else: for d in s: self.board[q+d-c] = p i = self.pieces.index(p) self.pieces.remove(p) if not self.pieces: self.n += 1 self.display() else: if self.runmode: self.display() self.solve() self.pieces.insert(i, p) for d in s: self.board[q+d-c] = ' ' return except(KeyboardInterrupt, SystemExit): raise def start(self, event): self.solve() #--------------------------------------------------------------------------- class MyFrame(wx.Frame): def __init__(self, parent, id, title, ww, wh): wx.Frame.__init__(self, parent, id, title, size=(ww, wh), style=wx.SYSTEM_MENU | wx.MINIMIZE_BOX | wx.CLOSE_BOX | wx.CAPTION) self.SetIcon(wx.Icon('./icons/wxwin.ico', wx.BITMAP_TYPE_ICO)) #------------ self.pen = MyPentomino(self) self.panel = MyPanel(self, self.pen) self.pen.panel = self.panel self.isRunning = False self.statusbar = self.CreateStatusBar() self.startButton = wx.Button(self.panel, wx.ID_ANY, '&Start', (140, 240)) self.Bind(wx.EVT_BUTTON, self.buttonControl) self.Centre() self.Show(True) #----------------------------------------------------------------------- def buttonControl(self, event): if self.isRunning == False: self.pen.start(event) isRunning = True #--------------------------------------------------------------------------- class MyPanel(wx.Panel): def __init__(self, parent, pen): wx.Panel.__init__(self, parent) self.pen = pen self.w = self.pen.w self.h = self.pen.h self.Bind(wx.EVT_PAINT, self.OnPaint) self.SetFocus() self.colors = { ' ': (0,0,0), 'X': (0xEF, 0x84, 0x5c), 'T': (0xF9, 0xC2, 0x70), 'C': (0xFF, 0xF6, 0x7F), 'W': (0xC1, 0xDB, 0x81), 'I': (0x69, 0xBD, 0x83), 'S': (0x61, 0xC1, 0xBE), 'F': (0x54, 0xC3, 0xF1), 'P': (0x6C, 0x9B, 0xD2), 'L': (0x79, 0x6B, 0xAF), 'V': (0xBA, 0x79, 0xB1), 'Y': (0xEE, 0x87, 0xB4), 'N': (0xEF, 0x85, 0x8C), } self.light = { ' ': (0,0,0), 'X': (0xF8, 0xC5, 0xAC), 'T': (0xFC, 0xE2, 0xBA), 'C': (0xFF, 0xFB, 0xC7), 'W': (0xE2, 0xEE, 0xC5), 'I': (0xBE, 0xDF, 0xC2), 'S': (0xBC, 0xE1, 0xDF), 'F': (0xBA, 0xE3, 0xF9), 'P': (0xBB, 0xCC, 0xE9), 'L': (0xBB, 0xB3, 0xD8), 'V': (0xDB, 0xBE, 0xDA), 'Y': (0xF7, 0xC9, 0xDD), 'N': (0xF7, 0xC7, 0xC6), } self.dark = { ' ': (0, 0, 0), 'X': (0xE6, 0x00, 0x12), 'T': (0xF3, 0x98, 0x00), 'C': (0xFF, 0xF1, 0x00), 'W': (0x8F, 0xC3, 0x1F), 'I': (0x00, 0x99, 0x44), 'S': (0x00, 0x9E, 0x96), 'F': (0x00, 0xA0, 0xE9), 'P': (0x00, 0x68, 0xB7), 'L': (0x1D, 0x20, 0x88), 'V': (0x92, 0x07, 0x83), 'Y': (0xE4, 0x00, 0x7F), 'N': (0xE5, 0x00, 0x4F), } #----------------------------------------------------------------------- def OnPaint(self, event): dc = wx.PaintDC(self) for col in range(self.h): for row in range(self.w): x = 30*row + 20 y = 30*col + 40 c = self.pen.board[row*10+col+11] dc.SetBrush(wx.Brush(self.colors[c])) dc.DrawRectangle(x, y, 30, 30) dc.SetPen(wx.Pen(self.light[c])) dc.DrawLine(x, y + 29, x, y) dc.DrawLine(x, y, x + 29, y) dc.SetPen(wx.Pen(self.dark[c])) dc.DrawLine(x + 1, y + 29, x + 29, y + 29) dc.DrawLine(x + 29, y + 29, x + 29, y + 1) #--------------------------------------------------------------------------- def main(): app = wx.App() frame = MyFrame(None, -1, 'Pentomino puzzle solver', 355, 340) app.MainLoop() #--------------------------------------------------------------------------- if __name__ == '__main__': main() }}} -------- == Sudoku == {{attachment:img_sudoku.png}} Link : https://www.daniweb.com/programming/software-development/tutorials/520379/how-to-write-a-sudoku-gui-in-python-wxpython -------- = Download source = [[attachment:source.zip]] -------- = Additional Information = '''Link :''' https://wiki.python.org/moin/GameProgramming http://mientki.ruhosting.nl/data_www/pylab_works/pw_bricks_2d_scene.html - - - - - https://wiki.wxpython.org/TitleIndex https://docs.wxpython.org/ -------- = Thanks to = ??? (minesweeper.py coding), Jean-Claude Rimbault (pentomino.py coding), Reverend Jim & Daniweb (sudoku.py coding), the wxPython community... -------- = About this page = Date(d/m/y) Person (bot) Comments : 12/02/21 - Ecco (Created page for wxPython Phoenix). -------- = Comments = - blah, blah, blah...