Skip to content

Commit 0f42c5c

Browse files
committed
Upgrade python version and python doctest for a CI
1 parent 68e6a0c commit 0f42c5c

8 files changed

Lines changed: 280 additions & 93 deletions

‎.github/workflows/python.yml‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
runs-on: ubuntu-latest
1717
strategy:
1818
matrix:
19-
python-version: ['3.10', '3.11', '3.12']
19+
python-version: ['3.11', '3.12','3.13','3.14']
2020
steps:
2121
- name: Checkout repository
2222
uses: actions/checkout@v4
@@ -29,7 +29,7 @@ jobs:
2929
- name: Install all dependencies and tools
3030
run: |
3131
python -m pip install --upgrade pip
32-
pip install ruff bandit mypy pytest codespell requests-mock colorama
32+
pip install ruff bandit mypy pytest codespell requests-mock colorama pytest-xdist
3333
3434
- name: Run Codespell check
3535
run: codespell --skip "*.json,*.txt,*.pdf,*.md" || true
@@ -38,7 +38,7 @@ jobs:
3838
run: bandit -r . --skip B101,B105 -ll || true
3939

4040
- name: Run Pytest tests
41-
run: pytest --tb=short || true
41+
run: pytest --doctest-modules -tb=short -n auto || true
4242

4343
- name: Run Ruff checks with ignored rules
4444
run: ruff check . --ignore B904,B905,EM101,EXE001,G004,ISC001,PLC0415,PLC1901,PLW060,PLW1641,PLW2901,PT011,PT018,PT028,S101,S311,SIM905,SLF001,F405

‎aaa.txt‎

Whitespace-only changes.

‎check if a number positive , negative or zero‎

Lines changed: 0 additions & 16 deletions
This file was deleted.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
num = float(input("Enter a number: "))
2+
if num > 0:
3+
print("Positive number")
4+
elif num == 0:
5+
print("Zero")
6+
else:
7+
print("Negative number")
8+
num = float(input("Enter a number: "))
9+
if num >= 0:
10+
if num == 0:
11+
print("Zero")
12+
else:
13+
print("Positive number")
14+
else:
15+
print("Negative number")

‎memorygame.py‎

Lines changed: 168 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,208 @@
1-
from random import *
2-
from turtle import *
1+
#!/usr/bin/env python3
2+
"""
3+
Memory Game – a tile‑matching game using the Turtle graphics library.
4+
5+
The board consists of 64 tiles (8x8 grid), each hiding one of 32 possible
6+
icons (numbers 0–31). The player clicks on tiles to reveal them. When two
7+
consecutive revealed tiles show the same icon, they remain visible; otherwise
8+
they are hidden again. The game continues until all pairs are found.
9+
10+
Dependencies:
11+
- Python standard library: random, turtle
12+
- freegames (optional) – provides a car image; if not available, remove
13+
the car-related lines and the game will work without it.
14+
15+
Author: Adapted from a freegames example.
16+
Date: 2026-07-12
17+
"""
18+
19+
import random
20+
import turtle
321

422
from freegames import path
523

24+
# ----------------------------------------------------------------------------
25+
# Game constants and global state
26+
# ----------------------------------------------------------------------------
27+
28+
# Load the car image (used as a decorative stamp on the board)
629
car = path("car.gif")
30+
31+
# Create a list of 64 tile values: each number from 0 to 31 appears exactly twice
732
tiles = list(range(32)) * 2
33+
34+
# State dictionary: 'mark' stores the index of the currently selected tile
35+
# (the first tile clicked in a pair attempt). None means no tile is selected.
836
state = {"mark": None}
37+
38+
# Boolean list indicating whether each tile is hidden (True = hidden, False = shown)
939
hide = [True] * 64
1040

1141

12-
def square(x, y):
13-
"Draw white square with black outline at (x, y)."
14-
up()
15-
goto(x, y)
16-
down()
17-
color("black", "white")
18-
begin_fill()
19-
for count in range(4):
20-
forward(50)
21-
left(90)
22-
end_fill()
42+
# ----------------------------------------------------------------------------
43+
# Drawing utilities
44+
# ----------------------------------------------------------------------------
45+
46+
47+
def square(x: float, y: float) -> None:
48+
"""
49+
Draw a 50x50 white square with a black outline at the given coordinates.
50+
51+
The turtle starts at the bottom‑left corner of the square and draws it
52+
counter‑clockwise using the standard forward/left movements.
53+
54+
Args:
55+
x: X‑coordinate of the bottom‑left corner.
56+
y: Y‑coordinate of the bottom‑left corner.
57+
"""
58+
turtle.up()
59+
turtle.goto(x, y)
60+
turtle.down()
61+
turtle.color("black", "white")
62+
turtle.begin_fill()
63+
for _ in range(4):
64+
turtle.forward(50)
65+
turtle.left(90)
66+
turtle.end_fill()
67+
68+
69+
# ----------------------------------------------------------------------------
70+
# Coordinate and index conversion
71+
# ----------------------------------------------------------------------------
72+
2373

