初始給定一個1~15數字隨機打散的4x4遊戲版,
讓使用者透過移動空格來重新排列數字,
最後數字排成1~15,而且空格剛好在右下角的時候,遊戲結束。
遊戲開始時,電腦為玩家建立一個4x4的板子,隨機填充0~15的數字。
數字0代表空格。
玩家每回合可以移動空格一次,藉此重新排列板子上的數字。
最後數字依序排成1~15,而且空格0剛好在右下角的時候,遊戲結束。
建立遊戲場景,為玩家建立一個4x4的板子,隨機填充0~15的數字。
數字0代表空格。
每回合都先顯示當下的板子狀態給玩家看。
玩家每回合可以選擇一個和空格相鄰的數字,接著把空格移動到對應的位置,
藉此重新排列板子上的數字。
接著檢查所有數字是否已經依序排成1~15,而且空格0剛好在右下角?
如果是,則遊戲結束。
如果不是,則遊戲繼續。
透過list()建構子 和 range()先建立長度為16的list,依序填入0~15的數字。
並且使用python內建的random.shuffle()方法,
進行隨機採樣,打散所有數字的位置。
最後,透過List comprehension生成4x4的遊戲版,上面帶著隨機生成的0~15的數字。
class FifteenPuzzle:
def __init__(self):
# 生成4x4的遊戲版
self.board = self.create_board()
# 紀錄空格所在的位置
self.empty_tile = self.find_empty()
def find_empty(self):
# 找空格所在的位置
for y in range(4):
for x in range(4):
if self.board[y][x] == 0:
return y, x
return -1, -1
def create_board(self):
# 生成4x4的遊戲版
tiles = list(range(0, 16))
random.shuffle(tiles)
return [tiles[i:i+4] for i in range(0, 16, 4)]
用雙層迴圈去做輸出排版,印出4x4遊戲版當下的內容。
def display_board(self):
for row in self.board:
print(' '.join(f'{tile:2}' for tile in row))
print()
return
先找出使用者輸入的數字,
接著把空格(用特殊數字0來代表)移動到使用者指定的數字所在的位置上。
def move_tile(self, tile):
y, x = self.empty_tile
for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
nx, ny = x + dx, y + dy
if 0 <= nx < 4 and 0 <= ny < 4 and self.board[ny][nx] == tile:
# 移動空格
self.board[y][x], self.board[ny][nx] = self.board[ny][nx], self.board[y][x]
# 紀錄空格在移動後的新位置
self.empty_tile = (ny, nx)
return True
return False
每回合檢查所有數字是否已經依序排成1~15,而且空格剛好在右下角?
如果是,則遊戲結束。
如果不是,則遊戲繼續。
def is_solved(self):
# 完全排好的狀態
answer = [list(range(i, i+4)) for i in range(1, 16, 4)]
answer[-1][-1] = 0
'''
[
[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12],
[ 13, 14, 15, 0]
]
'''
# 檢查是否已經排好所有數字
return self.board == answer
每回合先呼叫 is_solved()檢查是否遊戲結束。
如果遊戲還沒結束,就進入while本體,
等待使用者輸入數字,透過移動空格去重新排列遊戲版上的數字。
def play():
game = FifteenPuzzle()
while not game.is_solved():
game.display_board()
try:
tile = int(input("Enter the number to move (-1 to quit): "))
if tile == -1:
break
if not game.move_tile(tile):
print("Invalid move!")
except ValueError:
print("Please enter a valid number.")
print("Congratulations! You solved the puzzle!")
import random
class FifteenPuzzle:
def __init__(self):
self.board = self.create_board()
self.empty_tile = self.find_empty()
def find_empty(self):
for y in range(4):
for x in range(4):
if self.board[y][x] == 0:
return y, x
return -1, -1
def create_board(self):
tiles = list(range(0, 16))
random.shuffle(tiles)
return [tiles[i:i+4] for i in range(0, 16, 4)]
def display_board(self):
for row in self.board:
print(' '.join(f'{tile:2}' for tile in row))
print()
return
def move_tile(self, tile):
y, x = self.empty_tile
for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
nx, ny = x + dx, y + dy
if 0 <= nx < 4 and 0 <= ny < 4 and self.board[ny][nx] == tile:
self.board[y][x], self.board[ny][nx] = self.board[ny][nx], self.board[y][x]
self.empty_tile = (ny, nx)
return True
return False
def is_solved(self):
answer = [list(range(i, i+4)) for i in range(1, 16, 4)]
answer[-1][-1] = 0
'''
[
[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12],
[ 13, 14, 15, 0]
]
'''
return self.board == answer
def play():
game = FifteenPuzzle()
while not game.is_solved():
game.display_board()
try:
tile = int(input("Enter the number to move (-1 to quit): "))
if tile == -1:
break
if not game.move_tile(tile):
print("Invalid move!")
except ValueError:
print("Please enter a valid number.")
print("Congratulations! You solved the puzzle!")
if __name__ == "__main__":
play()
如果對程式或者演算法有興趣的同學,
可以試著觀察華榮道移動數字的規律,
開發更強的解題演算法,嘗試用最少的移動步數去重新排好所有的數字。
很有趣喔~