├── .gitignore ├── images ├── image1.png └── image2.png ├── README.md └── credit_cards.py /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.swn 3 | *.swp 4 | .*.swn 5 | .*.swo 6 | .*.swp 7 | .*~ 8 | -------------------------------------------------------------------------------- /images/image1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gamithra/credit-card-game/HEAD/images/image1.png -------------------------------------------------------------------------------- /images/image2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gamithra/credit-card-game/HEAD/images/image2.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## MEMORIZE THE CREDIT CARD NUMBERS 2 | 3 | [play web version here](https://mokytis.gitlab.io/credit-card-game/) (rewritten in JS by Luke Spademan) 4 | 5 | 6 | speed-memorizing credit card numbers is a very useful life skill and you should get better at it 7 | 8 | to play, literally just clone the repository or download *credit_cards.py*, and run 9 | 10 | python3 credit_cards.py 11 | nothing else*. no dependencies. just one file. try it 12 | 13 | **python3 required* 14 | 15 | 16 | ### this is what it looks like 17 | or should look like depending on if your terminal supports all these cool colors and unicode symbols 18 | ![this is the first screenshot](/images/image1.png) 19 | 20 | important feature you should know about: *it also randomizes names, bank logos and colours every time* 21 | 22 | ![this is the second screenshot](/images/image2.png) 23 | 24 | important feature 2 you should know about: *it also randomizes these red and green words and you're welcome to suggest words to add to the list, submit a pull request :-)* 25 | 26 | 27 | ### choose between two modes: 28 | - unlimited time 29 | - time-limited 30 | 31 | to set a time limit, just run the script with an optional argument: 32 | 33 | python3 credit_cards.py [seconds] 34 | 35 | like, for example, 5 seconds: 36 | 37 | python3 credit_cards.py 5 38 | but use something bigger than 5. you probably can't do it in 5 seconds (yet). hopefully, you soon will, with the use of this invaluable tool 39 | 40 | 41 | 42 | *disclaimer: whenever memorizing credit card numbers, it's good practice to check that the card owner consents to the activity. consent is important* 43 | -------------------------------------------------------------------------------- /credit_cards.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import random 5 | import time 6 | import os 7 | os.system('color') # apparently this makes colors work for windows users 8 | 9 | main = "" 10 | cvc = "" 11 | date = "" 12 | margin = " "*8 13 | seconds = "" 14 | 15 | failure_words = ["Bollocks", "Bugger", "ffs", "Shite", "Damn", "Goddammit", "Gah", "Nope", "Boo", "Dagnabbit", "For goodness' sake", "Nuh-uh", "Nah", "Negative"] 16 | success_words = ["Woohooo!", "No way", "PARTY!", "Hell yeah", "Well done", "Good job", "Awww yeah", "Indeed", "Hurrah", "Whoopee", "Hooray", "You're a master", "Nice", "Awesome", "Amazing", "Keep up the good work", "Keep it up"] 17 | names = ["John Smith", "Gamithra M.", "Donald Trump", "Foo Bar", "Jane Doe", "David", "Karl Marx", "Abe Lincoln", "Elon Musk", "Steve Jobs", "S. Wozniak", "Willy Wonka", "Bill Gates", "Henry Ford", "Ada Lovelace",] 18 | banks = ['\u263B', '\u262F', '\u2605', '\u2622', '\u2665', '\u266B', '\u2691', '\u2654'] 19 | 20 | # failure and success colors 21 | fc = "\x1B[38;5;124m" 22 | sc = "\x1B[38;5;76m" 23 | cd = "\x1B[0m" # default color 24 | cbg = "" 25 | 26 | 27 | def clear_screen(): 28 | if os.name == 'nt': 29 | os.system('cls') 30 | else: 31 | sys.stdout.write('\x1Bc') 32 | sys.stdout.flush() 33 | 34 | 35 | def print_card(): 36 | global main, date, cvc, cbg, cd, banks 37 | 38 | cl = str(16 + random.randint(0,5) * 36 + random.randint(0, 20)) # magic values to make sure the colours are on the darker side 39 | cbg = "\x1B[48;5;" + cl + "m" # colored background 40 | ctx = "\x1B[38;5;" + cl + "m" # colored text (for the corners) 41 | cch = "\x1B[48;5;136m" 42 | 43 | name, bank = random.choice(names), random.choice(banks) 44 | 45 | card_front = [ctx + '\u259F' + cd + cbg +" "*26 + cd + ctx + '\u2599' + cd, \ 46 | cbg + " "*24 + bank + " "*3 + cd, \ 47 | cbg + " "*28 + cd, \ 48 | cbg + " "*3 + cch + " "*4 + cbg + " "*21 + cd, \ 49 | cbg + " "*28 + cd, \ 50 | cbg + " "+ main + " "*(25-len(main)) + cd, \ 51 | cbg + " "+ name + (14-len(name))*" " + date + " " + cd, \ 52 | ctx + '\u259C' + cd + cbg +" "*26 + cd + ctx + '\u259B' + cd, \ 53 | ] 54 | 55 | card_back = [ctx + '\u259F' + cd + cbg +" "*26 + cd + ctx + '\u2599' + cd, \ 56 | cd + " "*28 + cd, \ 57 | cd + " "*28 + cd, \ 58 | cbg + " "*28 + cd, \ 59 | cbg + " "*3 + "\x1B[48;5;231m" + "\x1B[38;5;16m" + " "*8 + cvc + cbg + " "*14 + cd, \ 60 | cbg + " "*28 + cd, \ 61 | cbg + " "*28 + cd, \ 62 | ctx + '\u259C' + cd + cbg +" "*26 + cd + ctx + '\u259B' + cd, \ 63 | ] 64 | 65 | 66 | for i in range(len(card_front)): 67 | print(margin + card_front[i] + " " + card_back[i]) 68 | 69 | print("") 70 | 71 | def luhn(digits): 72 | """ 73 | Calc the correct CC checksum for our random CC number. 74 | input - digits - is a list of integers. 75 | """ 76 | odds_sum = sum(digits[-2::-2]) 77 | evens_sum = sum([sum(divmod(2*i, 10)) for i in digits[-1::-2]]) 78 | sum_digits = odds_sum+evens_sum 79 | # because we have an odd num of digits, we just take the mod 10 80 | return (10-(sum_digits % 10)) % 10 81 | 82 | def do_checksum(pan): 83 | pan_digits = list(map(int,pan.replace("-",""))) 84 | return pan[:-1]+str(luhn(pan_digits[:-1])) 85 | 86 | 87 | def ask(): 88 | global main, date, cvc, seconds 89 | print(margin + "Memorize as many digits as you can!") 90 | print("") 91 | 92 | main = "" 93 | 94 | # add numbers that start with zero 95 | for i in range(4): 96 | main += str(random.randint(1,9999)).zfill(4) 97 | if i < 3: main += "-" 98 | # added checksum - luhn 99 | main = do_checksum(main) 100 | 101 | cvc = str(random.randint(100, 999)) 102 | 103 | expires_day = random.randint(1, 12) 104 | if expires_day < 10: 105 | expires_day = "0" + str(expires_day) 106 | date = str(expires_day) + "/" + str(random.randint(20, 28)) 107 | 108 | 109 | sys.stdout.write("\r") 110 | print_card() 111 | if seconds != "": 112 | for remaining in range(seconds, 0, -1): 113 | sys.stdout.write("\r") 114 | sys.stdout.write(margin + " {:2d} seconds remaining.".format(remaining)) 115 | sys.stdout.flush() 116 | time.sleep(1) 117 | else: 118 | input(margin + "Press Enter when you're done!") 119 | clear_screen() 120 | 121 | 122 | def calc_score(a, b, date=False): 123 | score = 0 124 | if date: 125 | if a[0:2] == b[0:2]: 126 | score += 1 127 | if a[3:5] == b[3:5]: 128 | score += 1 129 | else: 130 | for i in range(min(len(a), len(b))): 131 | if a[i] != "-" or a[i] == "/": 132 | if a[i] == b[i]: 133 | score += 1 134 | 135 | return score 136 | 137 | 138 | 139 | def success(): 140 | global sc, cd 141 | return sc + success_words[random.randint(0, len(success_words)-1)] + "!" + cd 142 | 143 | def failure(): 144 | global fc, cd 145 | return fc + failure_words[random.randint(0, len(failure_words)-1)] + "!" + cd 146 | 147 | def guess(): 148 | global main, date, cvc, cbg, cd 149 | 150 | 151 | for i in range(4): 152 | print("") 153 | 154 | guess_main = input(margin + cbg + "What was the credit card number? \n" + cd + margin + "Format: xxxx-xxxx-xxxx-xxxx\n"+ margin) 155 | score_main = calc_score(guess_main, main) 156 | if guess_main == main: 157 | print(margin + success() + " You got it right!") 158 | elif score_main > 0: 159 | print(margin + failure() + " It was " + main + ", but you got " + str(score_main) + " digits right!") 160 | else: 161 | print(margin + failure() + " It was " + main + ".") 162 | print("") 163 | 164 | guess_cvc = input(margin + cbg + "What was the CVC?\n" + cd + margin + "Format: xxx\n"+margin) 165 | score_cvc = calc_score(guess_cvc, cvc) 166 | if guess_cvc == cvc: 167 | print(margin + success() + " That's correct.") 168 | elif score_cvc > 0: 169 | print(margin + failure() + " It was " + cvc + ", but you got " + str(score_cvc) + " digits right!") 170 | else: 171 | print(margin + failure() + " It was " + cvc + ".") 172 | print("") 173 | 174 | guess_date = input(margin + cbg + "What was the expiry date?\n" + cd + margin + "Format: xx/xx\n"+margin) 175 | score_date = calc_score(guess_date, date, date=True) 176 | if guess_date == date: 177 | print(margin + success() + " That's it.") 178 | elif score_date > 0: 179 | print(margin + failure() + " It was " + date + ", but you got " + str(score_date) + " digits right!") 180 | else: 181 | print(margin + failure() + " It was " + date + ".") 182 | 183 | print("") 184 | print(margin + "\x1B[48;5;231m" + "\x1B[38;5;16m" + " Score for this round: " + str(int((score_main + score_cvc + score_date)/21*100)) + "% " + cd) 185 | 186 | print("") 187 | print("") 188 | 189 | print(margin + "Too easy? To set a time limit, just run:\n"+margin+"'python3 credit_card.py [seconds]'!") 190 | print("") 191 | 192 | print(margin + "\x1B[38;5;22m" + "made by @gamithra" + cd) 193 | play_again = input(margin + "Press Enter to play again - or 'q' to quit!") 194 | if play_again == "q": 195 | print(margin + "See you again soon :-)") 196 | else: 197 | play() 198 | 199 | 200 | def play(): 201 | global seconds 202 | clear_screen() 203 | if len(sys.argv) > 1: 204 | seconds = int(sys.argv[1]) 205 | for i in range(4): 206 | print("") 207 | 208 | ask() 209 | guess() 210 | 211 | if __name__ == "__main__": 212 | play() 213 | 214 | 215 | --------------------------------------------------------------------------------