色ブロックを表示する

色ブロックを表示する

次の「color.py」「main.py」ファイルをコーディングして「main.py」を「▷」で実行し、タイトル画像をクリックすると図4のように色ブロックが現れます。

図4:色ブロック

Colorクラスを実装する

新たにcolor.pyファイルを新規作成します。color.pyファイルでは色ブロック1個ずつの「Color」クラスを実装します。まずはコンストラクタだけ実装します。

・サンプルコード「color.py」ファイル

import random
# 色ブロック1つ分のクラス
class Color():
  image_id = -1
  def __init__(self,color,width,height):
    self.x = random.randint(100,width-100)
    self.y = random.randint(100,height-100)
    self.dx = random.choice([-3,-2,-1,1,2,3])
    self.dy = random.choice([-3,-2,-1,1,2,3])
    self.color = color

【サンプルコードの解説】
乱数のrandomモジュールを読み込みます。
ユニークな(一意の)image_idプロパティを宣言します。ただしデフォルトではユニークではない-1です。
コンストラクタで色ブロック1つのランダムな(x,y)座標プロパティ、増分(Delta)のランダムな(dx,dy)プロパティ、色番号のcolorプロパティをセットします。

メインコードをコーディングする

赤緑青の色ブロック画像を読み込んで表示します。色ブロックは画像ですが、ラベルではなく1つのキャンバスの中に複数表示します。まだ色ブロックは移動しませんが、クリックして背景色に色を混ぜて真っ白になったらステージクリアです(図5)。

図5:ステージクリア

・サンプルコード「main.py」ファイル

import tkinter as tk
import random
from color import Color
(中略)
# ゲームクラス
class Game():
  # コンストラクタ
  def __init__(self):
    self.stage = 2
  # タイトル表示
  def title(self):
(中略)
  # ゲーム開始
  def on_start(self,event):
    self.label.destroy()
    # 画像読み込み
    files = ["images/0.png", "images/1.png", "images/2.png"]
    self.colors = []
    # PhotoImage保持
    self.images = []
    # CanvasアイテムID
    self.image_ids = []  
    self.canvas = tk.Canvas(root, bg="white")
    self.canvas.pack(fill="both", expand=True)
    for i in range(self.stage*3):
      self.colors.append(Color(i%3,width,height))
      self.img = tk.PhotoImage(file=files[i%3])
      self.images.append(self.img)
      self.colors[i].image_id = self.canvas.create_image(self.colors[i].x, self.colors[i].y, image=self.img)
      self.image_ids.append(self.colors[i].image_id)
      self.canvas.tag_bind(self.colors[i].image_id,"<Button-1>", self.on_click)
    self.rgb = [0,0,0]
    num = self.stage-1
    while self.rgb[0] == self.rgb[1]:
      self.rgb = [random.randint(0,num),random.randint(0,num),random.randint(0,num)]
    self.bg_color()
    self.update()
  # 背景色
  def bg_color(self):
(中略)
    if self.rgb[0] == self.rgb[1] and self.rgb[0] == self.rgb[2]:
      self.stage_clear()
  # ゲームのメインループ
  def update(self):
    if not self.canvas.winfo_exists():
      return
  # 色ブロックのクリック
  def on_click(self,event):
    item_id = event.widget.find_withtag("current")
    if item_id:
      for c in self.colors:
        if c.image_id == item_id[0]:
          self.rgb[c.color] += 1
          c.x += c.dx*width
          break
    self.bg_color()
  # ステージクリア
  def stage_clear(self):
    self.canvas.destroy()
    self.stage += 1
    img = tk.PhotoImage(file="images/StageClear.png")
    self.label = tk.Label(root, image=img)
    self.label.pack(expand=True)
    self.label.image = img
    self.label.bind("<Button-1>", self.on_start)
# ゲームクラスのインスタンス生成
game = Game()
# ゲームクラスのタイトル画面へ
game.title()
# tkinterのメインループ
root.mainloop()

【サンプルコードの解説】
色ブロックごとにColorクラスのインスタンスを生成し、colorsプロパティ(配列)に追加します。
PhotoImageクラスで色ブロック画像を読み込み、参照をimagesプロパティに保持しておくことで画像が表示されなくなるのを防ぎます。
image_idプロパティで画像のユニークなイメージID(整数)を取得します。
イメージIDの画像がクリックされたら「on_click」メソッドを呼び出します。
bg_colorメソッドではrgb配列の3要素がすべて同じ値になった場合、真っ白になったと判定してステージクリアとします。
on_clickメソッドではクリックされたブロックのアイテム番号を取得し、colors配列からimage_idが一致する要素を特定します。該当する色の値をインクリメントして背景色に反映させます。あわせて、クリックされたブロックは画面外へ移動させ非表示にします。
stage_clearメソッドはtitleメソッドと同様にラベルへステージクリア画像を表示します。画像をクリックするとメインゲームが再開されます。

色ブロックを移動しゲームを完成させる

色ブロックを移動させるようにし、色ブロックが1個もなくなったらゲームオーバーです(図6)。これでゲームは完成です。サウンドがないのは寂しかったでしょうか?

