def drawLine(self, lines): """ This is called when it's this player's turn to draw a line. This is the method to implement by the student. This method provides the lines that are currently drawn in the game board. Each line in lines is a list of ints in this format: [m1, n1, m2, n2] The above cartesian coordinates correspond to the game board: The gameboard is an imaginary object that has the following layout: --------------------------> m | (0,0) (0,1) (0,2) (0,3) | (1,0) (1,1) (1,2) (1,3) | (2,0) (2,1) (2,2) (2,3) | (3,0) (3,1) (3,2) (3,3) n (grows downwards) e.g. lines = [ [0,0, 0,1], [1,0, 0,1], [0,0, 1,0], ] this contains 3 lines that forms a triangle * Note that lines can be an empty list [] * There are 42 possible lines, 33 of which will be used in a single game (discounting the overlapping lines) all_possible_valid_lines = [ # all horizontal lines [0,0, 0,1], [0,1, 0,2], [0,2, 0,3], [1,0, 1,1], [1,1, 1,2], [1,2, 1,3], [2,0, 2,1], [2,1, 2,2], [2,2, 2,3], [3,0, 3,1], [3,1, 3,2], [3,2, 3,3], # all vertical lines [0,0, 1,0], [0,1, 1,1], [0,2, 1,2], [0,3, 1,3], [1,0, 2,0], [1,1, 2,1], [1,2, 2,2], [1,3, 2,3], [2,0, 3,0], [2,1, 3,1], [2,2, 3,2], [2,3, 3,3], # all positive slopes [1,0, 0,1], [1,1, 0,2], [1,2, 0,3], [2,0, 1,1], [2,1, 1,2], [2,2, 1,3], [3,0, 2,1], [3,1, 2,2], [3,2, 2,3], # all negative slopes [0,0, 1,1], [0,1, 1,2], [0,2, 1,3], [1,0, 2,1], [1,1, 2,2], [1,2, 2,3], [2,0, 3,1], [2,1, 3,2], [2,2, 3,3], ] ** This method needs to return a valid, non-overlapping line or you lose. So, you should definitely check the validity of the line first before returning it to avoid disqualification. Do this by: if not line_overlaps(my_line, lines) and\ line_is_valid(my_line): # fix it. It should never go here if you know what you # are doing. return my_line 1) Use line_is_valid(line) to check if the line follows the convention below. As a convention of the game, lines should be written from left to right and from up to down e.g. VALID vertical lines: '0010', '1121', ... horizontal lines: '0001', '1112', ... positive slope: '1001', '1203', ... negative slope: '0011', '1223', ... INVALID vertical lines: '1000', '2111', ... horizontal lines: '0100', '1211', ... positive slope: '0110', '0312', ... negative slope: '1100', '2312', ... 2) Use line_overlaps(line, lines) to check if line is already drawn (already in lines) and if it overlaps another line. """ all_lines = self.all_possible_valid_lines # choose a random line chosen_line_index = randint(0, len(all_lines)-1) chosen_line = all_lines[chosen_line_index] # if the line is invalid, remove it and choose another if all_lines: # not empty while line_overlaps(chosen_line, lines) or\ not line_is_valid(chosen_line): all_lines.remove(chosen_line) chosen_line_index = randint(0, len(all_lines)-1) chosen_line = all_lines[chosen_line_index] return chosen_line
def drawLine(self, lines): """ Strategy ----------------------------------------------------- Step 1: check for incomplete triangles in lines - if there is such a triangle, then complete it. Step 2: if step 1 does not return a line, choose a line that will not leave in an incomplete triangle for the other player after this turn. Step 3: if step 2 does not return a line, choose a line that will result in an incomplete triangle but will result in the least amount of triangles being completed by the other player in the following turn. Notes -------------------------------------------------------- The gameboard is an imaginary object that has the following layout: --------------------------> m | (0,0) (0,1) (0,2) (0,3) | (1,0) (1,1) (1,2) (1,3) | (2,0) (2,1) (2,2) (2,3) | (3,0) (3,1) (3,2) (3,3) n (grows downwards) """ # first turn of the game, choose arbitrary line. if not lines: return [0, 0, 0, 1] # update the list of lines that are not yet drawn lines_to_rmv = [] for line in self.all_possible_valid_lines: if line_overlaps(line, lines) or\ not line_is_valid(line): lines_to_rmv.append(line) for l in lines_to_rmv: self.all_possible_valid_lines.remove(l) # if step 1 fails, do not let opponent predict what # we will draw shuffle(self.all_possible_valid_lines) # Step 1 c = self.line_complete(lines) if c: return c[0] # Step 2 for line in self.all_possible_valid_lines: tmp = lines[:] tmp.append(line) c = self.line_complete(tmp) if not c: return line # Step 3 min_score, l = 9001, None for line in self.all_possible_valid_lines: score = 0 tmp = lines[:] tmp.append(line) while True: c = self.line_complete(tmp) if c: score += c[1] tmp.append(c[0]) continue break if score < min_score or not l: min_score = score l = line return l