Refactoring player turn and computer turn to separate methods. Computer turn logic previously ignored counting turns. Computer turn previously gave up the round if the user enters "inconsistent information" about the computers guess when it should have restarted the computers turn. Refactoring to remove usage of 'flag' variables to control program flow.

This commit is contained in:
Joe Nellis
2022-04-30 00:42:24 -07:00
parent 8bc2b33a58
commit f74367fa59

View File

@@ -37,119 +37,119 @@ computer_score = 0
def main() -> None: def main() -> None:
global human_score, computer_score
current_round = 1 current_round = 1
while current_round <= NUM_ROUNDS: while current_round <= NUM_ROUNDS:
print(f"Round number {current_round}") print(f"Round number {current_round}")
num_moves = 1 human_turn()
guesses: List[List[Union[str, int]]] = [] computer_turn()
turn_over = False current_round += 1
print("Guess my combination ...") print_score(is_final_score=True)
secret_combination = int(POSSIBILITIES * random.random()) sys.exit()
answer = possibility_to_color_code(secret_combination)
while num_moves < 10 and not turn_over:
print(f"Move # {num_moves} Guess : ") def human_turn() -> None:
user_command = input("Guess ") global human_score
if user_command == "BOARD": num_moves = 1
print_board(guesses) # 2000 guesses: List[List[Union[str, int]]] = []
elif user_command == "QUIT": # 2500 print("Guess my combination ...")
print(f"QUITTER! MY COMBINATION WAS: {answer}") secret_combination = int(POSSIBILITIES * random.random())
print("GOOD BYE") answer = possibility_to_color_code(secret_combination)
quit() while True:
elif len(user_command) != NUM_POSITIONS: # 410 print(f"Move # {num_moves} Guess : ")
print("BAD NUMBER OF POSITIONS") user_command = input("Guess ")
if user_command == "BOARD":
print_board(guesses) # 2000
elif user_command == "QUIT": # 2500
print(f"QUITTER! MY COMBINATION WAS: {answer}")
print("GOOD BYE")
quit()
elif len(user_command) != NUM_POSITIONS: # 410
print("BAD NUMBER OF POSITIONS")
else:
invalid_letters = get_invalid_letters(user_command)
if invalid_letters > "":
print(f"INVALID GUESS: {invalid_letters}")
else: else:
invalid_letters = get_invalid_letters(user_command) guess_results = compare_two_positions(user_command, answer)
if invalid_letters > "": if guess_results[1] == NUM_POSITIONS: # correct guess
print(f"INVALID GUESS: {invalid_letters}") print(f"You guessed it in {num_moves} moves!")
human_score = human_score + num_moves
print_score()
return # from human turn, triumphant
else: else:
guess_results = compare_two_positions(user_command, answer) print(
if guess_results[1] == NUM_POSITIONS: # correct guess "You have {} blacks and {} whites".format(
turn_over = True guess_results[1], guess_results[2]
print(f"You guessed it in {num_moves} moves!")
human_score = human_score + num_moves
print_score()
else:
print(
"You have {} blacks and {} whites".format(
guess_results[1], guess_results[2]
)
) )
num_moves = num_moves + 1 )
guesses.append(guess_results) guesses.append(guess_results)
if not turn_over: # RAN OUT OF MOVES num_moves += 1
if num_moves > 10: # RAN OUT OF MOVES
print("YOU RAN OUT OF MOVES! THAT'S ALL YOU GET!") print("YOU RAN OUT OF MOVES! THAT'S ALL YOU GET!")
print(f"THE ACTUAL COMBINATION WAS: {answer}") print(f"THE ACTUAL COMBINATION WAS: {answer}")
human_score = human_score + num_moves human_score = human_score + num_moves
print_score() print_score()
return # from human turn, defeated
# COMPUTER TURN
turn_over = False def computer_turn() -> None:
inconsistent_information = False global computer_score
while not turn_over and not inconsistent_information: while True:
all_possibilities = [1] * POSSIBILITIES all_possibilities = [1] * POSSIBILITIES
num_moves = 1 num_moves = 1
inconsistent_information = False print("NOW I GUESS. THINK OF A COMBINATION.")
print("NOW I GUESS. THINK OF A COMBINATION.") input("HIT RETURN WHEN READY: ")
input("HIT RETURN WHEN READY: ") while True:
while num_moves < 10 and not turn_over and not inconsistent_information: possible_guess = find_first_solution_of(all_possibilities)
found_guess = False if possible_guess < 0: # no solutions left :(
possible_guess = int(POSSIBILITIES * random.random()) print("YOU HAVE GIVEN ME INCONSISTENT INFORMATION.")
if ( print("TRY AGAIN, AND THIS TIME PLEASE BE MORE CAREFUL.")
all_possibilities[possible_guess] == 1 break # out of inner while loop, restart computer turn
): # random guess is possible, use it
found_guess = True computer_guess = possibility_to_color_code(possible_guess)
else: print(f"My guess is: {computer_guess}")
for i in range(possible_guess + 1, POSSIBILITIES): blacks_str, whites_str = input(
if all_possibilities[i] == 1: "ENTER BLACKS, WHITES (e.g. 1,2): "
found_guess = True ).split(",")
possible_guess = i blacks = int(blacks_str)
break whites = int(whites_str)
if not found_guess: if blacks == NUM_POSITIONS: # Correct guess
for i in range(0, possible_guess): print(f"I GOT IT IN {num_moves} MOVES")
if all_possibilities[i] == 1: computer_score = computer_score + num_moves
found_guess = True print_score()
possible_guess = i return # from computer turn
break
if not found_guess: # inconsistent info from user # computer guessed wrong, deduce which solutions to eliminate.
print("YOU HAVE GIVEN ME INCONSISTENT INFORMATION.") for i in range(0, POSSIBILITIES):
print("TRY AGAIN, AND THIS TIME PLEASE BE MORE CAREFUL.") if all_possibilities[i] == 0: # already ruled out
turn_over = True continue
inconsistent_information = True possible_answer = possibility_to_color_code(i)
else: comparison = compare_two_positions(
computer_guess = possibility_to_color_code(possible_guess) possible_answer, computer_guess
print(f"My guess is: {computer_guess}") )
blacks_str, whites_str = input( if (blacks != comparison[1]) or (whites != comparison[2]):
"ENTER BLACKS, WHITES (e.g. 1,2): " all_possibilities[i] = 0
).split(",")
blacks = int(blacks_str) if num_moves == 10:
whites = int(whites_str)
if blacks == NUM_POSITIONS: # Correct guess
print(f"I GOT IT IN {num_moves} MOVES")
turn_over = True
computer_score = computer_score + num_moves
print_score()
else:
num_moves += 1
for i in range(0, POSSIBILITIES):
if all_possibilities[i] == 0: # already ruled out
continue
possible_answer = possibility_to_color_code(i)
comparison = compare_two_positions(
possible_answer, computer_guess
)
if (blacks != comparison[1]) or (whites != comparison[2]):
all_possibilities[i] = 0
if not turn_over: # COMPUTER DID NOT GUESS
print("I USED UP ALL MY MOVES!") print("I USED UP ALL MY MOVES!")
print("I GUESS MY CPU IS JUST HAVING AN OFF DAY.") print("I GUESS MY CPU IS JUST HAVING AN OFF DAY.")
computer_score = computer_score + num_moves computer_score = computer_score + num_moves
print_score() print_score()
current_round += 1 return # from computer turn, defeated.
print_score(is_final_score=True) num_moves += 1
sys.exit()
def find_first_solution_of(all_possibilities: List[int]) -> int:
"""Scan through all_possibilities for first remaining non-zero marker,
starting from some random position and wrapping around if needed.
If not found return -1."""
start = int(POSSIBILITIES * random.random())
for i in range(0, POSSIBILITIES):
solution = (i+start) % POSSIBILITIES
if all_possibilities[solution]:
return solution
return -1
# 470 # 470
@@ -172,7 +172,6 @@ def print_board(guesses) -> None:
print(f"{idx + 1}\t{guess[0]}\t{guess[1]} {guess[2]}") print(f"{idx + 1}\t{guess[0]}\t{guess[1]} {guess[2]}")
def possibility_to_color_code(possibility: int) -> str: def possibility_to_color_code(possibility: int) -> str:
"""Accepts a (decimal) number representing one permutation in the realm of """Accepts a (decimal) number representing one permutation in the realm of
possible secret codes and returns the color code mapped to that permutation. possible secret codes and returns the color code mapped to that permutation.