flutter_sudoku/lib/widgets/sudoku_board.dart
2025-11-07 17:07:22 +09:00

96 lines
3.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:sudoku_app/models/sudoku_theme.dart'; // 👈 [추가]
class SudokuBoard extends StatelessWidget {
final int blockSize;
final SudokuTheme theme; // 👈 [추가]
final List<int> cells; // 👈 [수정] List<String> -> List<int>
final List<int> originalCells; // 👈 [수정] List<String> -> List<int>
final int? selectedIndex;
final int? selectedNumberPad;
final Set<int> incorrectCells;
final Function(int) onCellTapped;
const SudokuBoard({
super.key,
required this.blockSize,
required this.theme, // 👈 [추가]
required this.cells,
required this.originalCells,
required this.selectedIndex,
required this.selectedNumberPad,
required this.incorrectCells,
required this.onCellTapped,
});
@override
Widget build(BuildContext context) {
final int gridSize = blockSize * blockSize;
final double fontSize = (gridSize > 9) ? (gridSize > 16 ? 12 : 16) : 24;
return AspectRatio(
aspectRatio: 1.0,
child: GridView.builder(
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: gridSize,
),
itemCount: gridSize * gridSize,
itemBuilder: (context, index) {
int row = index ~/ gridSize;
int col = index % gridSize;
int cellValue = cells[index]; // 👈 [수정] 0, 1, 10...
bool isEditable = (originalCells[index] == 0); // 👈 [수정] "0" -> 0
bool isSelected = (index == selectedIndex);
bool isHighlighted = (cellValue != 0 && // 👈 [수정]
selectedNumberPad != null &&
cellValue == selectedNumberPad); // 👈 [수정] int == int 비교
bool isIncorrect = incorrectCells.contains(index);
BorderSide thickBorder = const BorderSide(color: Colors.black, width: 2.0);
BorderSide thinBorder = const BorderSide(color: Colors.grey, width: 0.5);
return GestureDetector(
onTap: () => onCellTapped(index),
child: Container(
alignment: Alignment.center,
decoration: BoxDecoration(
color: isIncorrect
? Colors.red.shade100
: isSelected
? Colors.blue.shade100
: isHighlighted
? Colors.blue.shade200
: isEditable
? Colors.white
: Colors.grey.shade200,
border: Border(
top: (row == 0) ? thickBorder : thinBorder,
left: (col == 0) ? thickBorder : thinBorder,
right: (col == gridSize - 1) ? thickBorder : (col % blockSize == blockSize - 1) ? thickBorder : thinBorder,
bottom: (row == gridSize - 1) ? thickBorder : (row % blockSize == blockSize - 1) ? thickBorder : thinBorder,
),
),
child: Text(
// 🔽 [수정] 0이면 비우고, 아니면 테마 기호("1", "A", "🍎") 표시
cellValue == 0 ? '' : theme.getSymbol(cellValue),
style: TextStyle(
fontSize: fontSize,
fontWeight: FontWeight.bold,
color: isIncorrect
? Colors.red.shade900
: isEditable
? Colors.blue
: Colors.black,
),
),
),
);
},
),
);
}
}