-2

我有一个用于 python 3 的黑白棋游戏的 2 个文件。我的第一个文件称为 reversi.py。它实现了 (a) 游戏玩法的高级控制(例如,从计算机玩家和人类玩家那里获取动作,确定玩家是否用完动作,确定游戏结束并宣布游戏结果) , (b) 通过 QuickDraw 渲染游戏,以及 (c) 从人类玩家那里获取输入。

继承人的文件:

from game import *
from copy import deepcopy
from time import sleep
import sys
from subprocess import PIPE,Popen
from threading import Thread
from queue import Queue,Empty



def ParseEvent() :
    r=receive()
    if r==None:return None,None
    s=[x.rstrip().strip() for x in r.split(":")]
    return s[0],s[1]


def highlight(move):
    send( 'color 255 0 0\n circle %d %d 11\n' % \
        (240+(move[0]+0.5)*40, 100+(move[1]+0.5)*40))


def stone(x,y,turn):
    send('color %d %d %d\n' % \
        (255*(1-turn),255*(1-turn),255*(1-turn)))
    send('fillcircle %d %d %d\n' % \
        (240+(x+0.5)*40, 100+(y+0.5)*40, 17))


def draw(board):
    send('color 20 20 20\n clear\n color 15 15 100\n')
    send( 'button button1 600 20 100 20 "Calculate W:L"')
    send('fillrect %d %d %d %d\n' % (240,100,320,320))
    send('color 0 70 0\n') 
    for i in range(1,8):
        send('line %d %d %d %d\n' %\
            (240+i*40,100, 240+i*40,420))
        send('line %d %d %d %d\n' %\
            (240, 100+i*40, 560, 100+i*40))
    for i in range(8):
        for j in range(8):
            if board[i][j] >= 0:
                stone(i, j, board[i][j])

def makeBoard():
    board = []
    for i in range(8):
        board.append([])
        for j in range(8):
            board[i].append(-1)  
    board[3][3], board[4][4], board[3][4], board[4][3] = 0,0,1,1
    return board



def _queueqd(ip,q):
    for line in iter(ip.readline,b''):
        q.put(line)
    ip.close()

def send(*args):
    s=""
    for a in args:
        s+=str(a)
        if s[-1]!=" ":s+=" "
    if s!="":
        op.write((s[:-1]+"\n").encode('utf-8'))
    else:
        op.write("\n".encode('utf-8'))

def receive():
    try:
        return qdq.get_nowait().decode('utf-8')[:-1]
    except Empty:
        return None
def running():
    return qdp.poll()==None


def simulate(numTimes=1000):
    w=0
    b=0
    for i in range(numTimes):
        goesFirst=i&1
        gb=makeBoard()
        sg = Game(gb, goesFirst)
        count = 4
        while count < 64: # max num of stones is 64
            sg.get_moves()
            if sg.moves == []: 
                sg.turn = 1 - sg.turn
                sg.get_moves()
                if sg.moves!= []:
                    continue 
                sg.turn = 1 - sg.turn
                break 
            if sg.turn==0:
                mv = sg.select_move()
            else:
                mv= sg.moves[int(len(sg.moves)*random.random())]
            sg.play_move(mv)
            sg.turn=1-sg.turn
            count+=1
        num_white, num_black = sg.final_result()
        if num_white>num_black:w+=1
        if num_black>num_white:b+=1
    return w/b

try:
    qdp = Popen("java -jar quickdraw.jar",shell=True,stdout=PIPE,stdin=PIPE)
    op=qdp.stdin
    qdq = Queue()
    qdt = Thread(target=_queueqd,args=(qdp.stdout,qdq))
    qdt.daemon=True
    qdt.start()
except:
    print("quickdraw.jar must be in the same directory as this python script.")
    quit()

send( "mouseclick True\n" )
# initialize the board, get ready for the game 

board =makeBoard()
draw(board) 


# game time, let's play...
# human player is white and moves first

