用python寫貪吃蛇,不來看看這個嗎?

當你學會python,興趣正濃的時候,是不是迫不及待的想實現些什麼,實現什麼好呢,好難受,快讓我實現些什麼。實現個貪吃蛇吧,反正也沒啥技術含量(狗頭)
實現貪吃蛇的博客真的好多啊,一開始我想複製一個下來,然後看一看,改一改,我就想找一個直接全部複製到pycharm,然後運行就可以的,哎,怎麼找了幾個都不行…後來去pygame官網看看,隨手找到一個貪吃蛇實現,github把代碼複製下來,哎,好像就是我想要的東西了。原版的是這個樣子的
在這裏插入圖片描述
我們可以修改成這個樣子,看起來會不會好一點
在這裏插入圖片描述
是的上面的其實就是改顏色,不過還添加一個有趣地方,當蛇靠近邊緣時,會開啓“慢動作”比如下面這個
在這裏插入圖片描述

來一起看看是如何實現的,然後我們再給他修改修改,嘿嘿嘿
先來了解下思路,整個遊戲過程中,我們應該是不停的在循環檢查,每次循環檢查蛇是否碰到牆壁,是否碰到自己,是否吃到食物,然後每個結果都執行對應操作,最後更新一下畫面,繼續循環。蛇如何存呢,程序採用一個列表來存,把蛇的每一節都存在這個列表裏,然後蛇的移動,我們只需要把最後一節蛇刪除,然後計算出新的蛇頭位置,把蛇頭更新,說起來可能不太好理解,一看代碼就明白了,下面分步來看看(原始的版本),說明全部在代碼註釋中啦

1、初始化

def __init__(self, windowSizeX=500, windowSizeY=500):
        #窗口大小
        self.windowSizeX = windowSizeX
        self.windowSizeY = windowSizeY
        #食物和蛇的單位大小
        self.gameUnitSize = 16
        #讓屏幕和單位大小適配
        if (self.windowSizeX % self.gameUnitSize != 0):
            self.windowSizeX += self.gameUnitSize - self.windowSizeX % self.gameUnitSize
        if (self.windowSizeY % self.gameUnitSize != 0):
            self.windowSizeY += self.gameUnitSize - self.windowSizeY % self.gameUnitSize
        self.window = pygame.display.set_mode(
            [self.windowSizeX, self.windowSizeY])

		#標題
        pygame.display.set_caption("Snake!")
        #填充色
        self.window.fill((255, 255, 255))
        #初始化字體
        pygame.font.init()
        #設置字體
        self.font = pygame.font.SysFont("bahnschrift", 20)
		
		#設置畫面顯示的內容
        self.text = self.font.render(
            "Press Direction key to begin", True, (0, 0, 0))
        self.startTextRect = self.text.get_rect(
            center=(windowSizeX/2, windowSizeY/2))

		#這個就是我們的蛇了
        self.snake = [self.startSnake()]
        #這是我們的食物
        self.food = self.createFood()
        #速度
        self.speed = self.gameUnitSize
        #得分
        self.score = 0
        #得分顯示
        self.scoreText = self.font.render(
            f"Score: {self.score}", True, (0, 0, 0), None)
        #蛇的方向控制
        self.snakeDirections = {
            'left': (-1, 0), 'right': (1, 0), 'up': (0, -1), 'down': (0, 1)}
		#上一次的執行動作,初始化隨便給一個
        self.previousDirection = self.snakeDirections.get('left')
	
		#循環內容
        self.readyScreen()
        self.gameLoop()

2、循環部分

#檢測鍵盤事件,當有鍵盤按鍵按下時,pygame可以幫我們檢測到是什麼按鍵被按下了
    def readyScreen(self):
        while True:
            self.window.blit(self.text, self.startTextRect)
            for event in pygame.event.get():
                if event.type == KEYDOWN:
                    if event.key == K_ESCAPE:
                        exit()
            keys = pygame.key.get_pressed()
            if (keys[K_LEFT]):
                self.previousDirection = self.snakeDirections.get('left')
                break
            if (keys[K_RIGHT]):
                self.previousDirection = self.snakeDirections.get('right')
                break
            if (keys[K_UP]):
                self.previousDirection = self.snakeDirections.get('up')
                break
            if (keys[K_DOWN]):
                self.previousDirection = self.snakeDirections.get('down')
                break
            pygame.display.update()
#循環開始     
    def gameLoop(self):
        while True:
            pygame.time.delay(100)
            self._input()
            self._update()
            
