|
| 1 | +"""Simulate a six-sided dice roll. |
| 2 | +
|
| 3 | +Usage: |
| 4 | +
|
| 5 | + $ python dice.py |
| 6 | + How many dice do you want to roll? [1-6] 5 |
| 7 | +
|
| 8 | +~~~~~~~~~~~~~~~~~~~~~~~~~ RESULTS ~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 9 | +┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ |
| 10 | +│ ● ● │ │ ● │ │ ● ● │ │ ● ● │ │ │ |
| 11 | +│ ● │ │ │ │ ● │ │ ● │ │ ● │ |
| 12 | +│ ● ● │ │ ● │ │ ● ● │ │ ● ● │ │ │ |
| 13 | +└─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ |
| 14 | +""" |
| 15 | + |
| 16 | +import random |
| 17 | + |
| 18 | +DICE_ART = { |
| 19 | + 1: ( |
| 20 | + "┌─────────┐", |
| 21 | + "│ │", |
| 22 | + "│ ● │", |
| 23 | + "│ │", |
| 24 | + "└─────────┘", |
| 25 | + ), |
| 26 | + 2: ( |
| 27 | + "┌─────────┐", |
| 28 | + "│ ● │", |
| 29 | + "│ │", |
| 30 | + "│ ● │", |
| 31 | + "└─────────┘", |
| 32 | + ), |
| 33 | + 3: ( |
| 34 | + "┌─────────┐", |
| 35 | + "│ ● │", |
| 36 | + "│ ● │", |
| 37 | + "│ ● │", |
| 38 | + "└─────────┘", |
| 39 | + ), |
| 40 | + 4: ( |
| 41 | + "┌─────────┐", |
| 42 | + "│ ● ● │", |
| 43 | + "│ │", |
| 44 | + "│ ● ● │", |
| 45 | + "└─────────┘", |
| 46 | + ), |
| 47 | + 5: ( |
| 48 | + "┌─────────┐", |
| 49 | + "│ ● ● │", |
| 50 | + "│ ● │", |
| 51 | + "│ ● ● │", |
| 52 | + "└─────────┘", |
| 53 | + ), |
| 54 | + 6: ( |
| 55 | + "┌─────────┐", |
| 56 | + "│ ● ● │", |
| 57 | + "│ ● ● │", |
| 58 | + "│ ● ● │", |
| 59 | + "└─────────┘", |
| 60 | + ), |
| 61 | +} |
| 62 | +DIE_HEIGHT = len(DICE_ART[1]) |
| 63 | +DIE_WIDTH = len(DICE_ART[1][0]) |
| 64 | +DIE_FACE_SEPARATOR = " " |
| 65 | + |
| 66 | + |
| 67 | +def parse_input(input_string): |
| 68 | + """Return `input_string` as an integer between 1 and 6. |
| 69 | +
|
| 70 | + Check if `input_string` is an integer number between 1 and 6. |
| 71 | + If so, return an integer with the same value. Otherwise, tell |
| 72 | + the user to enter a valid number and quit the program. |
| 73 | + """ |
| 74 | + if input_string.strip() in {"1", "2", "3", "4", "5", "6"}: |
| 75 | + return int(input_string) |
| 76 | + else: |
| 77 | + print("Please enter a number from 1 to 6.") |
| 78 | + raise SystemExit(1) |
| 79 | + |
| 80 | + |
| 81 | +def roll_dice(num_dice): |
| 82 | + """Return a list of integers with length `num_dice`. |
| 83 | +
|
| 84 | + Each integer in the returned list is a random number between |
| 85 | + 1 and 6, inclusive. |
| 86 | + """ |
| 87 | + roll_results = [] |
| 88 | + for _ in range(num_dice): |
| 89 | + roll = random.randint(1, 6) |
| 90 | + roll_results.append(roll) |
| 91 | + return roll_results |
| 92 | + |
| 93 | + |
| 94 | +def generate_dice_faces_diagram(dice_values): |
| 95 | + """Return an ASCII diagram of dice faces from `dice_values`. |
| 96 | +
|
| 97 | + The string returned contains an ASCII representation of each die. |
| 98 | + For example, if `dice_values = [4, 1, 3, 2]` then the string |
| 99 | + returned looks like this: |
| 100 | +
|
| 101 | + ~~~~~~~~~~~~~~~~~~~ RESULTS ~~~~~~~~~~~~~~~~~~~ |
| 102 | + ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ |
| 103 | + │ ● ● │ │ │ │ ● │ │ ● │ |
| 104 | + │ │ │ ● │ │ ● │ │ │ |
| 105 | + │ ● ● │ │ │ │ ● │ │ ● │ |
| 106 | + └─────────┘ └─────────┘ └─────────┘ └─────────┘ |
| 107 | + """ |
| 108 | + dice_faces = _get_dice_faces(dice_values) |
| 109 | + dice_faces_rows = _generate_dice_faces_rows(dice_faces) |
| 110 | + |
| 111 | + # Generate header with the word "RESULTS" centered |
| 112 | + width = len(dice_faces_rows[0]) |
| 113 | + diagram_header = " RESULTS ".center(width, "~") |
| 114 | + |
| 115 | + dice_faces_diagram = "\n".join([diagram_header] + dice_faces_rows) |
| 116 | + return dice_faces_diagram |
| 117 | + |
| 118 | + |
| 119 | +def _get_dice_faces(dice_values): |
| 120 | + dice_faces = [] |
| 121 | + for value in dice_values: |
| 122 | + dice_faces.append(DICE_ART[value]) |
| 123 | + return dice_faces |
| 124 | + |
| 125 | + |
| 126 | +def _generate_dice_faces_rows(dice_faces): |
| 127 | + dice_faces_rows = [] |
| 128 | + for row_idx in range(DIE_HEIGHT): |
| 129 | + row_components = [] |
| 130 | + for die in dice_faces: |
| 131 | + row_components.append(die[row_idx]) |
| 132 | + row_string = DIE_FACE_SEPARATOR.join(row_components) |
| 133 | + dice_faces_rows.append(row_string) |
| 134 | + return dice_faces_rows |
| 135 | + |
| 136 | + |
| 137 | +# ~~~ App's main code block ~~~ |
| 138 | +# 1. Get and validate user's input |
| 139 | +num_dice_input = input("How many dice do you want to roll? [1-6] ") |
| 140 | +num_dice = parse_input(num_dice_input) |
| 141 | +# 2. Roll the dice |
| 142 | +roll_results = roll_dice(num_dice) |
| 143 | +# 3. Generate the ASCII diagram of dice faces |
| 144 | +dice_face_diagram = generate_dice_faces_diagram(roll_results) |
| 145 | +# 4. Display the diagram |
| 146 | +print(f"\n{dice_face_diagram}") |
0 commit comments