【Python練習】烏龜喫魚小遊戲

最近在學習Python的時候看到一個烏龜喫魚的練習,下面是我做這個練習的過程。

遊戲規則如下:

1. 遊戲背景爲10*10 
2.
遊戲會自動生成1個烏龜和10條魚; 
3.
它們移動方向隨機
4.
烏龜最大移動能力爲2 [-2,-1,1,2] 
5.
魚最大移動能力爲1 [-1,1] 
6.
當移動到場景邊界,自動反方向移動
7.
烏龜初始化體能爲100;每移動一次消耗體能1 
8.
當烏龜和魚的座標重合,代表烏龜喫掉魚,體能增加20 

9. 烏龜無體力或者魚喫光,遊戲結束;

因爲烏龜和魚移動方向是隨機的,而且烏龜的移動步長也是隨機的,因此引入random模塊

import random as r

首先定義一個烏龜類

class Tortoise:
    step = 2 # 步長
    axis = [0, 0] # 初始化座標
    area = [0, 0] # 初始化遊戲場景大小
    def __init__(self, a, b): # 定義遊戲場景大小
        self.area[0] = a
        self.area[1] = b
    def start_axis(self, x = 0, y = 0): # 設定烏龜開始的座標
        self.axis[0] = x
        self.axis[1] = y
        return self.axis
    def move(self): # 烏龜的移動
        while True:
            temp_x = r.randint(-self.step, self.step)
            temp_y = r.randint(-self.step, self.step)
            if temp_x == 0 and temp_y == 0:
                continue
            self.axis[0] = self.axis[0] + temp_x
            self.axis[1] = self.axis[1] + temp_y
            for i in range(0, 2): # 當移動到邊界時往反方向移動
                if self.axis[i] < 0: # 0 --> -2 = 0 --> 2
                    self.axis[i] = 0 - self.axis[i]
                if self.axis[i] > 10: # 10 --> 12 = 10 --> 8
                    self.axis[i] = 20 - self.axis[i]
            return self.axis

定義一個魚類

class Fish:
    step = 1 # 步長
    area = [0, 0] # 初始化座標
    axis = [0, 0] # 初始化遊戲場景大小
    def __init__(self, a, b): # 定義遊戲場景大小
        self.area[0] = a
        self.area[1] = b
    def start_axis(self): # 設定魚開始的座標
        self.axis[0] = r.randint(self.area[0], self.area[1])
        self.axis[1] = r.randint(self.area[0], self.area[1])
        return self.axis
    def move(self, axis): # 魚的移動
        self.axis = axis
        while True:
            temp_x = r.randint(-self.step, self.step)
            temp_y = r.randint(-self.step, self.step)
            if temp_x == 0 and temp_y == 0:
                continue
            self.axis[0] = self.axis[0] + temp_x
            self.axis[1] = self.axis[1] + temp_y
            for i in range(0, 2): # 當移動到邊界時往反方向移動
                if self.axis[i] < 0: # 0 --> -1 = 0 --> 1
                    self.axis[i] = 0 - self.axis[i]
                if self.axis[i] > 10: # 10 --> 11 = 10 --> 9
                    self.axis[i] = 20 - self.axis[i]
            return self.axis

接下來就可以開始寫遊戲的主程序了,首先,將烏龜和10條魚放進遊戲場景中

energy = 100
tort = Tortoise(1, 10)
tort_axis = tort.start_axis(1, 1) # 將烏龜放入場景內,設定初始座標爲(1,1)
print('-----------------------------')
print('烏龜的位置是:',tort_axis)
print('烏龜的體力:%d' % energy)
fish = Fish(1, 10)
fish_axis = {}
flag = 1
while True: # 將10條魚分別放入不同的座標中
    temp_axis = fish.start_axis()
    if flag == 1 and temp_axis != tort_axis:
        fish_axis.setdefault(flag, 0)
        fish_axis[flag] = temp_axis
        print('Fish%d的位置是:' % flag, fish_axis[flag])
        flag += 1
    if  flag > 1 and temp_axis != fish_axis[flag - 1] and temp_axis != tort_axis:
        fish_axis.setdefault(flag, 0)
        fish_axis[flag] = temp_axis
        print('Fish%d的位置是:' % flag, fish_axis[flag])
        flag += 1
    if flag > 10:
        break

然後實現烏龜和魚在場景中移動,並設立勝利條件

