Python 抽签决定胜利者

Python 抽签决定胜利者,python,Python,我想用python为一个名为winner(board)的3x3 tic-tac-toeboard编写一个过程,它获取一个代表tic-tac-toeboard的二维列表,并确定是否有赢家(以及是否有赢家,谁是赢家)或游戏是否以平局结束。棋盘使用'-'表示打开位置,玩家1使用'x',玩家2使用'o' 我还希望使用过程select_row(array,I)和select_col(array,I),它们接受二维数组(表示为嵌套列表)和行或列的索引,并返回表示与该索引关联的行或列的列表,以及过程selec

我想用python为一个名为
winner(board)
的3x3 tic-tac-toeboard编写一个过程,它获取一个代表tic-tac-toeboard的二维列表,并确定是否有赢家(以及是否有赢家,谁是赢家)或游戏是否以平局结束。棋盘使用
'-'
表示打开位置,玩家1使用
'x'
,玩家2使用
'o'

我还希望使用过程
select_row(array,I)
select_col(array,I)
,它们接受二维数组(表示为嵌套列表)和行或列的索引,并返回表示与该索引关联的行或列的列表,以及过程
select_main\u diag(array)
选择_counter_diag(array)
接受正方形二维数组并返回包含主对角线或反对角线元素的列表

报税表如下:

winner([['-','-','-'], ['-','-','-'], ['-','-','-']])
False

winner([['x','x','x'], ['-','-','-'], ['-','-','-']])
'x'

winner([['o', '-','-'], ['-', 'o','-'], ['-','-','o']])
'o'

winner([['-','-','x'], ['-','-','x'], ['-','-', 'x']])
'x'

winner([['x','o','x'], ['x','o','o'], ['o','x','x']])
"Draw"

winner([['x','o','x'], ['x','o','o'], ['o','-','x']])
False
def select_row(lst, i):
 return lst[i]

def select_col(lst, i):
   return [lst[idx][i] for idx in range(len(lst))]

def select_main_diag(array):
  return [array[i][i] for i in range(len(array))]

def select_counter_diag(array): 
  return [array[len(array)-i-1][i] for i in range(len(array))]
我希望在守则中包括和使用的程序如下:

winner([['-','-','-'], ['-','-','-'], ['-','-','-']])
False

winner([['x','x','x'], ['-','-','-'], ['-','-','-']])
'x'

winner([['o', '-','-'], ['-', 'o','-'], ['-','-','o']])
'o'

winner([['-','-','x'], ['-','-','x'], ['-','-', 'x']])
'x'

winner([['x','o','x'], ['x','o','o'], ['o','x','x']])
"Draw"

winner([['x','o','x'], ['x','o','o'], ['o','-','x']])
False
def select_row(lst, i):
 return lst[i]

def select_col(lst, i):
   return [lst[idx][i] for idx in range(len(lst))]

def select_main_diag(array):
  return [array[i][i] for i in range(len(array))]

def select_counter_diag(array): 
  return [array[len(array)-i-1][i] for i in range(len(array))]

我对使用python非常陌生,因此任何关于这个问题的建议——包括如何使用python以及如何将其转化为代码——都会非常有帮助。

