之前用 Python 的 pygame 庫寫了幾個小遊戲,分享一下。

坦克大戰 Python 版實現?

mp.weixin.qq.com

Python 實現經典飛機大戰?

mp.weixin.qq.com

Python 實現貪吃蛇?

mp.weixin.qq.com

Python 實現俄羅斯方塊?

mp.weixin.qq.com

用 Python 寫個消消樂小遊戲?

pythontalk.cn

用 Python 實現掃雷小遊戲?

pythontalk.cn


分享一個用Python自製的拼圖小遊戲,輕鬆搞定熊孩子

摘要:主要為大家詳細介紹了python實現拼圖小遊戲,文中還有示例代碼介紹,感興趣的小夥伴們可以參考一下。

開發工具

Python版本:3.6.4

相關模塊:

pygame模塊;

以及一些Python自帶的模塊

環境搭建

安裝Python並添加到環境變數,pip安裝需要的相關模塊即可。

原理介紹

遊戲簡介:

將圖像分為m×n個矩形塊,並將圖像右下角的矩形塊替換為空白塊後,將這些矩形塊隨機擺放成原圖像的形狀。遊戲目標為通過移動非空白塊將隨機擺放獲得的圖像恢復成原圖像的模樣,且規定移動操作僅存在於非空白塊移動到空白塊。

例如下圖所示:

逐步實現:

Step1:遊戲初始界面

既然是遊戲,總得有個初始界面吧?

OK,我們先寫一個遊戲初始界面:

效果是這樣子的:

根據玩家自身水平,可以選擇不同難度的拼圖遊戲。

Step2:定義移動操作

定義移動操作的目的是為了移動拼圖(好像是廢話T_T),具體實現起來十分簡單:

Step3:遊戲主界面

OK,有了前面的鋪墊,我們可以開始實現我們的遊戲主界面了。

首先,我們需要打亂拼圖, 但是隨機打亂很可能導致拼圖無解,因此我們通過隨機移動拼圖來實現打亂拼圖的效果 ,這也是我們先定義拼圖的移動操作的主要原因:

遊戲主界面初始化:

最後實現主界面的顯示刷新以及事件響應等功能:

Step4:遊戲結束界面

當玩家完成拼圖後,需要顯示遊戲結束界面,和遊戲初始界面類似,實現起來都比較簡單:

OK,大功告成!!!

本文分享自華為雲社區《利用python製作拼圖小遊戲的全過程》,原文作者:一隻無腦程序員。

發佈於 01-07繼續瀏覽內容知乎發現更大的世界打開Chrome繼續車卡門車卡門?

程序員話題下的優秀答主

關注這個問題很久了,終於騰出空來回答。

知乎很久沒更新,這段時間我做過很多事,其中之一就是:用 Python 寫遊戲,並且出版了一本書 《零基礎入門 Python 遊戲》。至於為什麼寫這本書,這裡不表,直接切入正題,Python 能做遊戲么?能做什麼樣的遊戲?怎麼樣做遊戲?

先來簡短回答下上面的問題

  1. Python 應用範圍很廣泛,遊戲當然也能做。
  2. 就目前比較流行的一些 Python 基礎遊戲引擎來看,大多為桌面端的 2D 或者 3D 遊戲,移動平台上也有相應的解決方案,不過相對較繁瑣,不是主流。
  3. 網路上目前流行的教程多為使用 Pygame 開發一些簡單的小遊戲。其實,除了 Pygame, 還有其他很多同樣優秀的框架,如 Cocos2D ,Panda3d 等。個人認為,由於其語法顆粒度問題,Pygame 並不是最好的選擇。除了使用現有的遊戲框架,為達到定製化和高性能的需求,也可以使用 C、C++ 編寫遊戲引擎,Python 開發上層繪製與顯示的部分。

再來看下我使用 Python 開發過的一些遊戲 Demo

  1. 俄羅斯方塊

2. 超級瑪麗

3. 其他

Github 頁面

https://github.com/chcarmen/python-game-book?

github.com

關於 Python 遊戲的詳細介紹,以及這本書的內容目錄,都在上面。開源了所有遊戲的源代碼,歡迎follow, star, issue, pr, fork

書的封面

購買鏈接

《零基礎入門Python遊戲》(車洪)【摘要 書評 試讀】- 京東圖書?

item.jd.com圖標

最後啰嗦一句,這本書可能是目前國內唯一一本關於 Python 遊戲的系統性教程,至少在我開始寫這本書的時候情況是這樣。