while True:    
    num = list(fish_axis.keys())
    length = len(num)
    for i in range(0, length): # 小魚的移動
        flag = 0
        while True:
            temp_axis = fish.move(fish_axis[num[i]])
            if i == 0:
                fish_axis[num[i]] = temp_axis.copy()
                print('fish%d的位置是:' % num[i], fish_axis[num[i]])
                flag = 1
            elif temp_axis != fish_axis[num[i - 1]]:
                # 字典中的前一項而不是i-1
                fish_axis[num[i]] = temp_axis.copy()
                print('fish%d的位置是:' % num[i], fish_axis[num[i]])
                flag = 1
            if flag == 1:
                break
    tort_axis = tort.move() # 烏龜的移動
    print('烏龜的位置是:',tort_axis)
    energy -= 1
    # 判斷小魚是否被烏龜喫掉
    for i in fish_axis:
        if fish_axis[i] == tort_axis:
            print('fish%s被喫掉' % i)
            fish_axis.pop(i)
            print('烏龜回覆20點體力')
            energy += 20
    print('烏龜的體力:%d' % energy)
    print('-----------------------------')
    if fish_axis == {}:
        print('烏龜獲勝')
        break
    elif energy == 0:
        print('小魚獲勝')
        break

 完成以後開始運行,結果......居然進入了死循環!!!抓狂

用ctrl+c終結程序後觀察錯誤信息發現錯誤 temp_axis = fish.start_axis()位置

Traceback (most recent call last):
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\example\test_37_1.py", line 64, in <module>
    temp_axis = fish.start_axis()
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\example\test_37_1.py", line 36, in start_axis
    self.axis[1] = random.randint(self.area[0], self.area[1])
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\random.py", line 220, in randint
    return self.randrange(a, b+1)
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\random.py", line 196, in randrange
    return istart + self._randbelow(width)
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\random.py", line 233, in _randbelow
    while r >= n:
KeyboardInterrupt

 在仔細觀察錯誤所在位置的程序發現錯誤位置爲下面劃線部分,原因是我使用的是賦值語句,這就說明fish_axis[flag]和temp_axis的地址是一樣的,也就是說在temp_axis = fish.start_axis()改變temp_axis的值時fish_axis[flag]的值也改變了,因此if語句中的條件temp_axis != fish_axis[flag - 1]永遠不成立,while語句進入死循環。

while True: # 將10條魚分別放入不同的座標中
    temp_axis = fish.start_axis()
    if flag == 1 and temp_axis != tort_axis:
        fish_axis.setdefault(flag, 0)
        fish_axis[flag] = temp_axis
        print('Fish%d的位置是:' % flag, fish_axis[flag])
        flag += 1
    if  flag > 1 and temp_axis != fish_axis[flag - 1] and temp_axis != tort_axis:
        fish_axis.setdefault(flag, 0)
        fish_axis[flag] = temp_axis
        print('Fish%d的位置是:' % flag, fish_axis[flag])
        flag += 1
    if flag > 10:
        break

於是我將賦值語句改爲淺複製fish_axis[flag] = temp_axis.copy(),這然fish_axis[flag]的地址和temp_axis的地址就不一樣了。

解決了這個問題之後,我又運行了一遍,結果又又又報錯了再見

Traceback (most recent call last):
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\example\test_37_1.py", line 125, in <module>
    for i in fish_axis:
RuntimeError: dictionary changed size during iteration

錯誤信息顯示錯誤在for i in fish_axis:語句中,錯誤類型爲RuntimeError,在反反覆覆前前後後看了幾遍之後還是看不出來有什麼地方不對,只好求助萬能的度娘,在大佬的指導下終於發現了錯誤。

for i in fish_axis:
    if fish_axis[i] == tort_axis:
        print('fish%s被喫掉' % i)
        fish_axis.pop(i)
        print('烏龜回覆20點體力')
        energy += 20

上面這種寫法在python2中是可與運行的,但是在python3中就會報錯,因爲在python3中keys()返回的是dict_keys而不是list此如果想遍歷的同時刪除字典中的元素應該改寫爲:

for i in list(fish_axis.keys()):
    if fish_axis[i] == tort_axis:
        print('fish%s被喫掉' % i)
        fish_axis.pop(i)
        print('烏龜回覆20點體力')
        energy += 20

這個問題解決之後終於可以運行了,下面附上完整的程序。