図6:ゲームオーバー

色ブロックの移動

Colorクラスのupdateメソッドで色ブロックの座標を増分だけ加算し、画面外に出たら戻り値として0を返します。それ以外は1を返します。

・サンプルコード「color.py」ファイル

import random
# 色ブロック1つ分のクラス
class Color():
  image_id = -1
  def __init__(self,color,width,height):
(中略)
  # 毎フレーム更新
  def update(self,width,height):
    self.x += self.dx
    self.y += self.dy
    if self.x < -50 or self.y < -50 or self.x > width+50 or self.y > height+50:
      return 0
    return 1

毎フレームupdateメソッドを呼び出す

毎フレームupdateをメインループで呼び出すには、afterメソッドで50ミリ秒後に自分自身(updateメソッド)を再度呼び出すだけです。

・サンプルコード「main.py」ファイル

(前略)
# ゲームクラス
class Game():
  # コンストラクタ
  def __init__(self):
    self.stage = 2
  # タイトル表示
  def title(self):
(中略)
  # ゲーム開始
  def on_start(self,event):
(中略)
  # 背景色
  def bg_color(self):
(中略)
  # ゲームのメインループ
  def update(self):
    if not self.canvas.winfo_exists():
      return
    flg = 0
    for i in range(len(self.image_ids)):
      flg += self.colors[i].update(width,height)
      self.canvas.coords(self.image_ids[i], self.colors[i].x, self.colors[i].y)
    if flg == 0:
      self.game_over()
    else:
      # 約20FPS
      root.after(50, self.update)
  # 色ブロックのクリック
  def on_click(self,event):
(中略)
  # ステージクリア
  def stage_clear(self):
(中略)
  # ゲームオーバー
  def game_over(self):
    self.canvas.destroy()
    img = tk.PhotoImage(file="images/GameOver.png")
    self.label = tk.Label(root, image=img)
    self.label.pack(expand=True)
    self.label.image = img
    self.label.bind("<Button-1>", self.on_title)
  # タイトル画像クリック時
  def on_title(self,event):
    self.label.destroy()
    self.title()
# ゲームクラスのインスタンス生成
game = Game()
# ゲームクラスのタイトル画面へ
game.title()
# tkinterのメインループ
root.mainloop()

【サンプルコードの解説】
ゲームのメインループのupdateメソッドでColorクラスのupdateを呼び出して移動し、画面外に出ていなければ戻り値でflg変数に加算して0より大きくなります。
coordsメソッドでイメージIDの色ブロックをその位置に配置します。
flgが0なら全ての色ブロックが画面外に出ているのでゲームオーバー処理し、そうでなければupdateメソッドをループします。
「game_over」メソッドではtitleメソッドと似たようなことをします。「GameOver.png」を表示し、それをクリックしたら「on_title」メソッドを呼び出し、ラベルを削除してタイトル画面に遷移します。

【コラム】携帯電話パソコン

スマホは電話番号で個人を特定して認証できるSMSなどがあります。そこでパソコンにも電話機能があれば? スマホアプリをパソコンで使えるAndroid PCが出るそうですが電話機能なしです。SIMが入れられるノートパソコンもありますがSMS的なことはできないようです。

おわりに

今回は2026年で最も人気のあるプログラミング言語の1つであるPythonでデスクトップのColorゲームをプログラミングしました。Pythonが使えたら様々な用途に使えるのでとても便利です。

人気記事トップ10

人気記事ランキングをもっと見る

企画広告も役立つ情報バッチリ! Sponsored

ClickHouse Cloudが実現した広告運用SaaS「ATOM」のデータ基盤革新、パフォーマンスを向上しながら、運用負荷とコストを削減 11月11日 6:20 AIで開発が加速する時代、品質保証はどう変わる? Tricentisが示すAIエージェント活用の実像 11月9日 6:45 悪用までの猶予が「1分」に迫るフロンティアAI時代に開発と本番を貫く脆弱性管理が必要 10月29日 8:30 欧州CRA対応とSBOM運用。AI生成コードのOSS混入問題の対策とは ――スニペット単位で検出する「FossID」「Insignary Clarity」によるSBOM運用 9月16日 6:40 PostgreSQLからTiDBへ、稼働中SaaSで進める段階的DB移行の実践と再設計への展望 9月7日 6:30 機能安全開発におけるGoogleTestの活用を支援!「Parasoft C/C++test CT」で実現する効率化&AI連携 4月14日 6:30 【CNDW2025】Grafanaが明かす「オブザーバビリティの哲学」ー最小限の労力で実用的なインサイトを得るには 1月23日 6:30 【CNDW2025】プロダクト急増に備える基盤刷新 ーウェルスナビがECSからEKSへの移行で得た知見とは 1月15日 6:30 【CNDW2025】250環境を5人で運用、構築時間は30分に ーKINTOテクノロジーズが語るインフラ基盤組織の作り方 2025年12月18日 6:30 新たな自動化で熱視線! AIエージェントの「推論能力」を支える2つのコンポーネントとは? 2025年11月28日 6:30