Fifteen

Tags: pgzero, game

https://simplegametutorials.github.io/pygamezero/

fifteen.py
  1import pgzrun
  2import random
  3
  4# SETTINGS {{{
  5TILE_SIZE = 200
  6GAME_WIDTH = 4
  7GAME_HEIGHT = 4
  8TILE_GAP = 5
  9BORDER_SIZE = 20
 10WIDTH = GAME_WIDTH * TILE_SIZE + 2 * BORDER_SIZE + (GAME_WIDTH + 1) * TILE_GAP
 11HEIGHT = GAME_HEIGHT * TILE_SIZE + 2 * BORDER_SIZE + (GAME_HEIGHT + 1) * TILE_GAP
 12
 13# }}}
 14class Game(object): # {{{
 15    class Board(object): # {{{
 16        class Tile(object): # {{{
 17            def __init__(self, value): # {{{
 18                self.value = value + 1
 19            # }}}
 20            def draw(self, order): # {{{
 21                x = order % GAME_WIDTH
 22                y = order // GAME_WIDTH
 23                x = x * TILE_SIZE + BORDER_SIZE + TILE_GAP * (order % GAME_WIDTH) + TILE_GAP
 24                y = y * TILE_SIZE + BORDER_SIZE + TILE_GAP * (order // GAME_WIDTH) + TILE_GAP
 25
 26                screen.draw.filled_rect(Rect(x, y, TILE_SIZE, TILE_SIZE), color="#773300")
 27                screen.draw.text(
 28                        "%s" % (self.value), 
 29                        center=(x+TILE_SIZE/2, y+TILE_SIZE/2), 
 30                        color="#aa9900",
 31                        fontsize=0.8*TILE_SIZE,
 32                        owidth=0.4,
 33                        ocolor="#662200",
 34
 35                        )
 36            # }}}
 37        # }}}
 38        def __init__(self): # {{{
 39            self.border = BORDER_SIZE
 40            self.tiles = [self.Tile(i) for i in range(GAME_WIDTH * GAME_HEIGHT - 1)]
 41            self.start = [tile.value for tile in self.tiles]
 42            self.tiles.append(None)
 43            self.start.append(None)
 44        # }}}
 45        def draw(self): # {{{
 46            border_colour = "#880000"
 47            if self.is_ordered():
 48                border_colour = "#662200"
 49            screen.fill((0, 0, 0))
 50            dimensions = (
 51                    ((0, 0), (WIDTH, BORDER_SIZE)),
 52                    ((0, BORDER_SIZE), (BORDER_SIZE, HEIGHT - 2*BORDER_SIZE)),
 53                    ((WIDTH-BORDER_SIZE, BORDER_SIZE), (WIDTH, HEIGHT - 2*BORDER_SIZE)),
 54                    ((0, HEIGHT-BORDER_SIZE), (WIDTH, BORDER_SIZE)),
 55                    )
 56
 57            for pos, size in dimensions:
 58                screen.draw.filled_rect( Rect(pos, size), color=border_colour,)
 59                screen.draw.rect( Rect(pos, size), color="black",)
 60
 61            for i, tile in enumerate(self.tiles):
 62                if tile: tile.draw(i)
 63        # }}}
 64        def update(self, dt): # {{{
 65            pass
 66        # }}}
 67        def shuffle(self): # {{{
 68            directions = [(0, -1), (-1, 0), (0, 1), (1, 0)]
 69            for i in range(400):
 70                random_move = directions[random.randint(0, 3)]
 71                self.move_tiles(random_move)
 72            # TODO {{{
 73            # 1. move the empty space to bottom right
 74            # 2. save the shuffling sequence
 75            # }}}
 76        # }}}
 77        def move_tiles(self,direction): # {{{
 78            empty_index = self.tiles.index(None)
 79            empty_x = empty_index % GAME_WIDTH
 80            empty_y = empty_index // GAME_WIDTH
 81            swap_x = empty_x + direction[0]
 82            swap_y = empty_y + direction[1]
 83            if (
 84                0 <= swap_x < GAME_WIDTH
 85                and
 86                0 <= swap_y < GAME_HEIGHT
 87                ):
 88                swap_index = swap_y * GAME_WIDTH + swap_x
 89
 90                self.tiles[empty_index], self.tiles[swap_index] = self.tiles[swap_index], self.tiles[empty_index]
 91            
 92            # }}}
 93        def is_ordered(self):
 94            is_ordered = False
 95            current_state = []
 96            for tile in self.tiles:
 97                if tile: current_state.append(tile.value)
 98                else: current_state.append(None)
 99
100            is_ordered = self.start == current_state
101
102            return is_ordered
103    # }}}
104    def __init__(self): # {{{
105        self.board = self.Board()
106    # }}}
107    def update(self, dt): # {{{
108        pass
109    # }}}
110    def draw(self): # {{{
111        self.board.draw()
112    # }}}
113    def on_key_down(self, key): # {{{
114        if key == keys.R:
115            self.board.shuffle()
116        elif key in [key.W, key.A, key.S, key.D]:
117            direction = {
118                key.W: (0, -1),
119                key.A: (-1, 0),
120                key.S: (0, 1),
121                key.D: (1, 0),
122                }[key]
123            self.board.move_tiles(direction)
124    # }}}
125    def on_mouse_down(self, pos, key): # {{{
126        x, y = pos
127
128        x = (x - BORDER_SIZE)//(TILE_SIZE + TILE_GAP)
129        y = (y - BORDER_SIZE)//(TILE_SIZE + TILE_GAP)
130        i = y*GAME_WIDTH + x
131        empty_index = self.board.tiles.index(None)
132        empty_x = empty_index % GAME_WIDTH
133        empty_y = empty_index // GAME_WIDTH
134        are_next = (
135                empty_x == x and abs(empty_y - y) == 1 
136                or
137                empty_y == y and abs(empty_x - x) == 1 
138                )
139
140        if are_next:
141            self.board.tiles[empty_index], self.board.tiles[i] = self.board.tiles[i], self.board.tiles[empty_index]
142        print(self.board.is_ordered())
143
144        # }}}
145
146# }}}
147# BOILERPLATE {{{
148def update(dt): game.update(dt)
149def draw(): game.draw()
150def on_key_down(key): game.on_key_down(key)
151def on_mouse_down(pos, button): game.on_mouse_down(pos, button)
152# }}}
153
154game = Game()
155pgzrun.go()
156
157
158
159# 王玉
160# 飛竜
161# 角馬
162# 金銀
163# 全
164# 桂今
165# 香仝
166# 歩个
167
168# 王将
169# 玉将
170# 飛車	飛
171# 竜王龍 or 竜[b]	ryū	FR
172# 角行角	kaku	B
173# 竜馬orse	+B	馬	uma	WB
174# 金将G	金	kin	WfF
175# 銀将S	銀	gin	FfW
176# 成銀+S	(全)	—	WfF
177# 桂馬N	桂	kei	ffN
178# 成桂	+N	(圭or今)	—	WfF
179# 香車L	香	kyō	fR
180# 成香	+L	(杏 or 仝)	—	WfF
181# 歩兵P	歩	fu	fW
182# と金	t