關注這個問題很久了,終於騰出空來回答。

知乎很久沒更新,這段時間我做過很多事,其中之一就是:用 Python 寫遊戲,並且出版了一本書 《零基礎入門 Python 遊戲》。至於為什麼寫這本書,這裡不表,直接切入正題,Python 能做遊戲么?能做什麼樣的遊戲?怎麼樣做遊戲?

先來簡短回答下上面的問題

  1. Python 應用範圍很廣泛,遊戲當然也能做。
  2. 就目前比較流行的一些 Python 基礎遊戲引擎來看,大多為桌面端的 2D 或者 3D 遊戲,移動平台上也有相應的解決方案,不過相對較繁瑣,不是主流。
  3. 網路上目前流行的教程多為使用 Pygame 開發一些簡單的小遊戲。其實,除了 Pygame, 還有其他很多同樣優秀的框架,如 Cocos2D ,Panda3d 等。個人認為,由於其語法顆粒度問題,Pygame 並不是最好的選擇。除了使用現有的遊戲框架,為達到定製化和高性能的需求,也可以使用 C、C++ 編寫遊戲引擎,Python 開發上層繪製與顯示的部分。

再來看下我使用 Python 開發過的一些遊戲 Demo

  1. 俄羅斯方塊

2. 超級瑪麗

3. 其他

Github 頁面

https://github.com/chcarmen/python-game-book?

github.com

關於 Python 遊戲的詳細介紹,以及這本書的內容目錄,都在上面。開源了所有遊戲的源代碼,歡迎follow, star, issue, pr, fork

書的封面

購買鏈接

《零基礎入門Python遊戲》(車洪)【摘要 書評 試讀】- 京東圖書?

item.jd.com圖標

最後啰嗦一句,這本書可能是目前國內唯一一本關於 Python 遊戲的系統性教程,至少在我開始寫這本書的時候情況是這樣。


有的,Python的pygame輕量級遊戲引擎,還是很適合練練手的,讓你對遊戲的運行機制可以有了解,但該遊戲引擎只能製作2d遊戲,而且運營效率很低,不建議用來專門做遊戲,做點打飛機之類的小遊戲是沒問題的。

另外,Python的Panda3d也是可以製作遊戲的,休注意是Panda3d,不是panda。迪士尼曾經就用Panda3d作為遊戲引擎開發了一款遊戲。

除此之外,還有一些GUI庫也可以做些小遊戲,如PyQt5的3d模塊等。

不過製作遊戲,還是不建議用Python,因為Python的速度慢,而且遊戲引擎也不如市面上的流行引擎專業。如果對遊戲製作感興趣,建議還是學習下Unity、Unreal、cocos-2dx、cocos-creator等遊戲引擎。這些引擎都是對遊戲開發做了封裝,開發起來很方便,甚至不用寫代碼,不是pygame這種輕量級引擎能比的,而且對遊戲設計的思想也會有很大的差別。


我用Python寫過好幾個遊戲,小鳥管道,是男人就下100層,五子棋,中國象棋,雷電戰機,魂斗羅,我的世界,坦克大戰,超級瑪麗。下面附上連連看源代碼,需要其它遊戲源代碼的關注我。


需要源碼和打包好的文件進裙免費領取
QQ群:721195303

import os, random
import tkinter as tk
import tkinter.messagebox
from PIL import Image, ImageTk

root = tk.Tk()

class MainWindow():
__gameTitle = "連連看遊戲"
__windowWidth = 700
__windowHeigth = 500
__icons = []
__gameSize = 10 # 遊戲尺寸
__iconKind = __gameSize * __gameSize / 4 # 小圖片種類數量
__iconWidth = 40
__iconHeight = 40
__map = [] # 遊戲地圖
__delta = 25
__isFirst = True
__isGameStart = False
__formerPoint = None
EMPTY = -1
NONE_LINK = 0
STRAIGHT_LINK = 1
ONE_CORNER_LINK = 2
TWO_CORNER_LINK = 3

def __init__(self):
root.title(self.__gameTitle)
self.centerWindow(self.__windowWidth, self.__windowHeigth)
root.minsize(460, 460)

self.__addComponets()
self.extractSmallIconList()

def __addComponets(self):
self.menubar = tk.Menu(root, bg="lightgrey", fg="black")

self.file_menu = tk.Menu(self.menubar, tearoff=0, bg="lightgrey", fg="black")
self.file_menu.add_command(label="新遊戲", command=self.file_new, accelerator="Ctrl+N")

