GamePage.dart 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. import 'dart:math';
  2. import 'package:flutter/cupertino.dart';
  3. var baiZiBean;
  4. var heiZiBean;
  5. List<BaiZiBean> baiZiBeanList = []; //所有白子的坐标点集合
  6. List<HeiZiBean> heiZiBeanList = []; //所有黑子的坐标点集合
  7. var flag = true; //默认为白子先走
  8. ///简单的实现五子棋效果
  9. class GamePage extends StatefulWidget {
  10. @override
  11. State<StatefulWidget> createState() => GamePageState();
  12. }
  13. class GamePageState extends State<GamePage> {
  14. @override
  15. Widget build(BuildContext context) {
  16. return Center(
  17. child: Column(
  18. mainAxisAlignment: MainAxisAlignment.center,
  19. crossAxisAlignment: CrossAxisAlignment.center,
  20. mainAxisSize: MainAxisSize.max,
  21. children: <Widget>[
  22. Padding(
  23. padding: EdgeInsets.only(bottom: 15.0),
  24. child: CupertinoButton.filled(
  25. padding: EdgeInsets.all(0.0),
  26. child: Text("重置棋盘"),
  27. onPressed: () {
  28. setState(() {
  29. baiZiBean = null;
  30. heiZiBean = null;
  31. baiZiBeanList.clear();
  32. heiZiBeanList.clear();
  33. });
  34. }),
  35. ),
  36. GestureDetector(
  37. onTapDown: (topDownDetails) {
  38. setState(() {
  39. var position = topDownDetails.localPosition;
  40. if (flag) {
  41. baiZiBean = BaiZiBean(position.dx, position.dy);
  42. } else {
  43. heiZiBean = HeiZiBean(position.dx, position.dy);
  44. }
  45. });
  46. },
  47. child: CustomPaint(
  48. size: Size(300.0, 300.0),
  49. painter: WuZiQiPainter(),
  50. ))
  51. ]),
  52. );
  53. }
  54. }
  55. class WuZiQiPainter extends CustomPainter {
  56. List<CrossOverBean> _crossOverBeanList = [];
  57. @override
  58. void paint(Canvas canvas, Size size) {
  59. // TODO: implement paint
  60. _crossOverBeanList.clear();
  61. canvas.drawColor(CupertinoColors.systemGrey, BlendMode.colorBurn);//重绘下整个界面的画布北京颜色
  62. double mWidth = size.width / 15;
  63. double mHeight = size.height / 15;
  64. //设置画笔,画棋盘背景
  65. var mPaint = Paint()
  66. ..isAntiAlias = true //抗锯齿
  67. ..style = PaintingStyle.fill //填充
  68. ..color = Color(0x77cdb175); //背景为纸黄色
  69. canvas.drawRect(
  70. Rect.fromCenter(
  71. center: Offset(size.width / 2, size.height / 2),
  72. width: size.width,
  73. height: size.height),
  74. mPaint);
  75. //画棋盘网格
  76. mPaint
  77. ..style = PaintingStyle.stroke
  78. ..color = CupertinoColors.systemGrey6
  79. ..strokeWidth = 1.0;
  80. for (var i = 0; i <= 15; i++) {
  81. //画横线
  82. canvas.drawLine(
  83. Offset(0, mHeight * i), Offset(size.width, mHeight * i), mPaint);
  84. }
  85. for (var i = 0; i <= 15; i++) {
  86. //画竖线
  87. canvas.drawLine(
  88. Offset(mWidth * i, 0), Offset(mWidth * i, size.height), mPaint);
  89. }
  90. //记录横竖线所有的交叉点
  91. for (int i = 0; i <= 15; i++) {
  92. for (int j = 0; j <= 15; j++) {
  93. _crossOverBeanList.add(CrossOverBean(mWidth * j, mHeight * i));
  94. }
  95. }
  96. //求两个点之间的距离,让棋子正确的显示在坐标轴上面
  97. if(flag && baiZiBean != null){
  98. //白子棋
  99. var dx = baiZiBean._dx;
  100. var dy = baiZiBean._dy;
  101. for(int i=0; i<_crossOverBeanList.length; i++){
  102. var absX = (dx - _crossOverBeanList[i]._dx).abs(); //两个点的x轴距离
  103. var absY = (dy - _crossOverBeanList[i]._dy).abs(); //两个点的y轴距离
  104. var s = sqrt(absX*absX + absY*absY); //利用直角三角形求斜边公式(a的平方 + b的平方 = c的平方)来计算出两点间的距离
  105. if(s <= mWidth/2 - 2){ // 触摸点到棋盘坐标坐标点距离小于等于棋子半径,那么
  106. //找到离触摸点最近的棋盘坐标点并记录保存下来
  107. baiZiBeanList.add(BaiZiBean(_crossOverBeanList[i]._dx, _crossOverBeanList[i]._dy));
  108. flag = false; //白子下完了,该黑子下了
  109. break;
  110. }
  111. }
  112. }else if(heiZiBean != null){
  113. //黑子棋
  114. var dx = heiZiBean._dx;
  115. var dy = heiZiBean._dy;
  116. for(int i=0; i<_crossOverBeanList.length; i++){
  117. var absX = (dx - _crossOverBeanList[i]._dx).abs();
  118. var absY = (dy - _crossOverBeanList[i]._dy).abs();
  119. var s = sqrt(absX*absX + absY*absY);
  120. if(s <= mWidth/2 - 2){
  121. heiZiBeanList.add(HeiZiBean(_crossOverBeanList[i]._dx, _crossOverBeanList[i]._dy));
  122. flag = true;
  123. break;
  124. }
  125. }
  126. }
  127. //画白子
  128. mPaint
  129. ..style = PaintingStyle.fill
  130. ..color = CupertinoColors.white;
  131. if (baiZiBeanList.isNotEmpty) {
  132. for (int i = 0; i < baiZiBeanList.length; i++) {
  133. canvas.drawCircle(Offset(baiZiBeanList[i]._dx, baiZiBeanList[i]._dy),
  134. min(mWidth / 2, mHeight / 2) - 2, mPaint);
  135. }
  136. }
  137. //画黑子
  138. mPaint..color = CupertinoColors.black;
  139. if (heiZiBeanList.isNotEmpty) {
  140. for (int i = 0; i < heiZiBeanList.length; i++) {
  141. canvas.drawCircle(Offset(heiZiBeanList[i]._dx, heiZiBeanList[i]._dy),
  142. min(mWidth / 2, mHeight / 2) - 2, mPaint);
  143. }
  144. }
  145. }
  146. //在实际场景中正确利用此回调可以避免重绘开销,本示例我们简单的返回true
  147. @override
  148. bool shouldRepaint(CustomPainter oldDelegate) {
  149. // TODO: implement shouldRepaint
  150. return true;
  151. }
  152. }
  153. class BaiZiBean {
  154. double _dx;
  155. double _dy;
  156. BaiZiBean(this._dx, this._dy);
  157. }
  158. class HeiZiBean {
  159. double _dx;
  160. double _dy;
  161. HeiZiBean(this._dx, this._dy);
  162. }
  163. ///记录棋盘上横竖线的交叉点
  164. class CrossOverBean {
  165. double _dx;
  166. double _dy;
  167. CrossOverBean(this._dx, this._dy);
  168. }