Как составить кроссворд на флаттере? - PullRequest
0 голосов
/ 19 июня 2020

Не могу понять слово, которое пользователь перетащил пальцем. Я никак не могу выбрать области, которых касаюсь, вижу, что маркеры не работают, при перетаскивании получаю только первое касание. Приближается алфавит и правильное слово. С точки зрения функциональности - доска позволяет нажимать любые две буквы, одну за другой. Если они оба указывают путь к правильному ответу - он обводится. В противном случае круг удаляется. Надеюсь, это поможет вам набрать asp код.

like pic

class WordMarker extends StatelessWidget {
  const WordMarker({
    Key key,
    @required this.rect,
    @required this.startIndex,
    this.color = Colors.green,
    this.width = 2.0,
    this.radius = 6.0,
  }) : super(key: key);

  final Rect rect;
  final Color color;
  final double width;
  final double radius;
  final int startIndex;

  @override
  Widget build(BuildContext context) {
    return Positioned.fromRect(
      rect: rect,
      child: DecoratedBox(
        decoration: BoxDecoration(
          border: Border.all(
            color: color,
            width: width,
          ),
          borderRadius: BorderRadius.circular(radius),
        ),
      ),
    );
  }

  WordMarker copyWith({Rect rect}) {
    return WordMarker(
      key: key,
      rect: rect ?? this.rect,
      startIndex: startIndex,
      color: color,
      width: width,
      radius: radius,
    );
  }
}

class WordSearchGame extends StatefulWidget {
  const WordSearchGame(
      {Key key,
      this.alphabet = const [
        'I',
        'A',
        'G',
        'M',
        'F',
        'Y',
        'L',
        'I',
        'R',
        'V',
        'P',
        'D',
        'B',
        'R',
        'A',
        'I',
        'N',
        'S',
        'T',
        'O',
        'R',
        'M',
        'E',
        'S',
        'S',
        'T',
        'R',
        'A',
        'T',
        'E',
        'G',
        'Y',
        'E',
        'A',
        'B',
        'W',
        'O',
        'M',
        'G',
        'O',
        'A',
        'L',
        'S',
        'X',
        'S',
        'Q',
        'U',
        'K',
        'H',
        'J',
        'P',
        'M',
        'D',
        'W',
        'S'
      ],
      this.words = const [
        'ARTHER',
        'GOLDEN',
        'AMADEUS',
        'IDEAS',
        'GOALS',
        'BRAINSTORM'
      ],
      this.wordsPerLine = 11})
      : super(key: key);

  final int wordsPerLine;
  final List<String> alphabet;
  final List<String> words;

  @override
  _WordSearchGameState createState() => _WordSearchGameState();
}

class _WordSearchGameState extends State<WordSearchGame> {
  final wordMarkers = <WordMarker>[];
  int correctAnswers = 0;
  var uniqueLetters;

  @override
  void initState() {
    super.initState();
    uniqueLetters = widget.alphabet
        .map((letter) => {'letter': letter, 'key': GlobalKey()})
        .toList();
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        BackgroundImage(StringConstant.asset__background, fullHeight(context),
            fullWidth(context)),
        Scaffold(
          body: Container(
            child: GridView.count(
              padding: new EdgeInsets.all(10.0),
              crossAxisCount: widget.wordsPerLine,
              children: uniqueLetters
                  .map<Widget>(
                    (val) => GestureDetector(
                      behavior: HitTestBehavior.opaque,
                      onTap: () {
                        print(uniqueLetters.indexOf(val));
                        setState(() {
                          final key = val['key'];
                          final renderBox =
                              key.currentContext.findRenderObject();
                          final markerRect = renderBox.localToGlobal(
                                  Offset.zero,
                                  ancestor: context.findRenderObject()) &
                              renderBox.size;
                          if (wordMarkers.length == correctAnswers) {
                            addMarker(markerRect, uniqueLetters.indexOf(val));
                          } else if (widget.words.contains(pathAsString(
                              wordMarkers.last.startIndex,
                              uniqueLetters.indexOf(val)))) {
                            wordMarkers.last =
                                adjustedMarker(wordMarkers.last, markerRect);
                            ++correctAnswers;
                          } else {
                            wordMarkers.removeLast();
                          }
                        });
                      },
                      child: Center(
                        child: Padding(
                          padding: const EdgeInsets.all(4.0),
                          key: val['key'],
                          child: Text(
                            val['letter'],
                          ),
                        ),
                      ),
                    ),
                  )
                  .toList(),
            ),
          ),
        ),
      ],
    );
  }

  void addMarker(Rect rect, int startIndex) {
    wordMarkers.add(WordMarker(
      rect: rect,
      startIndex: startIndex,
    ));
  }

  WordMarker adjustedMarker(WordMarker originalMarker, Rect endRect) {
    return originalMarker.copyWith(
        rect: originalMarker.rect.expandToInclude(endRect));
  }

  String pathAsString(int start, int end) {
    final isHorizontal =
        start ~/ widget.wordsPerLine == end ~/ widget.wordsPerLine;
    final isVertical = start % widget.wordsPerLine == end % widget.wordsPerLine;

    String result = '';

    if (isHorizontal) {
      result = widget.alphabet.sublist(start, end + 1).join();
    } else if (isVertical) {
      for (int i = start;
          i < widget.alphabet.length;
          i += widget.wordsPerLine) {
        result += widget.alphabet[i];
      }
    }

    return result;
  }
}

