-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpython_learning_game.py
More file actions
247 lines (218 loc) ยท 10.2 KB
/
Copy pathpython_learning_game.py
File metadata and controls
247 lines (218 loc) ยท 10.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
#!/usr/bin/env python3
import random
import sys
import io
import contextlib
from typing import Dict, List, Tuple, Optional, Any, Callable
class PythonLearningGame:
def __init__(self):
self.current_level = 1
self.score = 0
self.tasks = self.generate_tasks()
def generate_tasks(self) -> Dict[int, List[Dict[str, Any]]]:
return {
1: [ # Basic arithmetic
{
"description": "Write code to add 2 to 2",
"check": lambda result: result == 4,
"solution": "print(2 + 2)",
"hint": "Use the + operator for addition"
},
{
"description": "Write code to subtract 3 from 10",
"check": lambda result: result == 7,
"solution": "print(10 - 3)",
"hint": "Use the - operator for subtraction"
},
{
"description": "Write code to multiply 5 by 4",
"check": lambda result: result == 20,
"solution": "print(5 * 4)",
"hint": "Use the * operator for multiplication"
}
],
2: [ # Variables and strings
{
"description": "Create a variable called 'name' with value 'Python' and print it",
"check": lambda result: result == "Python",
"solution": "name = 'Python'\nprint(name)",
"hint": "Use variable assignment: name = 'value'"
},
{
"description": "Print the length of the string 'hello world'",
"check": lambda result: result == 11,
"solution": "print(len('hello world'))",
"hint": "Use the len() function to get string length"
},
{
"description": "Convert the number 42 to a string and print it",
"check": lambda result: str(result) == "42",
"solution": "print(str(42))",
"hint": "Use the str() function to convert to string"
}
],
3: [ # Lists and basic operations
{
"description": "Create a list [1, 2, 3] and print its first element",
"check": lambda result: result == 1,
"solution": "my_list = [1, 2, 3]\nprint(my_list[0])",
"hint": "List indexing starts from 0"
},
{
"description": "Add the number 4 to the list [1, 2, 3] and print the list",
"check": lambda result: isinstance(result, list) and len(result) == 4 and result == [1, 2, 3, 4],
"solution": "my_list = [1, 2, 3]\nmy_list.append(4)\nprint(my_list)",
"hint": "Use the append() method to add to a list"
},
{
"description": "Print the sum of numbers in list [1, 2, 3, 4]",
"check": lambda result: result == 10,
"solution": "print(sum([1, 2, 3, 4]))",
"hint": "Use the sum() function with a list"
}
],
4: [ # Conditionals
{
"description": "Check if 10 is greater than 5 and print True or False",
"check": lambda result: result == True,
"solution": "print(10 > 5)",
"hint": "Use comparison operators like >, <, ==, !="
},
{
"description": "Write code that prints 'even' if number 8 is even",
"check": lambda result: result == "even",
"solution": "if 8 % 2 == 0:\n print('even')",
"hint": "Use modulo operator % to check for even numbers"
},
{
"description": "Print the maximum of 15 and 25",
"check": lambda result: result == 25,
"solution": "print(max(15, 25))",
"hint": "Use the max() function to find the larger value"
}
],
5: [ # Functions
{
"description": "Define a function that returns 5 and call it to print the result",
"check": lambda result: result == 5,
"solution": "def my_function():\n return 5\n\nprint(my_function())",
"hint": "Use 'def' to define a function and 'return' to return a value"
},
{
"description": "Create a function that takes two numbers and returns their sum",
"check": lambda result: result == 7, # Check the printed result, not the function
"solution": "def add_numbers(a, b):\n return a + b\n\nprint(add_numbers(3, 4))",
"hint": "Functions can take parameters and use them in calculations"
}
]
}
def get_current_task(self) -> Optional[Dict[str, Any]]:
if self.current_level not in self.tasks:
return None
available_tasks = self.tasks[self.current_level]
if not available_tasks:
return None
return random.choice(available_tasks)
def execute_code(self, code: str) -> Any:
"""Execute user code and capture the output"""
try:
# Create a string buffer to capture output
buffer = io.StringIO()
# Execute the code and capture stdout
with contextlib.redirect_stdout(buffer):
# Create a local namespace for execution
local_vars = {}
exec(code, {}, local_vars)
# Get the output and try to evaluate it
output = buffer.getvalue().strip()
# If there's output, try to parse it as Python literal
if output:
try:
return eval(output, {"__builtins__": {}}, {})
except:
return output
# If no print output but there's a variable that might be the answer
for var_name, var_value in local_vars.items():
if not var_name.startswith('__'):
return var_value
return None
except Exception as e:
return f"Error: {str(e)}"
def check_answer(self, task: Dict[str, Any], user_code: str) -> Tuple[bool, Any]:
"""Check if user's code produces the correct result"""
result = self.execute_code(user_code)
if isinstance(result, str) and result.startswith("Error:"):
return False, result
try:
is_correct = task["check"](result)
return is_correct, result
except Exception as e:
return False, f"Error checking answer: {str(e)}"
def display_welcome(self):
print("๐ฎ Welcome to Python Learning Game! ๐ฎ")
print("Learn Python coding with interactive challenges!")
print("Type 'quit' to exit, 'hint' for a hint, 'skip' to skip a task")
print("-" * 50)
def display_task(self, task: Dict[str, Any]):
print(f"\n๐ Level {self.current_level}")
print(f"๐ฏ Task: {task['description']}")
print("\n๐ก Write your Python code below (multiple lines OK):")
def run(self):
self.display_welcome()
while True:
task = self.get_current_task()
if not task:
print(f"\n๐ Congratulations! You've completed all {len(self.tasks)} levels!")
print(f"๐ Final Score: {self.score}")
break
self.display_task(task)
# Get user input (single-line for simplicity)
print(">>> ", end="")
try:
user_code = input().strip()
except EOFError:
print(f"\n๐ Thanks for playing! Final Score: {self.score}")
return
if user_code == "quit":
print(f"\n๐ Thanks for playing! Final Score: {self.score}")
return
elif user_code == "hint":
print(f"๐ก Hint: {task['hint']}")
continue
elif user_code == "skip":
print("โญ๏ธ Task skipped!")
self.current_level = min(self.current_level + 1, len(self.tasks))
continue
# Check the answer
is_correct: bool
result: Any
is_correct, result = self.check_answer(task, user_code)
# Check the answer
is_correct: bool
result: Any
is_correct, result = self.check_answer(task, user_code)
if is_correct:
print("โ
You are right! Well done! ๐")
self.score += 10
print(f"๐ Score: {self.score}")
# Move to next level after 3 correct answers in current level
if self.score % 30 == 0: # Every 30 points (3 correct answers)
self.current_level = min(self.current_level + 1, len(self.tasks))
if self.current_level <= len(self.tasks):
print(f"๐ Level up! Now at Level {self.current_level}")
else:
print("โ Sorry, not this time.")
if isinstance(result, str) and result.startswith("Error:"):
print(f"๐ Error in your code: {result}")
print(f"๐ก The correct code is:")
print("```python")
print(task["solution"])
print("```")
# Move to next task in same level
continue
print("\n" + "="*50)
print("Ready for the next challenge? Press Enter to continue...")
input()
if __name__ == "__main__":
game = PythonLearningGame()
game.run()