g = Game(board, 0)
count = 4
while count < 64: # max num of stones is 64
    g.get_moves()
    if g.moves == []: 
        g.turn = 1 - g.turn
        g.get_moves()
        if  g.moves!= []:
            continue 
        g.turn = 1 - g.turn
        break 
    if g.turn == 0:
        while running():
            event, val = ParseEvent()
            if event == "MouseClicked":
                val=[ int(x) for x in val.split(",")]
                move = [(val[0]-240)//40, (val[1]-100)//40]
                if move in g.moves: break
            elif event=="ButtonClicked":
                send("colour 20 20 20\nfillrect 600 50 200 50\ncolour 255 255 255")
                send('text "Calculating..." 600 80')
                r=simulate()
                send("colour 20 20 20\nfillrect 600 50 200 50\ncolour 255 255 255")
                send("text ",'"W:L=',r,'"'," 600 80")
    else:
        move = g.select_move()
    stone(move[0], move[1], g.turn)
    highlight(move)
    sleep(1)
    board = deepcopy(g.board)
    g.play_move(move)
    g.turn=1-g.turn
    for i in range(8):
        for j in range(8):
            if board[i][j]!= g.board[i][j]:
                stone(i,j,1-g.turn)
    sleep(1)
    stone(move[0], move[1], 1-g.turn) # redraw to de-highlight
    count += 1


# game over, let's announce the result:

num_white, num_black = g.final_result()
send('color 255 255 255\n')
if num_black > num_white:
    send('text "black wins!" 370 470\n')
elif num_black < num_white:
    send('text "white wins!" 370 470\n')
else:
    send('text "tie!" 390 470\n')
send('text "black:" 325 500\n')
send('text "%d" 375 500\n' % num_black)
send('text "white:" 425 500\n')
send('text "%d" 475 500\n' % num_white)

while running():
    pass

这个文件就完成了。我的第二个文件名为 Game.py。第一个文件为玩家可以做出的动作导入这个文件。

import random

class Game:
    delta = [[0,-1],[1,-1],[1,0],[1,1],[0,1],\
                [-1,1],[-1,0],[-1,-1]]

    def __init__(self, board, turn):
        self.board = board
        self.turn = turn
        self.moves = self.get_moves()

    def check_move(self, move, d):
        pass #which I have to figure out!

    def get_moves(self):
        pass ##################

    def select_move(self):
        pass ##################

    def play_move(self, move): 
        m,n=move[0],move[1]
        for d in range(8):
            i, j = m, n
            if self.check_move(move,d):
                i, j = i+self.delta[d][0], j+self.delta[d][1]
                while self.board[i][j] == 1-self.turn:
                    self.board[i][j] = self.turn
                    i, j = i+self.delta[d][0], j+self.delta[d][1]
        self.board[m][n]=self.turn

    def final_result(self): 
        black, white = 0, 0   # color 0 is white
        for i in range(8):
            for j in range(8):
                if self.board[i][j] == 0: white += 1
                elif self.board[i][j] == 1: black += 1
        return white,black

我应该填写三个缺失的定义。假设给定回合,check move(self, move, d) 方法检查给定的移动是否沿某个方向 d 得到验证。它相应地返回 True 或 False。换句话说,如果从move指定的格子开始,可以捕获沿方向d的许多对手棋子,那么应该返回一个True。该方法可以方便地用于其他方法,例如 get move() 和 play move()。get move(self) 方法查找当前回合的所有有效移动,并将它们返回到列表中。例如,如果在 [2,4] 和 [3,6] 处有两个移动,那么返回值应该是 [[2,4], [3,6]]。select move(self) 方法从 self.move 中选择一个移动并返回它。显然,最简单的方法是返回随机移动。

所以基本上我有这是“check_move”功能的基础:

def check_move(self,move,d):
    check neighboring tile:
        if empty:
            False #can't move
        if enemy present:
            while there are enemy pieces:
                True #can move

这是正确的方向吗?

另外对于 get_moves 我有这样的理由:

def get_moves(self): # grid[ij]
    for i in range 
    for j in range
        check for possible move directions:
            check move again:
                if yes then append[ij] to a list of valid moves
        return list of valid moves
4

1 回答 1

2

I think you should first, before you start writing code, think about what defines a valid move in Reversi. Try writing in English what the definition is. For instance, here's the conditions I can think of in a few seconds:

  1. The tested tile must be empty
  2. The tested tile must have an enemy piece next to it in the selected direction.
  3. Past that enemy piece in the given direction, there may be more enemy pieces.
  4. Past all the enemy pieces, there must be a friendly piece (not an empty space or the edge of the board).

I'm not sure if that's comprehensive or not, but it's a reasonable start. Then, think about how to test each of those. Some may easily flow from each other, while others may be separate tests.

I'd also not be shy about reading and adapting the existing code you've been given. For instance, the play_move method just below the method's you're going to implement does a very similar loop to what you're going to want in your check_move method (though it's flipping the tiles, rather than checking that they can be flipped).

于 2012-12-03T03:34:18.017 回答