self.menubar.add_cascade(label="遊戲", menu=self.file_menu)
root.configure(menu=self.menubar)

self.canvas = tk.Canvas(root, bg = white, width = 450, height = 450)
self.canvas.pack(side=tk.TOP, pady = 5)
self.canvas.bind(&, self.clickCanvas)

def centerWindow(self, width, height):
screenwidth = root.winfo_screenwidth()
screenheight = root.winfo_screenheight()
size = %dx%d+%d+%d % (width, height, (screenwidth - width)/2, (screenheight - height)/2)
root.geometry(size)

def file_new(self, event=None):
self.iniMap()
self.drawMap()
self.__isGameStart = True

def clickCanvas(self, event):
if self.__isGameStart:
point = self.getInnerPoint(Point(event.x, event.y))
# 有效點擊坐標
if point.isUserful() and not self.isEmptyInMap(point):
if self.__isFirst:
self.drawSelectedArea(point)
self.__isFirst= False
self.__formerPoint = point
else:
if self.__formerPoint.isEqual(point):
self.__isFirst = True
self.canvas.delete("rectRedOne")
else:
linkType = self.getLinkType(self.__formerPoint, point)
if linkType[type] != self.NONE_LINK:
# TODO Animation
self.ClearLinkedBlocks(self.__formerPoint, point)
self.canvas.delete("rectRedOne")
self.__isFirst = True
if self.isGameEnd():
tk.messagebox.showinfo("You Win!", "Tip")
self.__isGameStart = False
else:
self.__formerPoint = point
self.canvas.delete("rectRedOne")
self.drawSelectedArea(point)

# 判斷遊戲是否結束
def isGameEnd(self):
for y in range(0, self.__gameSize):
for x in range(0, self.__gameSize):
if self.__map[y][x] != self.EMPTY:
return False
return True

提取小頭像數組

def extractSmallIconList(self):
imageSouce = Image.open(圖片/NARUTO.png)
for index in range(0, int(self.__iconKind)):
region = imageSouce.crop((self.__iconWidth * index, 0,
self.__iconWidth * index + self.__iconWidth - 1, self.__iconHeight - 1))
self.__icons.append(ImageTk.PhotoImage(region))

初始化地圖 存值為0-24

def iniMap(self):
self.__map = [] # 重置地圖
tmpRecords = []
records = []
for i in range(0, int(self.__iconKind)):
for j in range(0, 4):
tmpRecords.append(i)

total = self.__gameSize * self.__gameSize
for x in range(0, total):
index = random.randint(0, total - x - 1)
records.append(tmpRecords[index])
del tmpRecords[index]

# 一維數組轉為二維,y為高維度
for y in range(0, self.__gameSize):
for x in range(0, self.__gameSize):
if x == 0:
self.__map.append([])
self.__map[y].append(records[x + y * self.__gameSize])

根據地圖繪製圖像

def drawMap(self):
self.canvas.delete("all")
for y in range(0, self.__gameSize):
for x in range(0, self.__gameSize):
point = self.getOuterLeftTopPoint(Point(x, y))
im = self.canvas.create_image((point.x, point.y),
image=self.__icons[self.__map[y][x]], anchor=nw, tags = im%d%d % (x, y))

獲取內部坐標對應矩形左上角頂點坐標

def getOuterLeftTopPoint(self, point):
return Point(self.getX(point.x), self.getY(point.y))

獲取內部坐標對應矩形中心坐標

def getOuterCenterPoint(self, point):
return Point(self.getX(point.x) + int(self.__iconWidth / 2),
self.getY(point.y) + int(self.__iconHeight / 2))

def getX(self, x):
return x * self.__iconWidth + self.__delta

def getY(self, y):
return y * self.__iconHeight + self.__delta

獲取內部坐標

def getInnerPoint(self, point):
x = -1
y = -1

