目次

第1章 盤面を作ろう

1-1. 完成イメージ

※これは仮イメージ

GUIで見栄えのいいものは後程作りましょう。基礎が無ければ作れませんから。

1-2. オセロの盤面をどう表現する?

オセロでは、盤面上のどこに駒が置かれているか等を管理する必要があります。

今回は、二次元配列を使って盤面を表現します。
配列の x行、y列、を盤面の X座標、Y座標 のマスの状態とする事で、「どこに何が置かれているか」を管理します。

配列

プログラムでは、大量のデータを扱う事があります。

例えばオセロでは、

といった情報を盤面全体について管理する必要があります。

このような「同じ種類のデータをまとめて管理する」ために使われるのが 配列 です。

Pythonでは、配列に近いものとして list を利用できます。

例えば以下のコードでは、数字を複数まとめて管理しています。

sample101.py
numbers = [10, 20, 30, 40]
 
print(numbers[0])
print(numbers[1])

実行結果:

10
20

[0][1] の数字を 添字(index) と呼びます。

Pythonでは添字は 0 から始まります。numbersの添字と値の関係は以下のようになります。

添字
0 10
1 20
2 30
3 40

オセロではさらに「縦」と「横」の情報を持つ必要があります。

そこで利用するのが 二次元配列 です。

sample102.py
board = [
    [0,0,0],
    [0,0,0],
    [0,0,0]
]

これは以下のようなイメージになります。

0 0 0
0 0 0
0 0 0

二次元配列では、

のように扱えます。

例えば:

sample103.py
board[1][2] = 5
 
print(board[1][2])

実行結果:

5

盤面を表現する配列

ここで作るオセロでは、二次元配列を使って、

を管理していきます。さっそく、まだ駒の置かれていない盤面を表現する二次元配列を定義してみましょう。

sample004.py
board = [
    [9,9,9,9,9,9,9,9,9,9],
    [9,0,0,0,0,0,0,0,0,9],
    [9,0,0,0,0,0,0,0,0,9],
    [9,0,0,0,0,0,0,0,0,9],
    [9,0,0,0,0,0,0,0,0,9],
    [9,0,0,0,0,0,0,0,0,9],
    [9,0,0,0,0,0,0,0,0,9],
    [9,0,0,0,0,0,0,0,0,9],
    [9,0,0,0,0,0,0,0,0,9],
    [9,9,9,9,9,9,9,9,9,9],
]

盤外のマスが上下左右にあるので二次元配列は10×10のサイズで、盤外で囲まれた内側が8×8の、白黒の駒が置かれる面となります。

マスの状態を以下としています。

しかし、この方法では 「この数字は何を意味しているのか」 が分かりにくくなります。

そこで利用するのが Enum (列挙型)です。

Enumを使うと、 値に意味のある名前を付けられます。

from enum import IntEnum
 
class Cells(IntEnum):
    BLANK = 0
    BLACK_CHIP = 1
    WHITE_CHIP = 2
    WALL  = 9

これにより、

board[x][y] = Cells.BLACK_CHIP

のように、 「意味のある名称」で操作できるようになりプログラムの可読性が上がります。

1-3. 盤面を表示する

単純にコンソールへテキストで表示させてみましょう。

sample005.py
from enum import IntEnum
 
class Cells(IntEnum):
    BLANK      = 0
    BLACK_CHIP = 1
    WHITE_CHIP = 2
    WALL       = 9
 
board = [
    [9,9,9,9,9,9,9,9,9,9],
    [9,0,0,0,0,0,0,0,0,9],
    [9,0,0,0,0,0,0,0,0,9],
    [9,0,0,0,0,0,0,0,0,9],
    [9,0,0,0,1,2,0,0,0,9],
    [9,0,0,0,2,1,0,0,0,9],
    [9,0,0,0,0,0,0,0,0,9],
    [9,0,0,0,0,0,0,0,0,9],
    [9,0,0,0,0,0,0,0,0,9],
    [9,9,9,9,9,9,9,9,9,9],
]
 
## Display game board
for y in range(0, 10):
    for x in range(0, 10):
        if board[x][y] == Cells.BLANK:
            print("・", end="")
 
        elif board[x][y] == Cells.BLACK_CHIP:
            print("●", end="")
 
        elif board[x][y] == Cells.WHITE_CHIP:
            print("○", end="")
 
        elif board[x][y] == Cells.WALL:
            print("■", end="")
    print()

range(0, 10) は開始の値をゼロ(0)として、10個の連続した値、つまり0~9の10個要素を持つ一次元配列を返します。
print()で文字列を表示すると改行されてしまうのですが end=“” を指定して改行を““に変更し改行を抑止しています。

sample006.py
from enum import IntEnum
 
class Cells(IntEnum):
    BLANK      = 0
    BLACK_CHIP = 1
    WHITE_CHIP = 2
    WALL       = 9
 
board = [
    [9,9,9,9,9,9,9,9,9,9],
    [9,0,0,0,0,0,0,0,0,9],
    [9,0,0,0,0,0,0,0,0,9],
    [9,0,0,0,0,0,0,0,0,9],
    [9,0,0,0,1,2,0,0,0,9],
    [9,0,0,0,2,1,0,0,0,9],
    [9,0,0,0,0,0,0,0,0,9],
    [9,0,0,0,0,0,0,0,0,9],
    [9,0,0,0,0,0,0,0,0,9],
    [9,9,9,9,9,9,9,9,9,9],
]
 
## Display game board
for y in [0,1,2,3,4,5,6,7,8,9]:        ## ← range(0, 10)と等価
    for x in [0,1,2,3,4,5,6,7,8,9]:    ## ← range(0, 10)と等価
        if board[x][y] == Cells.BLANK:
            print("・", end="")
 
        elif board[x][y] == Cells.BLACK_CHIP:
            print("●", end="")
 
        elif board[x][y] == Cells.WHITE_CHIP:
            print("○", end="")
 
        elif board[x][y] == Cells.WALL:
            print("■", end="")
    print()

この記述と等価です。

実行結果はこうなります。
今は二次元配列の内容をテキストで表示させているけど、GUIで作る時には Cells.xxx 毎に表示するグラフィクスを選択する感じになりますね。