import random as r
class Tortoise:
    step = 2 # 步長
    axis = [0, 0] # 初始化座標
    area = [0, 0] # 初始化遊戲場景大小
    def __init__(self, a, b): # 定義遊戲場景大小
        self.area[0] = a
        self.area[1] = b
    def start_axis(self, x = 0, y = 0): # 設定烏龜開始的座標
        self.axis[0] = x
        self.axis[1] = y
        return self.axis
    def move(self): # 烏龜的移動
        while True:
            temp_x = r.randint(-self.step, self.step)
            temp_y = r.randint(-self.step, self.step)
            if temp_x == 0 and temp_y == 0:
                continue
            self.axis[0] = self.axis[0] + temp_x
            self.axis[1] = self.axis[1] + temp_y
            for i in range(0, 2): # 當移動到邊界時往反方向移動
                if self.axis[i] < 0: # 0 --> -2 = 0 --> 2
                    self.axis[i] = 0 - self.axis[i]
                if self.axis[i] > 10: # 10 --> 12 = 10 --> 8
                    self.axis[i] = 20 - self.axis[i]
            return self.axis
class Fish:
    step = 1 # 步長
    area = [0, 0] # 初始化座標
    axis = [0, 0] # 初始化遊戲場景大小
    def __init__(self, a, b): # 定義遊戲場景大小
        self.area[0] = a
        self.area[1] = b
    def start_axis(self): # 設定魚開始的座標
        self.axis[0] = r.randint(self.area[0], self.area[1])
        self.axis[1] = r.randint(self.area[0], self.area[1])
        return self.axis
    def move(self, axis): # 魚的移動
        self.axis = axis
        while True:
            temp_x = r.randint(-self.step, self.step)
            temp_y = r.randint(-self.step, self.step)
            if temp_x == 0 and temp_y == 0:
                continue
            self.axis[0] = self.axis[0] + temp_x
            self.axis[1] = self.axis[1] + temp_y
            for i in range(0, 2): # 當移動到邊界時往反方向移動
                if self.axis[i] < 0: # 0 --> -1 = 0 --> 1
                    self.axis[i] = 0 - self.axis[i]
                if self.axis[i] > 10: # 10 --> 11 = 10 --> 9
                    self.axis[i] = 20 - self.axis[i]
            return self.axis
# 遊戲開始
energy = 100
tort = Tortoise(1, 10)
tort_axis = tort.start_axis(1, 1) # 將烏龜放入場景內,設定初始座標爲(1,1)
print('-----------------------------')
print('烏龜的位置是:',tort_axis)
print('烏龜的體力:%d' % energy)
fish = Fish(1, 10)
fish_axis = {}
flag = 1
while True: # 將10條魚分別放入不同的座標中
    temp_axis = fish.start_axis()
    if flag == 1 and temp_axis != tort_axis:
        fish_axis.setdefault(flag, 0)
        fish_axis[flag] = temp_axis.copy()
        print('Fish%d的位置是:' % flag, fish_axis[flag])
        flag += 1
    if  flag > 1 and temp_axis != fish_axis[flag - 1] and temp_axis != tort_axis:
        fish_axis.setdefault(flag, 0)
        fish_axis[flag] = temp_axis.copy()
        print('Fish%d的位置是:' % flag, fish_axis[flag])
        flag += 1
    if flag > 10:
        break
print('----------遊戲開始-----------')
# 烏龜和小魚的移動
while True:    
    num = list(fish_axis.keys())
    length = len(num)
    for i in range(0, length): # 小魚的移動
        flag = 0
        while True:
            temp_axis = fish.move(fish_axis[num[i]])
            if i == 0:
                fish_axis[num[i]] = temp_axis.copy()
                print('fish%d的位置是:' % num[i], fish_axis[num[i]])
                flag = 1
            elif temp_axis != fish_axis[num[i - 1]]:
                # 字典中的前一項而不是i-1
                fish_axis[num[i]] = temp_axis.copy()
                print('fish%d的位置是:' % num[i], fish_axis[num[i]])
                flag = 1
            if flag == 1:
                break
    tort_axis = tort.move() # 烏龜的移動
    print('烏龜的位置是:',tort_axis)
    energy -= 1
    #-------------------------
    # 判斷小魚是否被烏龜喫掉
    for i in num:
        if fish_axis[i] == tort_axis:
            print('fish%s被喫掉' % i)
            fish_axis.pop(i)
            print('烏龜回覆20點體力')
            energy += 20
    print('烏龜的體力:%d' % energy)
    #-------------------------
    print('-----------------------------')
    if fish_axis == {}:
        print('烏龜獲勝')
        break
    elif energy == 0:
        print('小魚獲勝')
        break


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