pythonでオセロ(4×4)を作る方法 応用編!のコード
このページでは「pythonでオセロ(4×4)を作る方法 応用編!」のコードを載せています。
pythonのコード
""" othello16-pygame.py Copyright 2019 niwakoma """
import sys
import pygame
import random
from math import floor
import numpy as np
from pygame.locals import QUIT, MOUSEBUTTONDOWN
import copy
pygame.init() # pygameを初期化
SURFACE = pygame.display.set_mode((800, 600)) # windowのサイズを設定
FPSCLOCK = pygame.time.Clock()
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
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
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]]
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]]
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)
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
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 draw_stone(SURFACE, field):
for i in range(4):
for j in range(4):
stone = field[(i, j)]
ypos = 75 + (150 * i) - 60
xpos = 175 + (150 * j) - 60
if(stone == BLACK):
pygame.draw.ellipse(SURFACE, 0x000000, ((xpos, ypos), (120, 120)))
elif(stone == WHITE):
pygame.draw.ellipse(SURFACE, 0x000000, ((xpos, ypos), (120, 120)), 10)
elif(stone == EMPTY):
pass
else:
print("error")
sys.exti()
def show_result():
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
s = ""
winner = ""
if(black_stone < white_stone):
winner = "後手(白石)"
s = "勝者は{0}".format(winner)
elif(black_stone > white_stone):
winner = "先手(黒石)"
s = "勝者は{0}".format(winner)
elif(black_stone == white_stone):
s = "引き分け"
else:
winner = ""
print("")
print("===================")
print("結果発表")
print("黒石:{0}石".format(black_stone))
print("白石:{0}石".format(white_stone))
print("")
print("よって、{0}です。".format(s))
def player_turn():
sysfont_turn = pygame.font.SysFont(None, 24)
turn = sysfont_turn.render("TURN", True, (0, 0, 0))
turn_rect = turn.get_rect()
turn_rect.center = (50, 50)
sysfont_pt = pygame.font.SysFont(None, 24)
pt = sysfont_pt.render("Player", True, (0, 0, 0))
pt_rect = pt.get_rect()
pt_rect.center = (50, 100)
s = ""
if(Player == BLACK):
s = "BLACK"
elif(Player == WHITE):
s = "WHITE"
sysfont_color = pygame.font.SysFont(None, 24)
color = sysfont_color.render(s, True, (0, 0, 0))
color_rect = color.get_rect()
color_rect.center = (50, 150)
while(True):
address = ""
for event in pygame.event.get():
if(event.type == QUIT):
pygame.quit()
sys.exit()
if(event.type == MOUSEBUTTONDOWN and event.button == 1 and (event.pos[0] >= 100 and event.pos[0] < 700)):
xpos, ypos = floor((event.pos[0]-100)/150), floor(event.pos[1]/150)
address = field_address[(ypos, xpos)]
#print("({0}, {1}), address = {2}".format(ypos, xpos, address))
break
if(address in field_address):
break
# drawing line
SURFACE.fill((255, 255, 255))
weight = 10
for xpos in range(100, 701, 150):
pygame.draw.line(SURFACE, 0x000000, (xpos, 0), (xpos, 601), weight)
for ypos in range(0, 601, 150):
pygame.draw.line(SURFACE, 0x000000, (100, ypos), (701, ypos), weight)
# drawing stone
draw_stone(SURFACE, field)
SURFACE.blit(turn, turn_rect)
SURFACE.blit(pt, pt_rect)
SURFACE.blit(color, color_rect)
pygame.display.update()
FPSCLOCK.tick(3)
return address
# playerが画面のクリックするまで画面のを表示
def computer_turn():
sysfont_turn = pygame.font.SysFont(None, 24)
turn = sysfont_turn.render("TURN", True, (0, 0, 0))
turn_rect = turn.get_rect()
turn_rect.center = (50, 50)
sysfont_ct = pygame.font.SysFont(None, 24)
ct = sysfont_ct.render("Computer", True, (0, 0, 0))
ct_rect = ct.get_rect()
ct_rect.center = (50, 100)
s = ""
if(Computer == BLACK):
s = "BLACK"
elif(Computer == WHITE):
s = "WHITE"
sysfont_color = pygame.font.SysFont(None, 24)
color = sysfont_color.render(s, True, (0, 0, 0))
color_rect = color.get_rect()
color_rect.center = (50, 150)
x, y = -1, -1
while(True):
for event in pygame.event.get():
if(event.type == QUIT):
pygame.quit()
sys.exit()
if(event.type == MOUSEBUTTONDOWN and event.button == 1):
x, y = event.pos[0], event.pos[1]
break
# drawing line
SURFACE.fill((255, 255, 255))
weight = 10
for xpos in range(100, 701, 150):
pygame.draw.line(SURFACE, 0x000000, (xpos, 0), (xpos, 601), weight)
for ypos in range(0, 601, 150):
pygame.draw.line(SURFACE, 0x000000, (100, ypos), (701, ypos), weight)
# drawing stone
draw_stone(SURFACE, field)
SURFACE.blit(turn, turn_rect)
SURFACE.blit(ct, ct_rect)
SURFACE.blit(color, color_rect)
pygame.display.update()
FPSCLOCK.tick(3)
if(x >= 0 and y >= 0):
break
def main():
""" define """
# 4*4のオセロ
# 空白=0、 黒=1、 白=2
global EMPTY
EMPTY = 0
global BLACK
BLACK = 1
global WHITE
WHITE = 2
global TURN
TURN = 0
global Player
global Computer
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]
""" drawing title """
sysfont_title = pygame.font.SysFont(None, 80)
title = sysfont_title.render("othello(4×4).", True, (0, 0, 0))
title_rect = title.get_rect()
title_rect.center = (400, 200)
sysfont_start = pygame.font.SysFont(None, 60)
start = sysfont_start.render("start.", True, (255, 255, 255))
start_rect = start.get_rect()
start_rect.center = (400, 400)
while(True):
xpos = 0
ypos = 0
for event in pygame.event.get():
if(event.type == QUIT):
pygame.quit()
sys.exit()
if(event.type == MOUSEBUTTONDOWN and event.button == 1):
xpos, ypos = event.pos[0], event.pos[1]
if((xpos >= 325) and (xpos <= 475) and (ypos >= 375) and (ypos <= 425)):
break
SURFACE.fill((255, 255, 255))
SURFACE.blit(title, title_rect)
x = 150
y = 50
pygame.draw.rect(SURFACE, (0, 0, 0), ((400-(x/2), 400-(y/2)), (x, y)))
SURFACE.blit(start, start_rect)
pygame.display.update()
FPSCLOCK.tick(3)
""" drawing select first hand or late hand """
bxpos, bypos = 250, 350
wxpos, wypos = 550, 350
radius = 100
d = radius * 2 # diameter
sysfont = pygame.font.SysFont(None, 60)
select_black = sysfont.render("First hand.", True, (0, 0, 0))
select_black_rect = select_black.get_rect()
select_black_rect.center = (250, 200)
select_white = sysfont.render("Late hand.", True, (0, 0, 0))
select_white_rect = select_white.get_rect()
select_white_rect.center = (550, 200)
select_message = sysfont.render("Select First hand or Late hand.", True, (0, 0, 0))
select_message_rect = select_message.get_rect()
select_message_rect.center = (400, 100)
while(True):
xpos = 0
ypos = 0
for event in pygame.event.get():
if(event.type == QUIT):
pygame.quit()
sys.exit()
if(event.type == MOUSEBUTTONDOWN and event.button == 1):
xpos, ypos = event.pos[0], event.pos[1]
# calculate radius
br = np.sqrt((xpos - bxpos)**2 + (ypos - bypos)**2)
wr = np.sqrt((xpos - wxpos)**2 + (ypos - wypos)**2)
if(br <= radius):
Player = BLACK
Computer = WHITE
TURN = Player
break
elif(wr <= radius):
Player = WHITE
Computer = BLACK
TURN = Computer
break
# drawing background
SURFACE.fill((255, 255, 255))
# Rect
pygame.draw.ellipse(SURFACE, (0, 0, 0), ((bxpos-100, bypos-100), (d, d)))
pygame.draw.ellipse(SURFACE, (0, 0, 0), ((wxpos-100, wypos-100), (d, d)), 10)
# Font
SURFACE.blit(select_black, select_black_rect)
SURFACE.blit(select_white, select_white_rect)
SURFACE.blit(select_message, select_message_rect)
pygame.display.update()
FPSCLOCK.tick(3)
num = 0
before_field = copy.copy(field)
after_field = copy.copy(field)
while(True):
""" pygame """
for event in pygame.event.get():
if(event.type == QUIT):
pygame.quit()
sys.exit()
while(TURN != 0):
""" othello(4x4) """
while(TURN != 0):
# 黒の手番
if(TURN == BLACK):
point, offset_list = black_turn()
if(TURN == Player):
print("TURN : you")
if(point == (-1, -1)): # pass判定
if((before_field == after_field).all()):
print("pass")
print("両者がpassのため対局を終了します")
TURN = 0
break
print("pass")
print(field)
print("")
TURN = WHITE
before_field = copy.copy(after_field)
after_field = copy.copy(field)
break
address = player_turn()
point = address2point(address)
offset_list = point2offset(point, Player)
if(not(address_check(point, TURN))): # 反則負け
print("「{0}」は無効な手です。".format(address))
print("「先手(黒駒)」は反則により負けになります。")
print("勝者は「後手(白駒)」になります。")
print(field)
Player = 0
break
else:
print("TURN : computer")
if(point == (-1, -1)):
if((before_field == after_field).all()): # pass判定
print("pass")
print("両者がpassのため対局を終了します")
TURN = 0
break
print("pass")
print(field)
print("")
TURN = WHITE
before_field = copy.copy(after_field)
after_field = copy.copy(field)
break
computer_turn()
field = update_field(TURN, point, offset_list)
pygame.display.update()
FPSCLOCK.tick(3)
TURN = WHITE
before_field = copy.copy(after_field)
after_field = copy.copy(field)
print("field")
print(field)
print("")
# 白の手番
elif(TURN == WHITE):
point, offset_list = white_turn()
if(TURN == Player):
print("TURN : you")
if(point == (-1, -1)):
if((before_field == after_field).all()):
print("両者がpassのため対局を終了します")
TURN = 0
break
print("pass")
print(field)
print("")
TURN = BLACK
before_field = copy.copy(after_field)
after_field = copy.copy(field)
break
address = player_turn()
point = address2point(address)
offset_list = point2offset(point, Player)
if(not(address_check(point, TURN))): # 反則負け
print("「{0}」は無効な手です。".format(address))
print("「先手(黒駒)」は反則により負けになります。")
print("勝者は「後手(白駒)」になります。")
print(field)
TURN = 0
break
else:
print("TURN : computer")
if(point == (-1, -1)):
if((before_field == after_field).all()):
print("両者がpassのため対局を終了します")
TURN = 0
break
print("pass")
print(field)
print("")
TURN = BLACK
before_field = copy.copy(after_field)
after_field = copy.copy(field)
break
computer_turn()
field = update_field(TURN, point, offset_list)
pygame.display.update()
FPSCLOCK.tick(3)
TURN = BLACK
before_field = copy.copy(after_field)
after_field = copy.copy(field)
print("field")
print(field)
print("")
else:
print("error : TURN is not BLACK and WHITE")
break
#print(field)
if(not(0 in field)):
show_result()
TURN = 0
break
# othelloのwhile文 終了
# drawing line
SURFACE.fill((255, 255, 255))
weight = 10
for xpos in range(100, 701, 150):
pygame.draw.line(SURFACE, 0x000000, (xpos, 0), (xpos, 601), weight)
for ypos in range(0, 601, 150):
pygame.draw.line(SURFACE, 0x000000, (100, ypos), (701, ypos), weight)
# drawing stone
draw_stone(SURFACE, field)
pygame.display.update()
FPSCLOCK.tick(3)
if __name__ == '__main__':
main()
スポンサードサーチ