mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-22 15:16:33 -08:00
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:
@@ -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.
|
||||||
|
|||||||
Reference in New Issue
Block a user