#方向鍵被按下時,修改組成蛇的列表            
    def _input(self):
        for event in pygame.event.get():
            if event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    exit()
        keys = pygame.key.get_pressed()
        if (keys[K_LEFT] and self.previousDirection != self.snakeDirections.get('right')):
            self.moveSnake(self.snakeDirections.get('left'))
        elif (keys[K_RIGHT] and self.previousDirection != self.snakeDirections.get('left')):
            self.moveSnake(self.snakeDirections.get('right'))
        elif (keys[K_UP] and self.previousDirection != self.snakeDirections.get('down')):
            self.moveSnake(self.snakeDirections.get('up'))
        elif (keys[K_DOWN] and self.previousDirection != self.snakeDirections.get('up')):
            self.moveSnake(self.snakeDirections.get('down'))
        else:
            self.moveSnake(self.previousDirection)
            
#更新畫面的地方                       
    def _update(self):

        self.window.fill((0,0,0))

        if (self.intersect() == True):
            self.appendSnake()
            self.moveFood()
            self.score += 1

        elif (self.snakeCollidingWithWall() == True or self.snakeCollidingWithSelf() == True):
            return self.killSnake()

        for link in self.snake:
            pygame.draw.rect(self.window, (255,255,255), link)
        pygame.draw.rect(self.window, (102, 255, 51), self.food)

        self.scoreText = self.font.render(
            f"Score: {self.score}", True, (255, 255, 255))
        self.scoreTextRect = self.scoreText.get_rect(center=(40, 10))
        self.window.blit(self.scoreText, self.scoreTextRect)
		#不要忘了這個updata
        pygame.display.update()

源碼代碼彙總如下:

