Flutter로 구현된 가변 Tic Tae Toe 코드
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
void main() => runApp(const MyApp()); | |
class MyApp extends StatelessWidget { | |
const MyApp({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
// Remove the debug banner | |
debugShowCheckedModeBanner: false, | |
theme: ThemeData( | |
primarySwatch: Colors.amber, | |
), | |
title: 'coolsharp', | |
home: const TicTacToe(), | |
); | |
} | |
} | |
class TicTacToe extends StatefulWidget { | |
const TicTacToe({super.key}); | |
@override | |
State<TicTacToe> createState() => _TicTacToeState(); | |
} | |
class _TicTacToeState extends State<TicTacToe> { | |
String _currentPlayer = 'X'; | |
String _result = 'Tic Tac Toe'; | |
final List<String> _options = ['3칸', '4칸', '5칸', '6칸', '7칸', '8칸']; | |
String _selectOption = '3칸'; | |
int _blockCounter = 3; | |
List<String>? _boardList = List.generate(9, (index) => ''); | |
void _play(int index) { | |
setState(() { | |
if (!_checkWin() && '' == _boardList![index]) { | |
_boardList![index] = _currentPlayer; | |
if (_checkWin()) { | |
_result = '$_currentPlayer 승'; | |
} else if (_checkEndGame()) { | |
_result = '비김'; | |
} else { | |
_currentPlayer = _currentPlayer == 'X' ? 'O' : 'X'; | |
_result = '$_currentPlayer 차례'; | |
} | |
} | |
}); | |
} | |
bool _checkWin() { | |
bool isWin = true; | |
for(int row = 0; row < _blockCounter; row++) { | |
isWin = true; | |
for (int col = 0; col < _blockCounter; col++) { | |
if (_boardList![row * _blockCounter + col] != _currentPlayer) { | |
isWin = false; | |
break; | |
} | |
} | |
if (isWin) { | |
return true; | |
} | |
} | |
for(int col = 0; col < _blockCounter; col++) { | |
isWin = true; | |
for (int row = 0; row < _blockCounter; row++) { | |
if (_boardList![row * _blockCounter + col] != _currentPlayer) { | |
isWin = false; | |
break; | |
} | |
} | |
if (isWin) { | |
return true; | |
} | |
} | |
isWin = true; | |
for (int i = 0; i < _blockCounter; i++) { | |
if (_boardList![i * _blockCounter + i] != _currentPlayer) { | |
isWin = false; | |
break; | |
} | |
} | |
if (isWin) { | |
return true; | |
} | |
isWin = true; | |
for (int i = 0; i < _blockCounter; i++) { | |
if (_boardList![i * _blockCounter + (_blockCounter - 1 - i)] != _currentPlayer) { | |
isWin = false; | |
break; | |
} | |
} | |
if (isWin) { | |
return true; | |
} | |
return false; | |
} | |
bool _checkEndGame() { | |
for (int i = 0; i < _boardList!.length; i++) { | |
if ('' == _boardList![i]) { | |
return false; | |
} | |
} | |
return true; | |
} | |
void _reset() { | |
for (int i = 0; i < _boardList!.length; i++) { | |
_boardList![i] = ''; | |
} | |
setState(() { | |
_currentPlayer = 'X'; | |
_result = 'Tic Tac Toe'; | |
}); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
title: Text(_result), | |
actions: [ | |
IconButton( | |
onPressed: () { | |
_reset(); | |
}, | |
icon: Icon(Icons.refresh)) | |
], | |
), | |
body: Column( | |
children: [ | |
Row( | |
mainAxisAlignment: MainAxisAlignment.center, | |
crossAxisAlignment: CrossAxisAlignment.center, | |
children: [ | |
const Text('칸 선택 : '), | |
DropdownButton( | |
value: _selectOption, | |
icon: const Icon(Icons.arrow_drop_down), | |
items: _options.map((String item) { | |
return DropdownMenuItem(value: item, child: Text(item)); | |
}).toList(), | |
onChanged: (String? value) { | |
_selectOption = value!; | |
switch (_selectOption) { | |
case '3칸': | |
_blockCounter = 3; | |
break; | |
case '4칸': | |
_blockCounter = 4; | |
break; | |
case '5칸': | |
_blockCounter = 5; | |
break; | |
case '6칸': | |
_blockCounter = 6; | |
break; | |
case '7칸': | |
_blockCounter = 7; | |
break; | |
case '8칸': | |
_blockCounter = 8; | |
break; | |
} | |
setState(() { | |
_boardList = List.generate( | |
_blockCounter * _blockCounter, (index) => ''); | |
}); | |
}) | |
], | |
), | |
Expanded( | |
child: GridView.builder( | |
itemCount: _blockCounter * _blockCounter, | |
padding: const EdgeInsets.all(10), | |
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( | |
crossAxisCount: _blockCounter, | |
childAspectRatio: 1, | |
crossAxisSpacing: 10, | |
mainAxisSpacing: 10), | |
itemBuilder: (context, index) { | |
int row = index ~/ _blockCounter; | |
int col = index % _blockCounter; | |
Color colFace = Colors.white; | |
Color colBorder = Colors.black; | |
switch (_boardList![index]) { | |
case 'X': | |
colFace = Colors.blue; | |
colBorder = Colors.blueAccent; | |
break; | |
case 'O': | |
colFace = Colors.red; | |
colBorder = Colors.redAccent; | |
break; | |
} | |
return GestureDetector( | |
onTap: () { | |
_play(index); | |
print('row : $row, col : $col'); | |
}, | |
child: Container( | |
decoration: BoxDecoration( | |
border: Border.all(width: 2, color: colBorder), | |
color: colFace, | |
boxShadow: const [ | |
BoxShadow( | |
color: Colors.grey, | |
spreadRadius: 2, | |
blurRadius: 3, | |
offset: Offset(0, 5)) | |
]), | |
child: Center( | |
child: Text(_boardList![index]), | |
), | |
), | |
); | |
}), | |
), | |
], | |
), | |
); | |
} | |
} |
댓글
댓글 쓰기