for i in range(0, self.__gameSize):
x1 = self.getX(i)
x2 = self.getX(i + 1)
if point.x &>= x1 and point.x &< x2: x = i for j in range(0, self.__gameSize): j1 = self.getY(j) j2 = self.getY(j + 1) if point.y &>= j1 and point.y &< j2: y = j return Point(x, y) 選擇的區域變紅,point為內部坐標 def drawSelectedArea(self, point): pointLT = self.getOuterLeftTopPoint(point) pointRB = self.getOuterLeftTopPoint(Point(point.x + 1, point.y + 1)) self.canvas.create_rectangle(pointLT.x, pointLT.y, pointRB.x - 1, pointRB.y - 1, outline = red, tags = "rectRedOne") 消除連通的兩個塊 def ClearLinkedBlocks(self, p1, p2): self.__map[p1.y][p1.x] = self.EMPTY self.__map[p2.y][p2.x] = self.EMPTY self.canvas.delete(im%d%d % (p1.x, p1.y)) self.canvas.delete(im%d%d % (p2.x, p2.y)) 地圖上該點是否為空 def isEmptyInMap(self, point): if self.__map[point.y][point.x] == self.EMPTY: return True else: return False 獲取兩個點連通類型 def getLinkType(self, p1, p2): # 首先判斷兩個方塊中圖片是否相同 if self.__map[p1.y][p1.x] != self.__map[p2.y][p2.x]: return { type: self.NONE_LINK } if self.isStraightLink(p1, p2): return { type: self.STRAIGHT_LINK } res = self.isOneCornerLink(p1, p2) if res: return { type: self.ONE_CORNER_LINK, p1: res } res = self.isTwoCornerLink(p1, p2) if res: return { type: self.TWO_CORNER_LINK, p1: res[p1], p2: res[p2] } return { type: self.NONE_LINK } 直連 def isStraightLink(self, p1, p2): start = -1 end = -1 # 水平 if p1.y == p2.y: # 大小判斷 if p2.x &< p1.x: start = p2.x end = p1.x else: start = p1.x end = p2.x for x in range(start + 1, end): if self.__map[p1.y][x] != self.EMPTY: return False return True elif p1.x == p2.x: if p1.y &> p2.y:
start = p2.y
end = p1.y
else:
start = p1.y
end = p2.y
for y in range(start + 1, end):
if self.__map[y][p1.x] != self.EMPTY:
return False
return True
return False

def isOneCornerLink(self, p1, p2):
pointCorner = Point(p1.x, p2.y)
if self.isStraightLink(p1, pointCorner) and self.isStraightLink(pointCorner, p2) and self.isEmptyInMap(pointCorner):
return pointCorner

pointCorner = Point(p2.x, p1.y)
if self.isStraightLink(p1, pointCorner) and self.isStraightLink(pointCorner, p2) and self.isEmptyInMap(pointCorner):
return pointCorner

def isTwoCornerLink(self, p1, p2):
for y in range(-1, self.__gameSize + 1):
pointCorner1 = Point(p1.x, y)
pointCorner2 = Point(p2.x, y)
if y == p1.y or y == p2.y:
continue
if y == -1 or y == self.__gameSize:
if self.isStraightLink(p1, pointCorner1) and self.isStraightLink(pointCorner2, p2):
return {p1: pointCorner1, p2: pointCorner2}
else:
if self.isStraightLink(p1, pointCorner1) and self.isStraightLink(pointCorner1, pointCorner2) and self.isStraightLink(pointCorner2, p2) and self.isEmptyInMap(pointCorner1) and self.isEmptyInMap(pointCorner2):
return {p1: pointCorner1, p2: pointCorner2}

# 橫向判斷
for x in range(-1, self.__gameSize + 1):
pointCorner1 = Point(x, p1.y)
pointCorner2 = Point(x, p2.y)
if x == p1.x or x == p2.x:
continue
if x == -1 or x == self.__gameSize:
if self.isStraightLink(p1, pointCorner1) and self.isStraightLink(pointCorner2, p2):
return {p1: pointCorner1, p2: pointCorner2}
else:
if self.isStraightLink(p1, pointCorner1) and self.isStraightLink(pointCorner1, pointCorner2) and self.isStraightLink(pointCorner2, p2) and self.isEmptyInMap(pointCorner1) and self.isEmptyInMap(pointCorner2):
return {p1: pointCorner1, p2: pointCorner2}

class Point():
def __init__(self, x, y):
self.x = x
self.y = y

def isUserful(self):
if self.x &>= 0 and self.y &>= 0:
return True
else:
return False

判斷兩個點是否相同

def isEqual(self, point):
if self.x == point.x and self.y == point.y:
return True
else:
return False

克隆一份對象

def clone(self):
return Point(self.x, self.y)

改為另一個對象

def changeTo(self, point):
self.x = point.x
self.y = point.y

m = MainWindow()
root.mainloop()

如果大家在學習中遇到困難,想找一個python學習交流環境,可以點擊下方加入我們一起學習,歡迎零基礎和大佬加入

正在跳轉?

jq.qq.com

有關Python問題都可以給我留言喔


推薦閱讀:
相关文章