74+
def index(x: float, y: float) -> int:
75+
"""
76+
Convert screen coordinates to a tile index (0‑63).
2477
25-
def index(x, y):
26-
"Convert (x, y) coordinates to tiles index."
78+
The board is arranged in an 8x8 grid, with each cell being 50x50 pixels.
79+
The origin (0,0) is at the centre of the screen; the board occupies the
80+
region from (-200, -200) to (200, 200). This function maps a click
81+
position to the corresponding tile index, row‑major order.
82+
83+
Args:
84+
x: X‑coordinate of the click (in turtle screen units).
85+
y: Y‑coordinate of the click.
86+
87+
Returns:
88+
int: Tile index (0 to 63).
89+
"""
2790
return int((x + 200) // 50 + ((y + 200) // 50) * 8)
2891

2992

30-
def xy(count):
31-
"Convert tiles count to (x, y) coordinates."
93+
def xy(count: int) -> tuple[float, float]:
94+
"""
95+
Convert a tile index to screen coordinates of its bottom‑left corner.
96+
97+
This is the inverse of `index()`. The calculation uses integer division
98+
and modulo to determine the row and column.
99+
100+
Args:
101+
count: Tile index (0‑63).
102+
103+
Returns:
104+
tuple[float, float]: (x, y) coordinates of the tile's bottom‑left corner.
105+
"""
32106
return (count % 8) * 50 - 200, (count // 8) * 50 - 200
33107

34108

35-
def tap(x, y):
36-
"Update mark and hidden tiles based on tap."
109+
# ----------------------------------------------------------------------------
110+
# Game logic
111+
# ----------------------------------------------------------------------------
112+
113+
114+
def tap(x: float, y: float) -> None:
115+
"""
116+
Handle a mouse click event on the canvas.
117+
118+
This is the core game logic. It performs the following steps:
119+
1. Determine which tile was clicked.
120+
2. If no tile is currently marked (state["mark"] is None),
121+
mark this tile as the first of a pair.
122+
3. If a tile is already marked and it is not the same tile,
123+
compare the values of the marked tile and the newly clicked tile:
124+
- If they match (same number), reveal both tiles permanently.
125+
- If they do not match, unmark the tile (keep it hidden).
126+
4. If the same tile is clicked twice, it simply remains marked.
127+
128+
Args:
129+
x: X‑coordinate of the click.
130+
y: Y‑coordinate of the click.
131+
"""
37132
spot = index(x, y)
38133
mark = state["mark"]
39134

135+
# If no mark, or we clicked the same tile again, or the values differ:
136+
# just set the mark to the new spot (or keep it if it's the same).
137+
# Note: if the two values are different, we don't hide anything – the
138+
# tile will be drawn hidden again in the next draw() cycle because
139+
# hide[spot] remains True.
40140
if mark is None or mark == spot or tiles[mark] != tiles[spot]:
41141
state["mark"] = spot
42142
else:
143+
# Values match: reveal both tiles permanently.
43144
hide[spot] = False
44145
hide[mark] = False
146+
# Clear the mark so the next click starts a new pair.
45147
state["mark"] = None
46148

47149

48-
def draw():
49-
"Draw image and tiles."
50-
clear()
51-
goto(0, 0)
52-
shape(car)
53-
stamp()
54-
150+
def draw() -> None:
151+
"""
152+
Redraw the entire board and schedule the next animation frame.
153+
154+
This function is called repeatedly via turtle.ontimer() to update the
155+
display. It:
156+
- Clears the canvas.
157+
- Draws the decorative car image at the centre.
158+
- Draws a white square for every hidden tile.
159+
- If a tile is marked and currently hidden, it writes the tile's
160+
value (number) on top of that square.
161+
- Finally, triggers a redraw after 100 milliseconds.
162+
163+
The use of turtle.tracer(False) and manual turtle.update() ensures
164+
smooth animation without flickering.
165+
"""
166+
turtle.clear()
167+
turtle.goto(0, 0)
168+
turtle.shape(car)
169+
turtle.stamp() # Place the car image permanently on the canvas
170+
171+
# Draw all tiles that are still hidden.
55172
for count in range(64):
56173
if hide[count]:
57174
x, y = xy(count)
58175
square(x, y)
59176

177+
# If a tile is marked and hidden, display its value.
60178
mark = state["mark"]
61-
62179
if mark is not None and hide[mark]:
63180
x, y = xy(mark)
64-
up()
65-
goto(x + 2, y)
66-
color("black")
67-
write(tiles[mark], font=("Arial", 30, "normal"))
181+
turtle.up()
182+
turtle.goto(x + 2, y) # Shift slightly for better centering
183+
turtle.color("black")
184+
turtle.write(tiles[mark], font=("Arial", 30, "normal"))
185+
186+
turtle.update() # Refresh the screen with all drawn elements
187+
turtle.ontimer(draw, 100) # Schedule next redraw (10 fps)
68188

69-
update()
70-
ontimer(draw, 100)
71189

190+
# ----------------------------------------------------------------------------
191+
# Main setup and execution
192+
# ----------------------------------------------------------------------------
72193

73-
shuffle(tiles)
74-
setup(420, 420, 370, 0)
75-
addshape(car)
76-
hideturtle()
77-
tracer(False)
78-
onscreenclick(tap)
194+
# Shuffle the tile values to randomise the board layout.
195+
random.shuffle(tiles)
196+
197+
# Configure the turtle window.
198+
turtle.setup(420, 420, 370, 0) # Window size, start x, start y
199+
turtle.addshape(car) # Register the car image as a shape
200+
turtle.hideturtle() # Hide the turtle cursor (we only need drawings)
201+
turtle.tracer(False) # Disable automatic updates for performance
202+
turtle.onscreenclick(tap) # Bind mouse clicks to the tap() function
203+
204+
# Start the game loop.
79205
draw()
80-
done()
206+
207+
# Keep the window open (this is the main event loop).
208+
turtle.done()

0 commit comments

Comments
 (0)