# Simple game to learn common port numbers for Sec+ exam

This is a basic game asking for the common port number for a protocol used. I designed it with the intent on helping myself and others who are going after their Sec+ exam to memorize the ports needed. Any in cleaning up the code or better ways to process the lists would be most appreciated.

import random
import sys
from os import system

#List of lists of ports and protocols for SEC+ exam
numbers= {'TCP 22':('ssh','scp','sftp'),'TCP AND UDP 53':('DNS'),
'TCP 20 and 21':('FTP'),'UDP 69':('TFTP'),'443':('FTPS,HTTPS,SSL VPN443'),'TCP 25':('SMTP'),
'TCP 110':('POP3'), 'TCP 143':('Imap'),'TCP 23':('TelNet'),'TCP 49':('TACACS+'),'UDP 49':('TACACS'),
'UDP 1701':('L2TP'),'TCP and UDP 1723':('PPTP'),'TCP and UDP 3389':('RDP'),
'UDP 67,68':('DHCP'),'TCP 80':('HTTP'),'TCP AND UDP 88':('Kerberos'), 'TCP 119':('NNTP'),'UDP 161':('SNMP'),
'UDP 514':('Syslog'),'TCP 443':('HTTPS/SSL VPN/FTPS'),'UDP 67 and 68':('DHCP'),'UDP 500':('ISAKMP VPN'),'TCP AND UDP 162':('SNMP Trap')
}

#List of ports for random choice
random_gen= ('TCP 20 and 21','TCP 22','UDP 69','TCP 443','TCP 25','TCP 110','TCP 143','TCP 23','TCP 49','UDP 49','UDP 500'
,'UDP 1701','TCP and UDP 1723','TCP and UDP 3389','TCP AND UDP 53','UDP 67 and 68','TCP 80','TCP AND UDP 88','TCP 119','UDP 161',
'TCP AND UDP 162','UDP 514'
)

def Sec_port_game():
correct = 0
incorrect = 0
system('cls')
print("""This will ask you for port number and weather or not is uses TCP or UDP for communication. Answer must be formatted like 'TCP 443'
if the uses both the answer must be formatted 'TCP and UDP' followed by the port number. If it uses more than one port it must be formatted like
67 and 68. The lowest number will always come first.""")

while (1==1):
#Keeps track of total answred
total = incorrect + correct
#prints the amount of answers that you have correct, incorrect and total
print(f"correct {correct} incorrect {incorrect}: {total} total answered out of 20 questions.")
#creates the random port for question
rand_choice= random.choice(random_gen)
#Total of 20 random ports will ne assesed. Gives the total correct, incorrect and % coorect.
if(total == 20):
print(f"Total correct is {correct} total incorrectis {incorrect}")
print("Precent correct is")
print(correct/20 * 100)
#Asks the player if they would like to play again
play_again=input('''Would you like to play again? "yes" or "no" any other response to exit the program
:''')
#if player wants to play agin sets the correct and incorrect to 0 to start exit if and start over.
if(play_again.upper() == 'YES') or (play_again.upper() == 'Y'):
correct =0
incorrect = 0
#If the player does not wish to play again thanks them for playing and break out of the while loop wo exit the game.
else:
print("Thank you for playing")
break
#Takes the answer for the random port
answer = input(f"""Port number for {numbers[rand_choice]}?
:""")

#Checks the answer to see if it's correct
print('CORRECT!')
correct += 1

else:
print(f"""Nice try but the correct port is {rand_choice}""")
incorrect += 1

#starts the game
Sec_port_game()

• i will suggest you to use pylint for get feedback of your program – camp0 Dec 16 '19 at 9:23

## Naming things is hard

Two of your variables have terrible names. To see what I mean, try to guess what the following variables contain, by only looking at their name, but not at your code:

• numbers
• random_gen

All the other variables are named really good. They name exactly their purpose or accurately describe their content, like incorrect or answer.

## Source code layout

In the first section you list the quiz questions. Each of these questions should be on its own line of the code, to clearly show to the reader how the code is structured. That way, all quiz questions are listed nicely below each other, and it's easily possible to count the questions by checking their line numbers in the editor.

It's also easy to see that the 443 question is missing the protocol (TCP), which is difficult to see in the current layout.

The 443 question uses a single string as answer, while the 22 question uses a tuple of the application protocols. Which one is correct, or are they both? I doubt so.

What is the difference between AND and and in the questions? If there is none, choose one spelling and stick to it.

## Redundancy

Instead of repeating the question names in random_gen, you can just use the expression numbers.keys().

Instead of writing the number 20 everywhere, better describe what you really mean by that number, which is len(questions). (By now you should have renamed the numbers variable to the more appropriate questions).

## Typos

• Imap is spelled IMAP
• VPN443 is spelled VPN
• incorrectis is spelled incorrect is

## Bug

The program does not guarantee that you get each question once. Instead of using random_choice for each of the questions you should rather shuffle the questions and then just iterate over them.

## Code improvements

• Instead of (1==1), better write True.
• Instead of var == first or var == second, better write var in (first, second).
• There is no need to enclose each condition of an if or while in parentheses. That's only necessary in C and related languages. In Python and Go, it is considered bad style.

The function Sec_port_game should simply be named quiz since that is more specific than game, and at the same time makes the code independent from the Sec+ exam.

The function quiz should take the questions as a parameter, so that you can call it like this:

quiz(secplus_questions)
quiz(popular_rock_bands_questions)


It could be implemented like this:

import random
from typing import Dict

def quiz(questions: Dict[str, str]):

shuffled_keys = random.shuffle(list(questions.keys()))
for key in shuffled_keys:
question = questions[key]



Apart from mentioned by @Roland, I don't like the infinite loop. If you think about it, player plays multiple games until he wants to finish, each game made of 20 moves.

To me that sounds something like:

while(wants_to_play):

# setup new game
for question_index in range(20):
# process single question

# ask if he wants to play another and set wants_to_play accordingly