今回は、○や×、盤面などの見た目を色々と変えてみましょう。マルバツゲームプログラムが動くために必須というわけではありませんので、興味を持った部分だけ実装してみてください。
前回:Pythonでマルバツゲームをつくろう #3 人対人編
前回までのコード
from IPython.display import clear_output
current_player = "○" # 現在のプレイヤー
turn = 0 # 今何ターン目か
board = [ # 盤面(リスト)
"𝟶", "𝟷", "𝟸",
"𝟹", "𝟺", "𝟻",
"𝟼", "𝟽", "𝟾"
]
print(f" {board[0]} │ {board[1]} │ {board[2]} ") # 最初の盤面を表示
print("───┼───┼───")
print(f" {board[3]} │ {board[4]} │ {board[5]} ")
print("───┼───┼───")
print(f" {board[6]} │ {board[7]} │ {board[8]} ")
while turn < 9:
turn += 1 # ターンを進める
print(f"次は {current_player} の番です")
clear_output(wait=True) # 新たに出力され次第、表示済みの出力を消去
while True: # ユーザの入力を受け取る
try:
index = int(input(f"{current_player} の手 : "))
if (0 <= index <= 8) and (board[index] != "○" and board[index] != "×"):
break
else:
print("𝟶 ~ 𝟾 の空いているマスを選んでください")
except ValueError:
print("整数を入力してください")
print(f" {board[0]} │ {board[1]} │ {board[2]} ")
print("───┼───┼───")
print(f" {board[3]} │ {board[4]} │ {board[5]} ")
print("───┼───┼───")
print(f" {board[6]} │ {board[7]} │ {board[8]} ")
clear_output(wait=True)
board[index] = current_player # 入力手を盤面に適用
print(f" {board[0]} │ {board[1]} │ {board[2]} ") # 現在の盤面を表示
print("───┼───┼───")
print(f" {board[3]} │ {board[4]} │ {board[5]} ")
print("───┼───┼───")
print(f" {board[6]} │ {board[7]} │ {board[8]} ")
# 勝利判定
if (board[0] == board[1] == board[2] == current_player) or \
(board[3] == board[4] == board[5] == current_player) or \
(board[6] == board[7] == board[8] == current_player) or \
(board[0] == board[3] == board[6] == current_player) or \
(board[1] == board[4] == board[7] == current_player) or \
(board[2] == board[5] == board[8] == current_player) or \
(board[0] == board[4] == board[8] == current_player) or \
(board[2] == board[4] == board[6] == current_player):
print(f"勝者: {current_player}")
break
current_player = "○" if current_player == "×" else "×" # 手番交代
else:
print("引き分け") # 引き分け
1. 数字のフォントを変えてみる
- もともと、
board
は
board = [
"𝟶", "𝟷", "𝟸",
"𝟹", "𝟺", "𝟻",
"𝟼", "𝟽", "𝟾"
]
このようになっていました。この数字を一つ一つ変えるのは手間なので、フォントを変える前に、コードの書き方を変えてみましょう。実は上と同じことを
board = list("𝟶𝟷𝟸𝟹𝟺𝟻𝟼𝟽𝟾𝟿")
このようにlist
関数により文字列をリストに変換する、という書き方で表現することもできたのです。これで、数字のフォントデザインを変えたいときに簡単に変えることができるようになりました。
board = list("₀₁₂₃₄₅₆₇₈₉") # 小さい文字
board = list("0123456789") # 普通の数字
- 他の数字のフォントは以下のサイトに載っています。ただし、同じ一文字でもサイズは必ずしも統一されていないので、整った表示になるとは限りません。色々試してみてください。
ここまでのコード
from IPython.display import clear_output
current_player = "○" # 現在のプレイヤー
turn = 0 # 今何ターン目か
board = list("₀₁₂₃₄₅₆₇₈₉") # 盤面(リスト)
print(f" {board[0]} │ {board[1]} │ {board[2]} ") # 最初の盤面を表示
print("───┼───┼───")
print(f" {board[3]} │ {board[4]} │ {board[5]} ")
print("───┼───┼───")
print(f" {board[6]} │ {board[7]} │ {board[8]} ")
while turn < 9:
turn += 1 # ターンを進める
print(f"次は {current_player} の番です")
clear_output(wait=True) # 新たに出力され次第、表示済みの出力を消去
while True: # ユーザの入力を受け取る
try:
index = int(input(f"{current_player} の手 : "))
if (0 <= index <= 8) and (board[index] != "○" and board[index] != "×"):
break
else:
print("𝟶 ~ 𝟾 の空いているマスを選んでください")
except ValueError:
print("整数を入力してください")
print(f" {board[0]} │ {board[1]} │ {board[2]} ")
print("───┼───┼───")
print(f" {board[3]} │ {board[4]} │ {board[5]} ")
print("───┼───┼───")
print(f" {board[6]} │ {board[7]} │ {board[8]} ")
clear_output(wait=True)
board[index] = current_player # 入力手を盤面に適用
print(f" {board[0]} │ {board[1]} │ {board[2]} ") # 現在の盤面を表示
print("───┼───┼───")
print(f" {board[3]} │ {board[4]} │ {board[5]} ")
print("───┼───┼───")
print(f" {board[6]} │ {board[7]} │ {board[8]} ")
# 勝利判定
if (board[0] == board[1] == board[2] == current_player) or \
(board[3] == board[4] == board[5] == current_player) or \
(board[6] == board[7] == board[8] == current_player) or \
(board[0] == board[3] == board[6] == current_player) or \
(board[1] == board[4] == board[7] == current_player) or \
(board[2] == board[5] == board[8] == current_player) or \
(board[0] == board[4] == board[8] == current_player) or \
(board[2] == board[4] == board[6] == current_player):
print(f"勝者: {current_player}")
break
current_player = "○" if current_player == "×" else "×" # 手番交代
else:
print("引き分け") # 引き分け
2. ○×の記号を変えてみる
- 同じように、○×も変えやすくしましょう。現時点のコードだと、○や×が6箇所にあります。
current_player = "○" # ココ
(省略)
while
(省略)
while
try
if board[index] != "○" and board[index] != "×": # ココとココ
(省略)
(省略)
current_player = "○" if current_player == "×" else "×" # ココとココとココ
(省略)
- 毎回6箇所もコピー&ペーストする手間を省くために、定数を利用します。
- 定数というのは、一度設定したらコードの途中で中身が変わったりしない変数のことです。大文字で書くことが慣習になっています。
O = "○" # 定数
X = "×" # 定数
current_player = O # ココ
(省略)
while
(省略)
while
try
if board[index] != O and board[index] != X: # ココとココ
(省略)
(省略)
current_player = O if current_player == X else X # ココとココとココ
(省略)
これでO
とX
を使って簡単に盤面をカスタマイズすることができるようになりました。
これも、文字のサイズによっては盤面が思ったように表示されないこともあるかもしれません。下のサイトにいろんな特殊文字が載っていますので、色々試してみてください。
https://appllio.com/Instagram-special-character
ここまでのコード
from IPython.display import clear_output
O = "☺︎"
X = "☻︎"
current_player = O # 現在のプレイヤー
turn = 0 # 今何ターン目か
board = list("₀₁₂₃₄₅₆₇₈₉") # 盤面(リスト)
print(f" {board[0]} │ {board[1]} │ {board[2]} ") # 最初の盤面を表示
print("───┼───┼───")
print(f" {board[3]} │ {board[4]} │ {board[5]} ")
print("───┼───┼───")
print(f" {board[6]} │ {board[7]} │ {board[8]} ")
while turn < 9:
turn += 1 # ターンを進める
print(f"次は {current_player} の番です")
clear_output(wait=True) # 新たに出力され次第、表示済みの出力を消去
while True: # ユーザの入力を受け取る
try:
index = int(input(f"{current_player} の手 : "))
if (0 <= index <= 8) and (board[index] != O and board[index] != X):
break
else:
print("𝟶 ~ 𝟾 の空いているマスを選んでください")
except ValueError:
print("整数を入力してください")
print(f" {board[0]} │ {board[1]} │ {board[2]} ")
print("───┼───┼───")
print(f" {board[3]} │ {board[4]} │ {board[5]} ")
print("───┼───┼───")
print(f" {board[6]} │ {board[7]} │ {board[8]} ")
clear_output(wait=True)
board[index] = current_player # 入力手を盤面に適用
print(f" {board[0]} │ {board[1]} │ {board[2]} ") # 現在の盤面を表示
print("───┼───┼───")
print(f" {board[3]} │ {board[4]} │ {board[5]} ")
print("───┼───┼───")
print(f" {board[6]} │ {board[7]} │ {board[8]} ")
# 勝利判定
if (board[0] == board[1] == board[2] == current_player) or \
(board[3] == board[4] == board[5] == current_player) or \
(board[6] == board[7] == board[8] == current_player) or \
(board[0] == board[3] == board[6] == current_player) or \
(board[1] == board[4] == board[7] == current_player) or \
(board[2] == board[5] == board[8] == current_player) or \
(board[0] == board[4] == board[8] == current_player) or \
(board[2] == board[4] == board[6] == current_player):
print(f"勝者: {current_player}")
break
current_player = O if current_player == X else X # 手番交代
else:
print("引き分け") # 引き分け
3. 枠線のフォントを変えてみる
枠線のフォントもいろいろあります。
print(f" {board[0]} │ {board[1]} │ {board[2]} ")
print("───┼───┼───")
print(f" {board[3]} │ {board[4]} │ {board[5]} ")
print("───┼───┼───")
print(f" {board[6]} │ {board[7]} │ {board[8]} ")
この部分も、
print(f" {board[0]} ┃ {board[1]} ┃ {board[2]} ")
print("━━━╋━━━╋━━━")
print(f" {board[3]} ┃ {board[4]} ┃ {board[5]} ")
print("━━━╋━━━╋━━━")
print(f" {board[6]} ┃ {board[7]} ┃ {board[8]} ")
print(f" {board[0]} ║ {board[1]} ║ {board[2]} ")
print("═══╬═══╬═══")
print(f" {board[3]} ║ {board[4]} ║ {board[5]} ")
print("═══╬═══╬═══")
print(f" {board[6]} ║ {board[7]} ║ {board[8]} ")
このように表現することもできます。
- もしくは、枠線は
"│"
、"─"
、"┼"
の三つのパーツのみからなっているので、O
やX
と同じようにこれも
TATE = "│"
YOKO = "─"
CROSS = "┼"
などの定数として、
print(f" {board[0]} {TATE} {board[1]} {TATE} {board[2]} ")
print(YOKO + YOKO + YOKO + CROSS + YOKO + YOKO + YOKO + CROSS + YOKO + YOKO + YOKO)
print(f" {board[3]} {TATE} {board[4]} {TATE} {board[5]} ")
print(YOKO + YOKO + YOKO + CROSS + YOKO + YOKO + YOKO + CROSS + YOKO + YOKO + YOKO)
print(f" {board[6]} {TATE} {board[7]} {TATE} {board[8]} ")
このように表現することもできます。(…もっとスタイリッシュに書く方法があれば、よければコメントで教えてください(・・;))
TATE = "┃"
YOKO = "━"
CROSS = "╋"
TATE = "║"
YOKO = "═"
CROSS = "╬"
他のフォントはこちらのページにあります。
https://tkmj.ac-absolute.com/line.html
ここまでのコード
from IPython.display import clear_output
O = "☺︎"
X = "☻︎"
current_player = O # 現在のプレイヤー
turn = 0 # 今何ターン目か
board = list("₀₁₂₃₄₅₆₇₈₉") # 盤面(リスト)
print(f" {board[0]} ║ {board[1]} ║ {board[2]} ")
print("═══╬═══╬═══")
print(f" {board[3]} ║ {board[4]} ║ {board[5]} ")
print("═══╬═══╬═══")
print(f" {board[6]} ║ {board[7]} ║ {board[8]} ")
while turn < 9:
turn += 1 # ターンを進める
print(f"次は {current_player} の番です")
clear_output(wait=True) # 新たに出力され次第、表示済みの出力を消去
while True: # ユーザの入力を受け取る
try:
index = int(input(f"{current_player} の手 : "))
if (0 <= index <= 8) and (board[index] != O and board[index] != X):
break
else:
print("𝟶 ~ 𝟾 の空いているマスを選んでください")
except ValueError:
print("整数を入力してください")
print(f" {board[0]} ║ {board[1]} ║ {board[2]} ")
print("═══╬═══╬═══")
print(f" {board[3]} ║ {board[4]} ║ {board[5]} ")
print("═══╬═══╬═══")
print(f" {board[6]} ║ {board[7]} ║ {board[8]} ")
clear_output(wait=True)
board[index] = current_player # 入力手を盤面に適用
print(f" {board[0]} ║ {board[1]} ║ {board[2]} ")
print("═══╬═══╬═══")
print(f" {board[3]} ║ {board[4]} ║ {board[5]} ")
print("═══╬═══╬═══")
print(f" {board[6]} ║ {board[7]} ║ {board[8]} ")
# 勝利判定
if (board[0] == board[1] == board[2] == current_player) or \
(board[3] == board[4] == board[5] == current_player) or \
(board[6] == board[7] == board[8] == current_player) or \
(board[0] == board[3] == board[6] == current_player) or \
(board[1] == board[4] == board[7] == current_player) or \
(board[2] == board[5] == board[8] == current_player) or \
(board[0] == board[4] == board[8] == current_player) or \
(board[2] == board[4] == board[6] == current_player):
print(f"勝者: {current_player}")
break
current_player = O if current_player == X else X # 手番交代
else:
print("引き分け") # 引き分け
4. 文字の色を変えてみる
- これまで、いちいち全部手動で変更するのが手間だったので変数や定数という形で管理し、一括で変更していました。
- 同じ理由で、いちいち手動で文字の色を変えるのは手間なので、簡単に色を変えてくれる関数を作りましょう。
- 中学や高校の数学でも、y = 2xのような関数を習ったと思います。この関数とは一体何だったのかというと、要は自動販売機のようなものだったのです。自動販売機は、投入口にお金を入れると、取り出し口から商品が出てきます。同じように、y = 2xはxに3を代入したらyから6が、-2を代入したら-4が出てくる自動販売機だったのです。
- さて、今回欲しい自動販売機はというと、文字列を入れると色のついた文字列を返してくれる自動販売機です。具体的にまずは、文字列を代入したら赤い文字列に変えて返してくれる自動販売機を作ってみましょう。
def red(text):
new_text = "\033[31m" + text + "\033[0m"
return new_text
red
というのがこの自動販売機の名前(関数名)です。
- お金を入れる投入口は
text
と書かれている部分で、これを引数といいます。飲み物が出てくる取り出し口はnew_text
と書かれている部分で、これを戻り値と言います。
- 内部処理は
new_text = "\033[31m" + text + "\033[0m"
という部分です。何をしているかというと、"\033[31m"
で色付けの開始を、"\033[0m"
で色付けの終了をインタプリタに知らせているのです。
- 色付け開始部分のコードは色によって異なります。参考:🔰[python]print文で色をつけてみよう
- これで自動販売機が完成しましたから、次は使ってみましょう。
red("○")
- このように、関数名の後ろにカッコをつけて、その中に関数に渡したいものを書きます。print()やint()などの関数と同じですね。
さて、これで例えばred関数と同様にmagentaとcyanという関数を作って、
O = magenta("☺︎")
X = cyan("☻︎")
このように適用することで、以下のように色付きの文字が表示できるようになりました。
ここまでのコード
from IPython.display import clear_output
def magenta(text):
new_text = "\033[35m" + text + "\033[0m"
return new_text
def cyan(text):
new_text = "\033[36m" + text + "\033[0m"
return new_text
O = magenta("☺︎")
X = cyan("☻︎")
current_player = O # 現在のプレイヤー
turn = 0 # 今何ターン目か
board = list("₀₁₂₃₄₅₆₇₈₉") # 盤面(リスト)
print(f" {board[0]} ║ {board[1]} ║ {board[2]} ")
print("═══╬═══╬═══")
print(f" {board[3]} ║ {board[4]} ║ {board[5]} ")
print("═══╬═══╬═══")
print(f" {board[6]} ║ {board[7]} ║ {board[8]} ")
while turn < 9:
turn += 1 # ターンを進める
print(f"次は {current_player} の番です")
clear_output(wait=True) # 新たに出力され次第、表示済みの出力を消去
while True: # ユーザの入力を受け取る
try:
index = int(input(f"{current_player} の手 : "))
if (0 <= index <= 8) and (board[index] != O and board[index] != X):
break
else:
print("𝟶 ~ 𝟾 の空いているマスを選んでください")
except ValueError:
print("整数を入力してください")
print(f" {board[0]} ║ {board[1]} ║ {board[2]} ")
print("═══╬═══╬═══")
print(f" {board[3]} ║ {board[4]} ║ {board[5]} ")
print("═══╬═══╬═══")
print(f" {board[6]} ║ {board[7]} ║ {board[8]} ")
clear_output(wait=True)
board[index] = current_player # 入力手を盤面に適用
print(f" {board[0]} ║ {board[1]} ║ {board[2]} ")
print("═══╬═══╬═══")
print(f" {board[3]} ║ {board[4]} ║ {board[5]} ")
print("═══╬═══╬═══")
print(f" {board[6]} ║ {board[7]} ║ {board[8]} ")
# 勝利判定
if (board[0] == board[1] == board[2] == current_player) or \
(board[3] == board[4] == board[5] == current_player) or \
(board[6] == board[7] == board[8] == current_player) or \
(board[0] == board[3] == board[6] == current_player) or \
(board[1] == board[4] == board[7] == current_player) or \
(board[2] == board[5] == board[8] == current_player) or \
(board[0] == board[4] == board[8] == current_player) or \
(board[2] == board[4] == board[6] == current_player):
print(f"勝者: {current_player}")
break
current_player = O if current_player == X else X # 手番交代
else:
print("引き分け") # 引き分け