質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.64%

NoneTypeエラーの解決法

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 138

shino_04

score 3

前提・実現したいこと

8月上旬より「10才からはじめるプログラミング図鑑 スクラッチ&Python超入門」という書籍を使って独学で勉強しています。この図書の最後の方に、Pythonを使って潜水艦ゲームを作ってみよう、というコードが書かれたページがあります。そのコードを書き写しているのですが、どうしてもNoneTypeというエラーが出てしまいます。
画像の部分がNoneTypeになっているのだと思いますが、どう解決すればよいのかがさっぱりわかりません…。

発生している問題・エラーメッセージ

score += collision()

TypeError: unsupported operand type(s) for +=: 'int' and 'NoneType'

該当のソースコード

#潜水艦ゲーム
"""ルールなど
・矢印キーを使って潜水艦を操作する
・水中の泡を割ると得点を得られる
・ゲーム時間は30s
・1000点獲得するとボーナスタイムが得られる
・時間切れとなればゲーム終了"""

#ステップ1
#ウィンドウを作る
from tkinter import *
HEIGHT = 500
WIDTH = 800#ウィンドウサイズ指定##500×800
window = Tk()
window.title('潜水艦ゲーム')
c = Canvas(window, width=WIDTH, height=HEIGHT, bg='darkblue')#背景色は深青色
c.pack()

#ステップ2
#簡易表示の潜水艦を作る
ship_id = c.create_polygon(5, 5, 5, 25, 30, 15, fill='red')#赤の三角形
ship_id2 = c.create_oval(0, 0, 30, 30, outline='red')#三角形の赤の外接円
SHIP_R = 15#潜水艦の半径##潜水艦の大きさとなる
MID_X = WIDTH / 2
MID_Y = HEIGHT / 2#中心座標(x,y)=(400,250)
c.move(ship_id, MID_X, MID_Y)
c.move(ship_id2, MID_X, MID_Y)#潜水艦を形作る図形二つを画面中央に置く

#ステップ3
#潜水艦を動かす
SHIP_SPD = 10#キーを動かしたとき10進む
def move_ship(event):
    if event.keysym == 'Up':
        c.move(ship_id, 0, -SHIP_SPD)
        c.move(ship_id2, 0, -SHIP_SPD)#↑で10上に進む
    elif event.keysym == 'Down':
        c.move(ship_id, 0, SHIP_SPD)
        c.move(ship_id2, 0, SHIP_SPD)#↓で10下に進む
    elif event.keysym == 'Left':
        c.move(ship_id, -SHIP_SPD, 0)
        c.move(ship_id2, -SHIP_SPD, 0)#←で10左に進む
    elif event.keysym == 'Right':
        c.move(ship_id, SHIP_SPD, 0)
        c.move(ship_id2, SHIP_SPD, 0)#→で10右に進む
c.bind_all('<Key>', move_ship)

#ステップ4
#泡を作る
from random import *
bub_id = list()#泡のid
bub_r = list()#泡の半径
bub_speed = list()#泡の速さ
MIN_BUB_R = 10#最小の泡の半径
MAX_BUB_R = 30#最大の泡の半径
MAX_BUB_SPD = 10#泡の最大速度
GAP = 100
def create_bubble():
    x = WIDTH + GAP#泡のx座標
    y = randint(0, HEIGHT)#y座標
    r = randint(MIN_BUB_R, MAX_BUB_R)#最小半径と最大半径の中でランダムの大きさの泡を生成
    id1 = c.create_oval(x - r, y - r, x + r, y + r, outline='white')#線色白の円を生成
    bub_id.append(id1)#泡のid
    bub_r.append(r)#泡の半径
    bub_speed.append(randint(1, MAX_BUB_SPD))#泡の速度をリストにセットした

#ステップ5
#泡を動かす
def move_bubbles():
    for i in range (len(bub_id)):#リストの中の泡の情報を順にみていく
        c.move(bub_id[i], -bub_speed[i], 0)#リストで指定されたスピードに合わせて泡を動かす

#ステップ7
#特定の泡がどこにあるのかを見つける関数を作る
def get_coords(id_num):
    pos = c.coords(id_num)
    x = (pos[0] + pos[2])/2#泡の中心のx座標
    y = (pos[1] + pos[3])/2#泡の中心のy座標
    return x, y

#ステップ8
#泡を割る方法
def del_bubble(i):
    del bub_r[i]
    del bub_speed[i]#半径と速度を記録するリストから泡を取り去る
    c.delete(bub_id[i])#キャンバスから泡を消す
    del bub_id[i]#idのリストから泡を消す
def clean_up_bubs():#ステップ9
    for i in range(len(bub_id)-1, -1, -1):#泡のリストの最後から先頭へと読み進める
        x,y = get_coords(bub_id[i])
        if x < -GAP:
            del_bubble(i)
from math import sqrt#ステップ11
def distance(id1, id2):
    x1, y1 = get_coords(id1)#1番目のものの位置を調べる
    x2, y2 = get_coords(id2)#2番目のものの位置を調べる
    return sqrt((x2 - x1)**2 + (y2 - y1)**2)#二つのものの距離を出す
def collision():#ステップ12##泡を割る
    points = 0#ポイントを一度集計
    for bub in range(len(bub_id)-1, -1, -1):
        if distance(ship_id2, bub_id[bub]) < (SHIP_R + bub_r[bub]):#潜水艦と泡がぶつかったか判定
            points += (bub_r[bub] + bub_speed[bub])#それぞれの泡のポイントを集計してpointsに加える
            del_bubble(bub)#泡を取り去る
        return points#今回のチェックでカウントされたポイントを返す

#ステップ6,10,13
from time import sleep, time#time関数から必要なものを呼び出す
BUB_CHANCE = 10
score = 0#ゲーム開始時のスコアを0にする
#メインのループ
while True:
    if randint(1, BUB_CHANCE) == 1:
        create_bubble()
    move_bubbles()
    clean_up_bubs()
    score += collision()
    print(score)
    window.update()
    sleep(0.01)

試したこと

何をすればよいのかが分からず、誤字脱字はないかくらいしかやっていません。詳しい知識等がまだ何もないため、かみ砕いて説明していただけると助かります…。
イメージ説明

補足情報(FW/ツールのバージョンなど)

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+2

collision関数のreturn文をfor文の中に書いてしまっているのが原因だと思います。
return文のインデントを1つ下げてみてください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/09/04 11:22

    !return文のインデントを下げたら解決しました!
    スペルのみを気にしてそこは気にかけていなかったです…。ありがとうございます!!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.64%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る