1 Ответ

0 голосов
/ 19 июня 2020
class WordSearchGame extends StatefulWidget {
  @override
  GridState createState() {
    return new GridState();
  }
}

class GridState extends State<WordSearchGame> {
  final Set<int> selectedIndexes = Set<int>();
  final key = GlobalKey();
  final Set<_Foo> _trackTaped = Set<_Foo>();
  List<String> alphabet=[
    'I',
    'A',
    'G',
    'M',
    'F',
    'Y',
    'L',
    'I',
    'R',
    'V',
    'P',
    'D',
    'B',
    'R',
    'A',
    'I',
    'N',
    'S',
    'T',
    'O',
    'R',
    'M',
    'E',
    'S',
    'S',
    'T',
    'R',
    'A',
    'T',
    'E',
    'G',
    'Y',
    'E',
    'A',
    'B',
    'W',
    'O',
    'M',
    'G',
    'O',
    'A',
    'L',
    'S',
    'X',
    'S',
    'Q',
    'U',
    'K',
    'H',
    'J',
    'P',
    'M',
    'D',
    'W',
    'S'
  ];
  List<String> words= [
  'ARTHER',
  'GOLDEN',
  'AMADEUS',
  'IDEAS',
  'GOALS',
  'BRAINSTORM'
  ];

  _detectTapedItem(PointerEvent event) {
    final RenderBox box = key.currentContext.findRenderObject();
    final result = BoxHitTestResult();
    Offset local = box.globalToLocal(event.position);
    if (box.hitTest(result, position: local)) {
      for (final hit in result.path) {
        /// temporary variable so that the [is] allows access of [index]
        final target = hit.target;
        if (target is _Foo && !_trackTaped.contains(target)) {
          _trackTaped.add(target);
          _selectIndex(target.index);
        }
      }
    }
  }

  _selectIndex(int index) {
    setState(() {
      selectedIndexes.add(index);

    });
  }


  String word='';
  String getWord(Set<int> selectedIndexes,List<String> alphabet){
    word='';
    selectedIndexes.forEach((element) {word=word+alphabet[element];});
//    word+=alphabet[selectedIndexes.elementAt(0)];
    return word;
  }

  @override
  Widget build(BuildContext context) {
    return Listener(
      onPointerDown: _detectTapedItem,
      onPointerMove: _detectTapedItem,
      onPointerUp: _clearSelection,

      child: GridView.builder(
        key: key,
        itemCount: alphabet.length,
        physics: NeverScrollableScrollPhysics(),
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 11,
          childAspectRatio: 0.7,
          crossAxisSpacing: 5.0,
          mainAxisSpacing: 5.0,
        ),
        itemBuilder: (context, index) {
          return Foo(
            index: index,
            child: Container(
              child: Text(alphabet[index]),
              color: selectedIndexes.contains(index) ? Colors.red : Colors.blue,
            ),
          );
        },
      ),
    );
  }

  void _clearSelection(PointerUpEvent event) {

    if(words.contains(getWord(selectedIndexes, alphabet))){
      print("ok");

    }
    else{
      _trackTaped.clear();
      setState(() {
        selectedIndexes.clear();
      });
    }

  }
}

class Foo extends SingleChildRenderObjectWidget {
  final int index;

  Foo({Widget child, this.index, Key key}) : super(child: child, key: key);

  @override
  _Foo createRenderObject(BuildContext context) {
    return _Foo()..index = index;
  }

  @override
  void updateRenderObject(BuildContext context, _Foo renderObject) {
    renderObject..index = index;

  }
}

class _Foo extends RenderProxyBox {
  int index;
}

На данный момент я примерно нашел такое решение.

...