Read and write the high score file and show the stored high score

Refs #24
Refs #25
Refs #26
Task: MIL-004#2
Task: MIL-004#3
Task: MIL-004#4
This commit is contained in:
2026-10-13 14:38:51 +08:00
parent c20ea6c616
commit 4ef3874bb1
5 changed files with 251 additions and 7 deletions
+53
View File
@@ -0,0 +1,53 @@
"""! @file
@brief Reading and writing the high score file: the day-24 file lectures.
The high score is kept as text in a file, so that it is still there the next time
the game is started. Both functions open the file with a `with` statement, which
closes it again even when something goes wrong, as the lecture teaches. The module
does not import `turtle`, so it needs no display and the tests use a temporary
file.
"""
from snake_game.constants import (
DEFAULT_HIGH_SCORE,
HIGH_SCORE_FILE,
HIGH_SCORE_FILE_ENCODING,
)
def write_high_score(high_score: int, path: str = HIGH_SCORE_FILE) -> None:
"""! @brief Replace the content of the file with the high score, as text.
The file is opened in write mode `w`, so the old content is overwritten and a
file that does not exist yet is created.
@param high_score The high score to store.
@param path The file to write; defaults to `HIGH_SCORE_FILE`.
"""
with open(path, mode="w", encoding=HIGH_SCORE_FILE_ENCODING) as data:
data.write(str(high_score))
def read_high_score(path: str = HIGH_SCORE_FILE) -> int:
"""! @brief Read the high score from the file and turn the text into a number.
A file that does not exist yet is created holding `DEFAULT_HIGH_SCORE`. A file
that does not hold a whole number, or holds a negative one, is read as
`DEFAULT_HIGH_SCORE` and is left as it is; the next new high score replaces it.
@param path The file to read; defaults to `HIGH_SCORE_FILE`.
@return The stored high score, 0 or more.
"""
try:
with open(path, encoding=HIGH_SCORE_FILE_ENCODING) as data:
text = data.read()
except FileNotFoundError:
write_high_score(DEFAULT_HIGH_SCORE, path)
return DEFAULT_HIGH_SCORE
except UnicodeDecodeError:
return DEFAULT_HIGH_SCORE
try:
high_score = int(text)
except ValueError:
return DEFAULT_HIGH_SCORE
return max(high_score, DEFAULT_HIGH_SCORE)
+15 -5
View File
@@ -10,6 +10,7 @@ module first.
from turtle import Turtle
from snake_game.constants import (
HIGH_SCORE_FILE,
HIGH_SCORE_LABEL,
SCORE_LABEL,
SCOREBOARD_ALIGNMENT,
@@ -17,18 +18,25 @@ from snake_game.constants import (
SCOREBOARD_FONT,
SCOREBOARD_POSITION,
)
from snake_game.high_score_file import read_high_score, write_high_score
class Scoreboard(Turtle):
"""! @brief Shows the score as text at the top centre of the screen."""
def __init__(self) -> None:
"""! @brief Set the scoreboard up and write the score 0."""
def __init__(self, path: str = HIGH_SCORE_FILE) -> None:
"""! @brief Set the scoreboard up and write the score 0 and the stored best.
@param path The file that keeps the high score; defaults to
`HIGH_SCORE_FILE`.
"""
super().__init__()
## @brief The file that keeps the high score between games.
self.path = path
## @brief The number of foods the snake has eaten since the last reset.
self.score = 0
## @brief The largest score reached so far.
self.high_score = 0
## @brief The largest score reached so far, as stored in the file.
self.high_score = read_high_score(path)
self.color(SCOREBOARD_COLOR)
self.penup()
self.hideturtle()
@@ -53,9 +61,11 @@ class Scoreboard(Turtle):
"""! @brief Keep the best score, start a new game and write the scoreboard.
When the score is higher than the high score, it becomes the new high
score. The score then goes back to 0.
score and is written to the file; a lower or equal score does not write
the file. The score then goes back to 0.
"""
if self.score > self.high_score:
self.high_score = self.score
write_high_score(self.high_score, self.path)
self.score = 0
self.update_scoreboard()