マルバツゲーム:賢いプレイヤー
Posted feedbacks - Python
先手、後手でも負けることはありません シンプルな実装にしました
・自分の駒が二個並んでいるときはそのまま勝つ ・相手の駒が二個並んでいて勝たれてしまうときは防ぐ ・相手のダブルリーチを防ぐ
を戦略として、先手の場合一手目、二手目だけ打つ方法を指定しています
random won: 0 , think won: 860 draw: 140 think won: 985 , random won: 0 draw: 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | import random
random.seed()
class Mark:
def __init__(self, name):
self.name = name
MARK_E = Mark(" ")
MARK_X = Mark("X")
MARK_O = Mark("O")
class Marubatsu:
lines = []
for a in range(3):
lines.append([(a, b) for b in range(3) ])
lines.append([(b, a) for b in range(3) ])
lines.append([(a, a) for a in range(3) ])
lines.append([(2 - a, a) for a in range(3) ])
def __init__(self, p1_logic, p2_logic):
self.fields = {}
self.seq = []
for x in range(3):
for y in range(3):
self.fields[(x, y)] = MARK_E
self.logic = (p1_logic, p2_logic)
self.turn = 0
def now_player(self):
return 0 if self.turn % 2 == 0 else 1
def mark(self):
return MARK_O if self.now_player() == 0 else MARK_X
def play(self):
for self.turn in range(9):
logic = self.logic[self.now_player()]
pos = logic(self)
if self.at(pos) != MARK_E:
raise "Err"
self.fields[pos] = self.mark()
self.seq.append((self.mark(), pos))
mark = self.end_check()
if mark:
return mark
return None
def at(self, pos):
return self.fields[pos]
def __str__(self):
str = ""
for x in range(3):
str += "".join([self.at((x, y)).name for y in range(3)])
str += "\n"
str += " ".join(["%s: %s" % (mark.name, pos) for mark, pos in self.seq])
str += "\n"
return str
def count_at_line(self, line):
ret = {MARK_E: 0 ,MARK_O: 0, MARK_X: 0}
for pos in line:
ret[self.fields[pos]] += 1
return ret
def end_check(self):
for line in Marubatsu.lines:
counts = self.count_at_line(line)
if counts[MARK_O] == 3:
return MARK_O
elif counts[MARK_X] == 3:
return MARK_X
return None
def can_puts(self):
return [pos for pos, mark in self.fields.items()
if mark == MARK_E]
def think_put(game):
if game.at((1, 1)) == MARK_E:
return (1, 1)
me = game.mark()
op = MARK_O if me == MARK_X else MARK_X
# OO_
for line in Marubatsu.lines:
counts = game.count_at_line(line)
if (counts[me] == 2 and counts[MARK_E] == 1):
return [pos for pos in line if game.at(pos) == MARK_E][0]
# XX_
for line in Marubatsu.lines:
counts = game.count_at_line(line)
if (counts[op] == 2 and counts[MARK_E] == 1):
return [pos for pos in line if game.at(pos) == MARK_E][0]
if game.turn == 3:
op_corners = [a for a in \
[game.at((0, 0)), game.at((0, 2)),
game.at((2, 0)), game.at((2, 2))]
if a == op]
if len(op_corners) == 2:
return (1, 0)
point_map = {}
for line in Marubatsu.lines:
counts = game.count_at_line(line)
if (counts[op] == 1 and counts[MARK_E] == 2):
for pos in line:
if point_map.has_key(pos):
point_map[pos] += 1
else:
point_map[pos] = 1
if len(point_map) > 0:
point_pos = max(point_map, key=point_map.__getitem__)
if game.at(point_pos) == MARK_E:
return point_pos
# O__
for line in Marubatsu.lines:
counts = game.count_at_line(line)
if (counts[me] == 1 and counts[MARK_E] == 2):
return [pos for pos in line if game.at(pos) == MARK_E][-1]
for pos in [(0, 0), (2, 2), (2, 0), (0, 2)]:
if game.at(pos) == MARK_E:
return pos
return random_put(game)
def random_put(game):
puts = game.can_puts()
return puts[random.randrange(len(puts))]
def play(p1_name, p1_logic, p2_name, p2_logic, count):
results = [0, 0, 0]
player_idx = {MARK_O: 0, MARK_X: 1, None: 2}
for round in range(count):
game = Marubatsu(p1_logic, p2_logic)
winner = player_idx[game.play()]
results[winner] += 1
if (winner == 0 and p2_name == "tnk") or \
(winner == 1 and p1_name == "tnk"):
print game
print p1_name , "won:", results[0], ",", \
p2_name, "won:", results[1], "draw:", results[2]
if __name__ == '__main__':
play("random", random_put, "think", think_put, 1000)
play("think", think_put, "random", random_put, 1000)
|

syat
#6207()
Rating0/2=0.00
マルバツゲームで、賢いプレイヤーの思考ルーチンを実装してください。
賢いといってもいろいろありますが、
1.負けない
2.できるだけ勝つ
という条件でいってみたいと思います。
ランダムプレイヤーと1万回バトルした結果(勝ち・負け・分け)を表示してください。
先攻になっても後攻になっても無敗!となれば言うことなしです。
[ reply ]