pythonでオセロ(4×4)を作る方法のコード
こちらのページでは「pythonでオセロ(4×4)を作る方法」のコードを載せています。
アルゴリズムや解説を読みたい方はこちらへ。
pythonのコード
import numpy as np
import random
# 黒または白石が置かれている座標を返す
# 引数は置かれている石(list)
def stone_location(stone):
stone_list = []
for i in range(4):
for j in range(4):
if(field[(i, j)] == stone):
stone_list.append((i, j))
return stone_list
# 引数のoffset範囲内に対する
# 空マスの座標とoffsetの組み合わせを返す(dic)
def empty_location(stone_list):
emp = {}
for x, y in stone_list:
for i in offset_x:
for j in offset_y:
p = (x+i, y+j)
if((p[0] <= 3) and (p[0] >= 0) and (p[1] <= 3) and (p[1] >= 0) ):
if((field[p] == EMPTY) and not(p in emp)):
emp[p] = []
emp[p].append((i, j))
elif((field[p] == EMPTY) and (p in emp)):
emp[p].append((i, j))
else:
pass
else:
pass
return emp
# 黒石の手番
# 黒石を置く座標とoffsetを返す
def black_turn():
#白石が置かれている場所のリスト
white_stone = stone_location(WHITE)
# 空マスの座標を返す
emp = empty_location(white_stone)
# 黒石が置ける座標を返す
black_possible = []
black_dic = {}
for kx, ky in emp.keys():
#print("({0}, {1})".format(kx, ky))
for vx, vy in emp[kx, ky]:
addx = vx*(-1)
addy = vy*(-1)
px = kx+(vx*(-1))
py = ky+(vy*(-1))
p = (px, py)
while((px >=0 and px <= 3) and (py >= 0 and py <= 3)):
#print(p, end="")
if(field[p] == WHITE):
#print("WHITE")
pass
elif(field[p] == BLACK):
if(not((kx, ky) in black_dic) and not((kx, ky) in black_possible)):
black_possible.append((kx, ky))
black_dic[(kx, ky)] = [(addx, addy)]
elif(((kx, ky) in black_dic) and ((kx, ky) in black_possible)):
black_dic[(kx, ky)].append((addx, addy))
#print("BLACK")
break
else:
#print("EMPTY")
break
px = px + addx
py = py + addy
p = (px, py)
#print("({0}, {1})".format(kx+(vx*(-1)), ky+(vy*(-1))))
#print("")
# black_possibleから1つ選出する
if(len(black_possible) == 0):
return (-1, -1), [(0, 0)]
r = random.randrange(len(black_possible))
return black_possible[r], black_dic[black_possible[r]]
# 白石の手番
# 白石を置く座標とoffsetを返す
def white_turn():
#黒石が置かれている場所のリスト
black_stone = stone_location(BLACK)
# 空マスの座標を返す
emp = empty_location(black_stone)
# 白石が置ける座標を返す
white_possible = []
white_dic = {}
for kx, ky in emp.keys():
#print("({0}, {1})".format(kx, ky))
for vx, vy in emp[kx, ky]:
addx = vx*(-1)
addy = vy*(-1)
px = kx+(vx*(-1))
py = ky+(vy*(-1))
p = (px, py)
while((px >=0 and px <= 3) and (py >= 0 and py <= 3)):
#print(p, end="")
if(field[p] == WHITE):
if(not((kx, ky) in white_dic) and not((kx, ky) in white_possible)):
white_possible.append((kx, ky))
white_dic[(kx, ky)] = [(addx, addy)]
elif(((kx, ky) in white_dic) and ((kx, ky) in white_possible)):
white_dic[(kx, ky)].append((addx, addy))
#print("WHITE")
break
elif(field[p] == BLACK):
#print("BLACK")
pass
else:
#print("EMPTY")
break
px = px + addx
py = py + addy
p = (px, py)
#print("({0}, {1})".format(kx+(vx*(-1)), ky+(vy*(-1))))
#print("")
# black_possibleから1つ選出する
if(len(white_possible) == 0):
return (-1, -1), [(0, 0)]
r = random.randrange(len(white_possible))
return white_possible[r], white_dic[white_possible[r]]
# 盤面を更新する
# 更新されたfieldを返す
def update_field(TURN, point, offset_list):
# 石を更新する座標を返す
px = point[0]
py = point[1]
update_possible = []
update_possible.append(point)
for addx, addy in offset_list:
vx = px
vy = py
value = point
while((vx >=0 and vx <= 3) and (vy >= 0 and vy <= 3)):
p = field[value]
if((p == TURN) or (p == EMPTY) and not(value in update_possible)):
break
elif((p != TURN) and (p != EMPTY) and not(value in update_possible)):
update_possible.append(value)
else:
pass
vx = vx + addx
vy = vy + addy
value = (vx, vy)
for i in update_possible:
field[i] = TURN
return field
# アドレスから座標に変換
# 座標を返す
def address2point(address):
for i in range(0, 4):
for j in range(0, 4):
if(field_address[(i, j)] == address and field[(i, j)] == 0):
return (i, j)
return (-1, -1)
# 座標から石をひっくり返す方向を取得
# offsetを返す
# しかし、empty_locationと合わせるためひっくり返す石からみたoffset
def point2offset(point, TURN):
#print("TURN", TURN)
px = point[0]
py = point[1]
p2o_list = []
for i in offset_x:
for j in offset_y:
vx = px + i
vy = py + j
p = (vx, vy)
if((p[0] <= 3) and (p[0] >= 0) and (p[1] <= 3) and (p[1] >= 0) and (field[p] != TURN) and (field[p] != EMPTY)):
vx = vx + i
vy = vy + j
p = (vx, vy)
while((p[0] <= 3) and (p[0] >= 0) and (p[1] <= 3) and (p[1] >= 0)):
if(field[p] != TURN and field[p] != EMPTY):
#print(" not TURN and not EMPTY")
pass
elif(field[p] == TURN and field[p] != EMPTY):
#print("TURN")
p2o_list.append((i, j))
break
elif(field[p] != TURN and field[p] == EMPTY):
#print("EMPTY")
break
vx = vx + i
vy = vy + j
p = (vx, vy)
return p2o_list
# 入力した手が有効な手であるか判断
# True or Falseを返す
def address_check(point, TURN):
#TURNと反対の石が置かれている場所のリスト
bw_stone = stone_location(3-TURN)
# 空マスの座標を返す
emp = empty_location(bw_stone)
# TURNが置ける座標を返す
stone_possible = []
stone_dic = {}
for kx, ky in emp.keys():
for vx, vy in emp[kx, ky]:
addx = vx*(-1)
addy = vy*(-1)
px = kx+(vx*(-1))
py = ky+(vy*(-1))
p = (px, py)
while((px >=0 and px <= 3) and (py >= 0 and py <= 3)):
if(field[p] != TURN):
pass
elif(field[p] == TURN):
if(not((kx, ky) in stone_dic) and not((kx, ky) in stone_possible)):
stone_possible.append((kx, ky))
stone_dic[(kx, ky)] = [(addx, addy)]
elif(((kx, ky) in stone_dic) and ((kx, ky) in stone_possible)):
stone_dic[(kx, ky)].append((addx, addy))
break
else:
break
px = px + addx
py = py + addy
p = (px, py)
if(point in stone_possible):
return True
return False
def othello16():
""" define """
# 4*4のオセロ
# 空白=0、 黒=1、 白=2
global EMPTY
EMPTY = 0
global BLACK
BLACK = 1
global WHITE
WHITE = 2
global field
field = np.array([[0,0,0,0],
[0,2,1,0],
[0,1,2,0],
[0,0,0,0]])
global field_address
# a, b, c, d
field_address = np.array([["a1", "b1", "c1", "d1"], # 1
["a2", "b2", "c2", "d2"], # 2
["a3", "b3", "c3", "d3"], # 3
["a4", "b4", "c4", "d4"]]) # 4
global offset_x
offset_x = [-1, 0, 1]
global offset_y
offset_y = [-1, 0, 1]
""" program """
print("先手:BLACK (1)")
print("後手:WHITE (2)")
print("空欄:EMPTY (0)")
Player = input("先手か後手を選んでください:")
if(Player == "BLACK"):
Player = BLACK
Computer = WHITE
TURN = Player
elif(Player == "WHITE"):
Player = WHITE
Computer = BLACK
TURN = Computer
else:
print("error : Please write your turn.(BLACK or WHITE)")
return field
print(field)
print(field_address)
num = 0
before_field = field
after_field = field
while(num == 0):
print("") # 改行
# 黒の手番
if(TURN == BLACK):
point, offset_list = black_turn()
if(TURN == Player):
print("TURN : you")
if(point == (-1, -1)):
print("pass")
print(field)
num = np.min(field)
TURN = WHITE
if((before_field == after_field).all()):
break
before_field = after_field
continue
address = input("石を置く場所を指定してください : ")
point = address2point(address)
offset_list = point2offset(point, Player)
if(not(address_check(point, TURN))):
print("「{0}」は無効な手です。".format(address))
print(field)
break
else:
print("TURN : computer")
if((point == (-1, -1) and TURN == Player)):
print("「{0}」は無効な手です。".format(address))
print(field)
break
if((point == (-1, -1) and TURN == Computer)):
print("pass")
print(field)
num = np.min(field)
TURN = WHITE
if((before_field == after_field).all()):
print("盤面上に打てるマスが無いため対局を終了します。")
break
before_field = after_field
continue
field = update_field(TURN, point, offset_list)
#before_field = after_field
after_field = field
TURN = WHITE
# 白の手番
elif(TURN == WHITE):
point, offset_list = white_turn()
if(TURN == Player):
print("TURN : you")
if(point == (-1, -1)):
print("pass")
print(field)
num = np.min(field)
TURN = BLACK
if((before_field == after_field).all()):
break
before_field = after_field
continue
address = input("石を置く場所を指定してください : ")
point = address2point(address)
offset_list = point2offset(point, Player)
if(not(address_check(point, TURN))):
print("「{0}」は無効な手です。".format(address))
print(field)
break
else:
print("computer")
if((point == (-1, -1) and TURN == Player)):
print("「{0}」は無効な手です。".format(address))
print(field)
break
if((point == (-1, -1) and TURN == Computer)):
print("pass")
print(field)
num = np.min(field)
TURN = BLACK
if((before_field == after_field).all()):
print("盤面上に打てるマスが無いため対局を終了します。")
break
before_field = after_field
continue
field = update_field(TURN, point, offset_list)
#before_field = after_field
after_field = field
TURN = BLACK
else:
print("error : TURN is not BLACK and WHITE")
break
print(field)
num = np.min(field)
return field
if __name__ == '__main__':
field = othello16()
black_stone = 0
white_stone = 0
for i in range(4):
for j in range(4):
stone = field[(i, j)]
if(stone == 1):
black_stone += 1
elif(stone == 2):
white_stone += 1
else:
pass
winner = ""
if(black_stone < white_stone):
winner = "後手(白石)"
elif(black_stone > white_stone):
winner = "先手(黒石)"
else:
winner = ""
print("")
print("===================")
print("結果発表")
print("黒石:{0}石".format(black_stone))
print("白石:{0}石".format(white_stone))
print("")
print("よって、勝者は「{0}」です。".format(winner))
スポンサードサーチ