以下是我将如何使用python的方法:

  • 对于每一行、每一列和每一对角线:这三个空格都一样吗?如果是这样,而且它们不是空的,那就是赢家
  • 否则,电路板是否已满(即没有空位)?如果是这样,那就是平局
  • 否则,就没有赢家,比赛就继续下去

  • 在接下来的实施中,该计划试图最大化获胜的机会。更强大的版本会尽量减少失败的机会。另一种策略是学习什么行动导致胜利,什么行动导致失败。对于获胜者,
    grade\u grid(state.grid)
    给出了答案

    import tkinter
    from itertools import product
    from math import trunc
    from functools import lru_cache, wraps
    from random import choice
    from sys import modules
    
    ################################################################################
    
    class Cross(tkinter.Frame):
    
        @classmethod
        def main(cls):
            tkinter.NoDefaultRoot()
            root = tkinter.Tk()
            root.title('Demo')
            root.resizable(False, False)
            widget = cls(root)
            widget.grid()
            root.mainloop()
    
        def __init__(self, master=None, cnf={}, **kw):
            super().__init__(master, cnf, **kw)
            self.__ai = CrossAI()
            space = ' ' * 11
            self.__buttons = {}
            for r, c in product(range(3), range(3)):
                b = tkinter.Button(self, text=space, command=self.__bind(r, c))
                b.grid(row=r, column=c, padx=10, pady=10)
                self.__buttons.setdefault(r, {})[c] = b
    
        def __bind(self, row, column):
            return lambda: self.click(row, column)
    
        def click(self, row, column):
            r, c = self.__ai.move(row, column)
            if r != -1 != c:
                self.__buttons[row][column]['text'] = '    X    '
                if r != -2 != c:
                    self.__buttons[r][c]['text'] = '    O    '
    
    ################################################################################
    
    def enum(names):
        "Create a simple enumeration having similarities to C."
        return type('enum', (), dict(map(reversed, enumerate(
            names.replace(',', ' ').split())), __slots__=()))()
    
    ################################################################################
    
    class Static(type):
    
        def __new__(cls, name, bases, members):
            for name, member in members.items():
                if callable(member):
                    members[name] = cls.__wrap(member)
                elif isinstance(member, property):
                    members[name] = property(cls.__wrap(member.fget),
                                             cls.__wrap(member.fset),
                                             cls.__wrap(member.fdel),
                                             member.__doc__)
                elif isinstance(member, (classmethod, staticmethod)):
                    members[name] = type(member)(cls.__wrap(member.__func__))
            return super().__new__(cls, name, bases, members)
    
        @classmethod
        def __wrap(cls, function):
            if function:
                annotations = function.__annotations__
                co_varnames = function.__code__.co_varnames
                if not annotations:
                    return function
                @wraps(function)
                def wrapper(*args):
                    for arg, name in zip(args, co_varnames):
                        cls.__raise(arg, annotations[name])
                    value = function(*args)
                    cls.__raise(value, annotations['return'])
                    return value
                return wrapper
    
        @staticmethod
        def __raise(item, klass):
            if klass is None:
                klass = type(None)
            elif isinstance(klass, str):
                klass = vars(modules[item.__module__])[klass]
            if not isinstance(item, klass):
                raise TypeError('{} must be of type {}'.format(item, klass))
    
    ################################################################################
    
    class CrossAI(metaclass=Static):
    
        STATE = enum('changing, victory, defeat, error, draw')
    
        def __init__(self: 'CrossAI') -> None:
            self.__db = State(((0, 0, 0), (0, 0, 0), (0, 0, 0)), 1)
    
        def move(self: 'CrossAI', row: int, column: int) -> tuple:
            if not self.__db.moves:
                return -1, -1
            self.__make_move(row, column)
            return self.__best_move()
    
        def __make_move(self: 'CrossAI', row: int, column: int) -> None:
            copy = tuple(map(list, self.__db.grid))
            copy[row][column] = 1
            self.__db = State(tuple(map(tuple, copy)), -1)
    
        def __best_move(self: 'CrossAI') -> tuple:
            if not self.__db.moves:
                return -2, -2
            score = min(move.grade for move in self.__db.moves)
            moves = tuple(move for move in self.__db.moves if move.grade == score)
            final = choice(moves)
            for r, c in product(range(3), range(3)):
                if self.__db.grid[r][c] != final.grid[r][c]:
                    self.__db = State(final.grid, 1)
                    return r, c
    
    ################################################################################
    
    class State(tuple):
    
        @lru_cache(None)
        def __new__(cls, grid, next_move):
            return super().__new__(cls, (grid, make_moves(grid, next_move)))
    
        @property
        def grid(self):
            return self[0]
    
        @property
        def moves(self):
            return self[1]
    
        @property
        def grade(self):
            return grade(*self)
    
    ################################################################################
    
    @lru_cache(None)
    def make_moves(grid, next_move):
        moves = []
        for r, c in available_moves(grid):
            copy = tuple(map(list, grid))
            copy[r][c] = next_move
            moves.append(State(tuple(map(tuple, copy)), -next_move))
        return frozenset(moves)
    
    @lru_cache(None)
    def available_moves(grid):
        return () if grade_grid(grid) else \
            tuple((r, c) for r, c in product(range(3), range(3)) if not grid[r][c])
    
    @lru_cache(None)
    def grade(grid, moves):
        return grade_grid(grid) + grade_moves(moves)
    
    @lru_cache(None)
    def grade_grid(grid):
        for triplet in combinations(grid):
            grade = trunc(sum(triplet) / 3)
            if grade:
                return grade
        return 0
    
    @lru_cache(None)
    def combinations(grid):
        combos = list(grid)
        for c in range(3):
            combos.append(tuple(grid[r][c] for r in range(3)))
        combos.append(tuple(grid[i][i] for i in range(3)))
        combos.append(tuple(grid[i][2 - i] for i in range(3)))
        return combos
    
    @lru_cache(None)
    def grade_moves(moves):
        return sum(grade(*move) for move in moves)
    
    ################################################################################
    
    if __name__ == '__main__':
        Cross.main()
    

    @内特,这有没有可能不是家庭作业?这是我计算机科学课上的一个实验室。因此,我必须处理非常具体的限制条件。@DavidBrainer Banker-不太可能,但我只是出于礼貌。虽然这些限制条件很难理解,但你会在中找到许多解决方案。和往常一样,不要把它看作是良好编程风格的象征,记住,新的高尔夫问题(和其他目标编程难题)应该去。