Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ python app.py

7. Open http://127.0.0.1:5000 in your browser.



## Running Tests
To run the test suite, ensure your virtual environment is activated and run:
```bash
pytest



## Project Instructions

Use GitHub Copilot to refactor the code for this game to add more advanced features. The goal is to create a more modern and maintainable codebase and add additional functionality to the final product. You can use any combination of code completion and chat features, like Ask, Edit, or Agent modes.
Expand Down
Binary file added Screenshots/grid_styling_prompt.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Screenshots/hint button.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Screenshots/initial_tests.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Screenshots/otherresponseafterrejection.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Screenshots/rejected prompt.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Screenshots/scoreboard_prompt.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Screenshots/timer.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Screenshots/toggle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Screenshots/unique_solution_prompt.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
167 changes: 167 additions & 0 deletions instruction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
# GitHub Copilot Instructions for Sudoku Application

## Project Overview
This repository contains a modern 9×9 Sudoku web application built with Flask for the Python backend and vanilla JavaScript/CSS for the frontend. The application should feel accessible, responsive, and easy to extend while keeping the core architecture clean and modular.

The application should:
- generate Sudoku puzzles on the backend in `starter/sudoku_logic.py`
- serve the game UI from `starter/templates/index.html`
- manage game state and validation through `starter/static/main.js`
- style the board and interaction states in `starter/static/styles.css`
- keep the backend lightweight with Flask and minimal dependencies

## Code Standards and Architecture

### Refactor Legacy Code to Modern Standards
- Use a modular architecture:
- keep backend routes and API handling in `starter/app.py`
- keep Sudoku generation and solving logic in `starter/sudoku_logic.py`
- keep rendering and browser interactions in `starter/static/main.js`
- keep styling in `starter/static/styles.css`
- Prefer small, single-purpose functions and avoid large monolithic blocks.
- Keep Python functions testable and avoid side effects where possible.
- In JavaScript, organize logic into reusable helper functions.
- Use comments to explain:
- non-trivial business logic
- puzzle generation and solving strategies
- API input/output expectations
- **Error Handling**: Implement consistent error handling patterns
- Use try/catch blocks for async operations
- Validate user inputs at boundaries
- Provide meaningful error messages to users
- Log errors appropriately for debugging

### Error Handling
- Validate all user input at boundary points.
- Use `try/catch` for async operations in JavaScript.
- Return clean JSON error responses from Flask, and use HTTP 400 for bad client requests.
- Show user-facing messages for invalid board submission, network errors, and unexpected backend failures.
- Do not crash the app on malformed input.

### Build & Run Requirements
- The application must install cleanly with `pip install -r requirements.txt`.
- It must run via `python app.py` or `flask run` without startup errors.
- Browser developer tools should show no console errors for normal usage.

## User Interface Requirements

### Responsive and Accessible Design
- Use plain CSS only; do not add framework dependencies.
- Ensure the Sudoku board is responsive and mobile-friendly.
- Keep the grid centered and proportional on all screen sizes.
- Use `em` or responsive units for scalable typography.
- Use minimum touch target sizes of about 44×44px for buttons on mobile.
- Avoid layout shifts while the board loads or updates.

### 3×3 Grid Styling
- Visually distinguish 3×3 sub-grids with alternating background shades or stronger borders.
- Keep the grid easy to scan and readable.
- Prefilled cells should look different from editable cells.

### Dark Mode Support
- Implement a light/dark theme toggle.
- Persist the user theme preference in `localStorage`.
- Ensure text and interactive controls maintain at least WCAG AA contrast.

### Keyboard & Accessibility
- Use semantic HTML and accessible ARIA roles as needed.
- All interactive UI elements must be keyboard accessible.
- Implement arrow-key navigation between cells and Enter to confirm input when appropriate.
- Provide visible focus indicators.
- For screen readers, label cells with row/column context and state, such as "Row 1, Column 2, empty" or "Row 1, Column 2, prefilled 5".
- Provide announcements or status text for errors, hints, and completion.
- Do not rely on color alone; use text or icons for invalid state and completion feedback.

## Core Sudoku Logic

### Puzzle Generation
- Generate puzzles with exactly one valid solution.
- Create a fully solved 9×9 board first, then remove cells while preserving uniqueness.
- Use backtracking and/or constraint propagation for both generation and uniqueness checking.
- Keep generation randomized so repeated plays are not the same.
- Control difficulty by the number of filled cells:
- Easy: 40-45 prefilled cells
- Medium: 30-35 prefilled cells
- Hard: 25-28 prefilled cells
- Prefilled cells must be immutable in the UI.

### Unique Solution Checking
- When removing a cell, verify that the board still has only one solution.
- Implement a solver that counts up to 2 possible completions and stops early once multiple solutions are found.
- Reject removals that cause a second valid solution.
- Maintain the solution only on the server side.

### Validation and Feedback
- Validate the board in real time as the user enters numbers:
- row constraint
- column constraint
- 3×3 sub-grid constraint
- Highlight conflicting cells with a clear visual style.
- If a user submits the board, return detailed validation results rather than just success/failure.
- Detect completion when all cells are filled and valid.
- Show a success modal or message with completion statistics.

## Interactive Features

### Core Game Interactions
- Implement a working Hint feature:
- reveal one correct number in an empty cell
- mark the hinted cell as locked/prefilled
- count hints separately for scoring
- Implement a Check button that validates the current board against the solution and reports incorrect cells.
- Provide user-friendly feedback for each action.
- Ensure the board remains playable while validation is happening.

### Timer
- Start timing when a new puzzle loads or when the first cell is edited.
- Display elapsed time in MM:SS.
- Stop the timer on puzzle completion.
- Optionally pause the timer when the user navigates away or switches tabs.

## Advanced Features

### Number Tracking Visualization
- Display the usage count of each digit (1-9) on the board.
- Show which numbers are complete and how many remain.
- Allow users to tap/click a number to highlight all board instances.
- Use text/icons so the feature remains accessible.

### Note Mode
- Provide a toggle or shortcut to enter note mode.
- In note mode, typed digits should add pencil marks to the selected cell.
- Allow multiple candidate notes in one cell.
- Clear notes when the user enters a final number.
- Display notes in smaller or superscript text.
- Indicate note mode visibly in the UI.

## Testing and Quality
- Add unit tests for Sudoku generation and validation in `tests/`.
- Test that generated boards are valid and puzzles follow Sudoku rules.
- Test that uniqueness checking rejects ambiguous boards.
- Add tests for Flask route behavior and JSON API responses.
- Keep tests deterministic and easy to run.
- Use descriptive test case names and document expected behavior.

## Error Handling Practices
- Validate all inputs before use.
- Ensure the backend returns clear JSON errors for invalid requests.
- Handle network failures gracefully on the frontend.
- Display friendly error messages in the UI.
- Avoid showing raw exception details to the user.
- Use consistent message styling for success, warning, and error states.

## Future Features and Improvements
- Add difficulty selection to the UI and persist the selected difficulty.
- Add a local leaderboard stored in `localStorage`.
- Add a theme toggle and save preference persistently.
- Add puzzle stats like best time, shortest completion, and hint usage.
- Add an undo/redo feature for cell entry.
- Add keyboard shortcuts for note mode, check, hint, and new game.

## Copilot Suggestion Guidance
- Keep changes aligned with the existing Flask + vanilla JS architecture.
- Avoid introducing heavy frontend frameworks or unnecessary dependencies.
- Prefer simple, maintainable solutions.
- Suggest backend improvements in `starter/app.py` and `starter/sudoku_logic.py`.
- Suggest frontend improvements in `starter/static/main.js`, `starter/static/styles.css`, and `starter/templates/index.html`.
- Focus on accessibility, responsive behavior, and game correctness.
Binary file added starter/__pycache__/app.cpython-312.pyc
Binary file not shown.
Binary file added starter/__pycache__/sudoku_logic.cpython-312.pyc
Binary file not shown.
87 changes: 71 additions & 16 deletions starter/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,86 @@
'solution': None
}


def json_error(message, status=400):
response = jsonify({'error': message})
response.status_code = status
return response


def validate_board(board):
if not isinstance(board, list) or len(board) != sudoku_logic.SIZE:
return False

for row in board:
if not isinstance(row, list) or len(row) != sudoku_logic.SIZE:
return False
for value in row:
if not isinstance(value, int) or value < 0 or value > sudoku_logic.SIZE:
return False
return True


@app.route('/')
def index():
return render_template('index.html')

@app.route('/new')
def new_game():
clues = int(request.args.get('clues', 35))
puzzle, solution = sudoku_logic.generate_puzzle(clues)
CURRENT['puzzle'] = puzzle
CURRENT['solution'] = solution
return jsonify({'puzzle': puzzle})
try:
clues = request.args.get('clues')
difficulty = request.args.get('difficulty', 'easy')

if clues is not None:
try:
clues = int(clues)
if clues < 0 or clues > sudoku_logic.SIZE * sudoku_logic.SIZE:
raise ValueError
except ValueError:
return json_error('Invalid clues parameter. Must be an integer between 0 and 81.', 400)

if difficulty not in sudoku_logic.DIFFICULTY_SETTINGS:
return json_error('Invalid difficulty. Must be easy, medium, or hard.', 400)

puzzle, solution = sudoku_logic.generate_puzzle(clues=clues, difficulty=difficulty)
CURRENT['puzzle'] = puzzle
CURRENT['solution'] = solution
return jsonify({'puzzle': puzzle, 'solution': solution, 'difficulty': difficulty})
except Exception:
app.logger.exception('Unexpected error while generating a new game')
return json_error('Unable to generate a new game.', 500)


@app.route('/check', methods=['POST'])
def check_solution():
data = request.json
board = data.get('board')
solution = CURRENT.get('solution')
if solution is None:
return jsonify({'error': 'No game in progress'}), 400
incorrect = []
for i in range(sudoku_logic.SIZE):
for j in range(sudoku_logic.SIZE):
if board[i][j] != solution[i][j]:
incorrect.append([i, j])
return jsonify({'incorrect': incorrect})
try:
if not request.is_json:
return json_error('Request must be JSON.', 400)

data = request.get_json(silent=True)
if data is None:
return json_error('Malformed JSON request body.', 400)

board = data.get('board')
if board is None:
return json_error('Missing board data in request.', 400)

if not validate_board(board):
return json_error('Board must be a 9x9 grid of integers between 0 and 9.', 400)

solution = CURRENT.get('solution')
if solution is None:
return json_error('No game in progress.', 400)

incorrect = []
for i in range(sudoku_logic.SIZE):
for j in range(sudoku_logic.SIZE):
if board[i][j] != solution[i][j]:
incorrect.append([i, j])
return jsonify({'incorrect': incorrect})
except Exception:
app.logger.exception('Unexpected error while checking the board')
return json_error('Unable to validate the board.', 500)

if __name__ == '__main__':
app.run(debug=True)
Loading