class Game_snake_ex:
    def __init__(self, windowsize_x=500, windowsize_y=500):
        self.windowsize_x = windowsize_x
        self.windowsize_y = windowsize_y
        self.gameUnitsize = 16
        if (self.windowsize_x % self.gameUnitsize != 0):
            self.windowsize_x += self.gameUnitsize - self.windowsize_x % self.gameUnitsize
        if (self.windowsize_y % self.gameUnitsize != 0):
            self.windowsize_y += self.gameUnitsize - self.windowsize_y % self.gameUnitsize
        self.window = pygame.display.set_mode(
            [self.windowsize_x, self.windowsize_y])

        pygame.display.set_caption("Snake!")
        self.window.fill((0, 0, 0))
        pygame.font.init()
        self.font = pygame.font.SysFont("bahnschrift", 20)

        self.text = self.font.render(
            "Press Direction key to begin", True, (255, 255, 255))
        self.startTextRect = self.text.get_rect(
            center=(windowsize_x/2, windowsize_y/2))
        self.snake = [self.startSnake()]
        self.food = self.createFood()
        self.speed = self.gameUnitsize
        self.score = 0
        self.scoreText = self.font.render(
            f"Score: {self.score}", True, (255, 255, 255), None)
        self.snakeDirections = {
            'left': (-1, 0), 'right': (1, 0), 'up': (0, -1), 'down': (0, 1)}

        self.previousDirection = self.snakeDirections.get('left')
        self.readyScreen()
        self.gameLoop()

    def startSnake(self):
        snakeNodeX = self.window.get_width() / 2 - self.gameUnitsize
        if (snakeNodeX % self.gameUnitsize != 0):
            snakeNodeX -= snakeNodeX % self.gameUnitsize
        snakeNodeY = self.window.get_height() / 2 - self.gameUnitsize
        if (snakeNodeY % self.gameUnitsize != 0):
            snakeNodeY -= snakeNodeY % self.gameUnitsize

        snakeNodeRectangle = Rect(
            (snakeNodeX, snakeNodeY), (self.gameUnitsize, self.gameUnitsize))
        return snakeNodeRectangle

    def createFood(self):
        foodX = randint(0, self.window.get_width() - self.gameUnitsize)
        if (foodX % self.gameUnitsize != 0):
            foodX -= foodX % self.gameUnitsize
        foodY = randint(0, self.window.get_height() - self.gameUnitsize)
        if (foodY % self.gameUnitsize != 0):
            foodY -= foodY % self.gameUnitsize
        foodRectangle = Rect(
            (foodX, foodY), (self.gameUnitsize, self.gameUnitsize))
        return foodRectangle

    def moveFood(self):
        self.food.x = randint(0, self.window.get_width() - self.gameUnitsize)
        if (self.food.x % self.gameUnitsize != 0):
            self.food.x -= self.food.x % self.gameUnitsize
        self.food.y = randint(0, self.window.get_height() - self.gameUnitsize)
        if (self.food.y % self.gameUnitsize != 0):
            self.food.y -= self.food.y % self.gameUnitsize

    def createSnake(self):
        snakeNodeX = randint(0, self.window.get_width())
        if (snakeNodeX % self.gameUnitsize != 0):
            snakeNodeX -= snakeNodeX % self.gameUnitsize
        snakeNodeY = randint(0, self.window.get_height())
        if (snakeNodeY % self.gameUnitsize != 0):
            snakeNodeY -= snakeNodeY % self.gameUnitsize
        snakeNodeRectangle = Rect(
            (snakeNodeX, snakeNodeY), (self.gameUnitsize, self.gameUnitsize))
        return snakeNodeRectangle

    def appendSnake(self):
        # add node to tail
        newSnakeLink = Rect((self.snake[len(self.snake) - 1].x, self.snake[len(
            self.snake) - 1].y), (self.gameUnitsize, self.gameUnitsize))
        self.snake.append(newSnakeLink)

    def moveSnake(self, direction):
    	#蛇尾刪掉,更新蛇頭,其他不變
        x = 0
        y = 1
        self.snake[len(self.snake) - 1].x = self.snake[0].x + \
            direction[x] * self.speed
        self.snake[len(self.snake) - 1].y = self.snake[0].y + \
            direction[y] * self.speed
        self.snake.insert(0, self.snake.pop())
        self.previousDirection = direction


    def intersect(self):
        if self.snake[0].x == self.food.x and self.snake[0].y == self.food.y:
            return True
        return False

    def snakeCollidingWithWall(self):
        if self.snake[0].x >= self.windowsize_x or self.snake[0].x < 0 or self.snake[0].y >= self.windowsize_y or self.snake[0].y < 0:
            return True
        return False


    def snakeCollidingWithSelf(self):
        for link in self.snake:
            if (self.snake[0] is not link):
                if self.snake[0].x == link.x and self.snake[0].y == link.y:
                    return True
        return False

    def killSnake(self):
        return self._gameOverScreen()

    def _update(self):

        self.window.fill((0,0,0))

        if (self.intersect() == True):
            self.appendSnake()
            self.moveFood()
            self.score += 1

        elif (self.snakeCollidingWithWall() == True or self.snakeCollidingWithSelf() == True):
            return self.killSnake()

        for link in self.snake:
            pygame.draw.rect(self.window, (255,255,255), link)
        pygame.draw.rect(self.window, (102, 255, 51), self.food)

        self.scoreText = self.font.render(
            f"Score: {self.score}", True, (255, 255, 255))
        self.scoreTextRect = self.scoreText.get_rect(center=(40, 10))
        self.window.blit(self.scoreText, self.scoreTextRect)

        pygame.display.update()

    def _input(self):
        for event in pygame.event.get():
            if event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    exit()
        keys = pygame.key.get_pressed()
        if (keys[K_LEFT] and self.previousDirection != self.snakeDirections.get('right')):
            self.moveSnake(self.snakeDirections.get('left'))
        elif (keys[K_RIGHT] and self.previousDirection != self.snakeDirections.get('left')):
            self.moveSnake(self.snakeDirections.get('right'))
        elif (keys[K_UP] and self.previousDirection != self.snakeDirections.get('down')):
            self.moveSnake(self.snakeDirections.get('up'))
        elif (keys[K_DOWN] and self.previousDirection != self.snakeDirections.get('up')):
            self.moveSnake(self.snakeDirections.get('down'))
        else:
            self.moveSnake(self.previousDirection)

    def readyScreen(self):
        while True:
            self.window.blit(self.text, self.startTextRect)
            for event in pygame.event.get():
                if event.type == KEYDOWN:
                    if event.key == K_ESCAPE:
                        exit()
            keys = pygame.key.get_pressed()
            if (keys[K_LEFT]):
                self.previousDirection = self.snakeDirections.get('left')
                break
            if (keys[K_RIGHT]):
                self.previousDirection = self.snakeDirections.get('right')
                break
            if (keys[K_UP]):
                self.previousDirection = self.snakeDirections.get('up')
                break
            if (keys[K_DOWN]):
                self.previousDirection = self.snakeDirections.get('down')
                break
            pygame.display.update()

    def _gameOverScreen(self):
        while True:
            self.window.fill((0, 0, 0))
            self.text = self.font.render(
                f"Game Over, Score: {self.score}", True, (255, 255, 255))
            self.startTextRect = self.text.get_rect(
                center=(self.windowsize_x/2, self.windowsize_y/2))
            self.window.blit(self.text, self.startTextRect)

            keys = pygame.key.get_pressed()
            if (keys[K_r]):
                break
            for event in pygame.event.get():
                if event.type == KEYDOWN:
                    if event.key == K_ESCAPE:
                     exit()
            pygame.display.update()
        return 1

    def gameLoop(self):
        while True:
            pygame.time.delay(100)
            self._input()
            self._update()

上面那個是原版,實現方法明白了以後,就可以自己動手來修改修改啦
這個是我添加 顏色變化 和“慢動作” 的版本
下載地址gitbub

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章