11from __future__ import annotations
22import itertools
3- import numpy
4- from typing import List , Tuple , Iterable , Optional
3+ import numpy as np
4+ import numpy .typing as npt
5+ from typing import List , Tuple , Iterable , Optional , Union
6+
7+ _all_numpy_int_types = Union [np .int8 , np .int16 , np .int32 , np .int64 ]
58
69X = 1
710O = 2
@@ -19,8 +22,8 @@ def __init__(self, dimensions: Tuple[int, ...] = (3, 3), x_in_a_row: int = 3) ->
1922 self .o : List [Move ] = []
2023 self .turn = X
2124
22- def create_board (self ) -> numpy . ndarray :
23- return numpy .zeros (self .dimensions )
25+ def create_board (self ) -> npt . NDArray [ np . int8 ] :
26+ return np .zeros (self .dimensions , dtype = np . int8 )
2427
2528 def copy (self ) -> Board :
2629 board = Board (self .dimensions , self .x_in_a_row )
@@ -30,7 +33,7 @@ def copy(self) -> Board:
3033
3134 def get_mark_at_position (self , position : Iterable [int ]) -> int :
3235 position = tuple (position )
33- return self .board [position ]
36+ return int ( self .board [position ])
3437
3538 def set_mark (self , coordinates : Tuple [int , ...], player : int ) -> None :
3639 self .board [coordinates ] = player
@@ -39,7 +42,7 @@ def set_mark(self, coordinates: Tuple[int, ...], player: int) -> None:
3942 else :
4043 self .o .append (Move (coordinates ))
4144
42- def is_empty (self , position ) :
45+ def is_empty (self , position : Tuple [ int , ...]) -> bool :
4346 return self .get_mark_at_position (position ) == 0
4447
4548 def push (self , coordinates : Iterable [int ]) -> None :
@@ -64,21 +67,21 @@ def find_directions(self) -> List[Tuple[int, ...]]:
6467 break
6568 return correct_directions
6669
67- def possible_moves (self ) -> numpy . ndarray :
68- return numpy .argwhere (self .board == 0 )
70+ def possible_moves (self ) -> npt . NDArray [ np . int64 ] :
71+ return np .argwhere (self .board == 0 )
6972
70- def out_of_bounds (self , pos : numpy . ndarray ) -> numpy .bool_ :
73+ def out_of_bounds (self , pos : npt . NDArray [ _all_numpy_int_types ] ) -> np .bool_ :
7174 return (pos < 0 ).any () or (pos >= self .dimensions ).any ()
7275
73- def in_bounds (self , pos : numpy . ndarray ) -> bool :
76+ def in_bounds (self , pos : npt . NDArray [ _all_numpy_int_types ] ) -> bool :
7477 return not self .out_of_bounds (pos )
7578
7679 def has_won (self , player : int ) -> bool :
77- positions = numpy .argwhere (self .board == player )
80+ positions = np .argwhere (self .board == player )
7881 for position in positions :
7982 for direction in self ._directions :
8083 for in_a_row in range (1 , self .x_in_a_row ):
81- pos = position + numpy .multiply (direction , in_a_row )
84+ pos = position + np .multiply (direction , in_a_row )
8285 if self .out_of_bounds (pos ) or self .board [tuple (pos )] != player :
8386 break
8487 else :
0 commit comments