Added more stuff for proper Object orientation, abstraction and so on
--- UI still not working gotta fix thatmain
parent
3b8eb7c0e6
commit
480dbdacc6
|
@ -1,5 +1,5 @@
|
|||
/// Enum for the stone colors.
|
||||
enum Color {
|
||||
enum StoneColors {
|
||||
red,
|
||||
green,
|
||||
blue,
|
||||
|
@ -7,4 +7,3 @@ enum Color {
|
|||
pink,
|
||||
special, // not a "real" color; indicates that a stone is special (Not retarded, in a nice way, like mama always used to tell me i am her special child)
|
||||
}
|
||||
|
|
@ -0,0 +1,253 @@
|
|||
import 'dart:math';
|
||||
|
||||
import 'package:bubbletwist/game/stone/SpecialStone.dart';
|
||||
|
||||
import '../enums/StoneColor.dart';
|
||||
import 'Game.dart';
|
||||
import 'stone/PentaSpecialStone.dart';
|
||||
import 'stone/Stone.dart';
|
||||
import 'stone/StoneLocation.dart';
|
||||
|
||||
class Board {
|
||||
static const int boardSize = 8;
|
||||
final Game game;
|
||||
late final List<List<Stone?>> stones =
|
||||
List.filled(boardSize, List.filled(boardSize, Stone()));
|
||||
|
||||
Board(this.game) {
|
||||
for (var row in stones) {
|
||||
for (var stone in row) {
|
||||
stone = Stone();
|
||||
}
|
||||
}
|
||||
// The map generates with pairs of 3+ stones already in place.
|
||||
// To fix that we just let the game remove all 3+ stone pairs until none are left
|
||||
//while (checkBoard());
|
||||
}
|
||||
void updateBoard() {
|
||||
game.updateBoard();
|
||||
}
|
||||
|
||||
bool swapStones(StoneLocation sl1, StoneLocation sl2) {
|
||||
// Check if the two stones that have been clicked are next to each other
|
||||
if (!(sl1.row >= sl2.row - 1 && sl1.row <= sl2.row + 1) ||
|
||||
!(sl1.column >= sl2.column - 1 && sl1.column <= sl2.column + 1)) {
|
||||
return false; // If they are not next to each other just abort
|
||||
}
|
||||
|
||||
final s1 = game.getStone(sl1);
|
||||
final ss1 = s1 is PentaSpecialStone ? s1 : null;
|
||||
if (ss1 != null) {
|
||||
ss1.stoneColor = getStone(sl2)!.stoneColor;
|
||||
performSpecialStone(ss1, sl1);
|
||||
return true;
|
||||
}
|
||||
|
||||
final s2 = game.getStone(sl2);
|
||||
final ss2 = s2 is PentaSpecialStone ? s2 : null;
|
||||
if (ss2 != null) {
|
||||
ss2.stoneColor = getStone(sl1)!.stoneColor;
|
||||
performSpecialStone(ss2, sl2);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Swap stones
|
||||
swap(sl1, sl2);
|
||||
if (checkBoard()) {
|
||||
// Check if swapping was a valid move
|
||||
// If Swap is valid, Stones have been removed and others have to fall down
|
||||
applyGravity();
|
||||
while (checkBoard()) {
|
||||
// Then we have to keep checking until no more 3+ stones are created by falling stones
|
||||
applyGravity();
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
// If Swap is invalid, the stones get swapped back
|
||||
swap(sl1, sl2);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool checkBoard() {
|
||||
bool stuffDeleted = false;
|
||||
|
||||
// FOR HORIZONTALS
|
||||
for (int row = 0; row < boardSize; ++row) {
|
||||
// First go through each row
|
||||
int startPosition = 0;
|
||||
int counter = 1;
|
||||
for (int column = 1; column < boardSize; ++column) {
|
||||
// And then through each column
|
||||
if (stones[row][column] == null || stones[row][column - 1] == null) {
|
||||
// Ignore deleted stones
|
||||
continue;
|
||||
}
|
||||
|
||||
final colorsAreSame = stones[row][column]!.stoneColor ==
|
||||
stones[row][column - 1]!.stoneColor;
|
||||
|
||||
// If both stones have the same color increase counter
|
||||
if (colorsAreSame) {
|
||||
counter++;
|
||||
}
|
||||
// If they are not the same color or we reach the end of the Board,
|
||||
// check the counter to see if the last 3+ stones had the same color
|
||||
if (!colorsAreSame || column == boardSize - 1) {
|
||||
if (counter >= 3) {
|
||||
// And if we had 3+ stones, remove them
|
||||
if (game.isRunning()) {
|
||||
game.addPoints(counter);
|
||||
game.addTime(3);
|
||||
}
|
||||
for (int k = 0; k < counter; ++k) {
|
||||
final st = StoneLocation(row: row, column: startPosition + k);
|
||||
removeStone(st);
|
||||
stuffDeleted = true;
|
||||
}
|
||||
if (counter == 3 && game.isRunning()) {
|
||||
//stones[row][startPosition] = TripleSpecialStone(this);
|
||||
}
|
||||
if (counter == 4 && game.isRunning()) {
|
||||
//stones[row][startPosition] = QuadSpecialStone(this, false);
|
||||
}
|
||||
if (counter == 5 && game.isRunning()) {
|
||||
stones[row][startPosition] = PentaSpecialStone(this);
|
||||
}
|
||||
}
|
||||
// Reset counter and start position after each color change
|
||||
counter = 1;
|
||||
startPosition = column;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FOR VERTICALS
|
||||
for (int column = 0; column < boardSize; ++column) {
|
||||
// First go through each column
|
||||
int startPosition = 0;
|
||||
int counter = 1;
|
||||
for (int row = 1; row < boardSize; ++row) {
|
||||
// And then through each row
|
||||
if (stones[row][column] == null || stones[row - 1][column] == null) {
|
||||
// Ignore deleted stones
|
||||
continue;
|
||||
}
|
||||
|
||||
// If both stones have the same color increase counter
|
||||
final colorsAreSame = stones[row][column]!.stoneColor ==
|
||||
stones[row - 1][column]!.stoneColor;
|
||||
if (colorsAreSame) {
|
||||
counter++;
|
||||
}
|
||||
// If they are not the same color or we reach the end of the Board,
|
||||
// check the counter to see if the last 3+ stones had the same color
|
||||
if (!colorsAreSame || row == boardSize - 1) {
|
||||
if (counter >= 3) {
|
||||
//And if we had 3+ stones, remove them
|
||||
if (game.isRunning()) {
|
||||
game.addPoints(counter);
|
||||
game.addTime(3);
|
||||
}
|
||||
for (int k = 0; k < counter; ++k) {
|
||||
final st = StoneLocation(row: startPosition + k, column: column);
|
||||
removeStone(st);
|
||||
stuffDeleted = true;
|
||||
}
|
||||
if (counter == 3 && game.isRunning()) {
|
||||
//stones[startPosition][column] = TripleSpecialStone(this);
|
||||
}
|
||||
if (counter == 4 && game.isRunning()) {
|
||||
//stones[startPosition][column] = QuadSpecialStone(this, true);
|
||||
}
|
||||
if (counter == 5 && game.isRunning()) {
|
||||
stones[startPosition][column] = PentaSpecialStone(this);
|
||||
}
|
||||
}
|
||||
// Reset counter and start position after each color change
|
||||
counter = 1;
|
||||
startPosition = row;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (stuffDeleted) {
|
||||
// If stuff has been deleted we have to update the Gui
|
||||
game.updateBoard();
|
||||
}
|
||||
return stuffDeleted;
|
||||
}
|
||||
|
||||
void removeStone(StoneLocation sl) {
|
||||
if (sl.row < 0 ||
|
||||
sl.row >= boardSize ||
|
||||
sl.column < 0 ||
|
||||
sl.column >= boardSize) {
|
||||
return;
|
||||
}
|
||||
if (!game.isRunning()) {
|
||||
// If game is not running, just give the stones a new color
|
||||
stones[sl.row][sl.column]!.stoneColor =
|
||||
StoneColors.values[Random().nextInt(StoneColors.values.length)];
|
||||
} else {
|
||||
// Otherwise mark stones as deleted
|
||||
stones[sl.row][sl.column] = null;
|
||||
}
|
||||
}
|
||||
|
||||
void applyGravity() {
|
||||
bool stonesHaveFallenDown;
|
||||
// Move Stones down 1 row if the stone below them is marked as deleted
|
||||
do {
|
||||
stonesHaveFallenDown = false;
|
||||
for (int column = 0; column < boardSize; ++column) {
|
||||
for (int row = boardSize - 1; row > 0; --row) {
|
||||
if (stones[row][column] == null) {
|
||||
if (stones[row - 1][column] == null) {
|
||||
continue;
|
||||
}
|
||||
stones[row][column] = stones[row - 1][column];
|
||||
stones[row - 1][column] = null;
|
||||
stonesHaveFallenDown = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (
|
||||
stonesHaveFallenDown); // Continue doing so until all deleted Stones are at the top most position
|
||||
|
||||
// Then generate new stones that rain from the sky)
|
||||
for (var row in stones) {
|
||||
for (var stone in row) {
|
||||
if (stone == null) {
|
||||
stone = Stone();
|
||||
}
|
||||
}
|
||||
}
|
||||
game.updateBoard();
|
||||
}
|
||||
|
||||
void performSpecialStone(SpecialStone ss, StoneLocation sl) {
|
||||
//Delete Stones
|
||||
ss.performSpecialStoneAction();
|
||||
removeStone(sl);
|
||||
//show Deleted Stones
|
||||
updateBoard();
|
||||
//Make Stones fall down into new "holes"
|
||||
applyGravity();
|
||||
updateBoard(); //Show the Gravity Effect
|
||||
while (checkBoard()) {
|
||||
// Then we have to keep checking until no more 3+ stones are created by falling stones
|
||||
applyGravity();
|
||||
}
|
||||
}
|
||||
|
||||
void swap(StoneLocation sl1, StoneLocation sl2) {
|
||||
final tmp = stones[sl1.row][sl1.column];
|
||||
stones[sl1.row][sl1.column] = stones[sl2.row][sl2.column];
|
||||
stones[sl2.row][sl2.column] = tmp;
|
||||
game.updateBoard();
|
||||
}
|
||||
|
||||
Stone? getStone(StoneLocation sl) {
|
||||
return stones[sl.row][sl.column];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
import 'dart:async';
|
||||
|
||||
import '../enums/StoneColor.dart';
|
||||
import 'Board.dart';
|
||||
import 'IGameConsumer.dart';
|
||||
import 'stone/Stone.dart';
|
||||
import 'stone/StoneLocation.dart';
|
||||
|
||||
class Game {
|
||||
IGameConsumer gameConsumer;
|
||||
late int timeInSeconds;
|
||||
int startTime = 60; // hardcoded
|
||||
int points = 0;
|
||||
bool running = false;
|
||||
late Board board;
|
||||
late Timer counterTimer;
|
||||
StoneLocation stoneToSwap = StoneLocation(row: -1, column: -1);
|
||||
|
||||
Game(this.gameConsumer) {
|
||||
timeInSeconds = startTime;
|
||||
board = Board(this);
|
||||
}
|
||||
|
||||
int getPoints() => points;
|
||||
|
||||
int getTimeInSeconds() => timeInSeconds;
|
||||
|
||||
void addPoints(int pointsToAdd) {
|
||||
if (timeInSeconds != 0 && running) {
|
||||
points += pointsToAdd;
|
||||
gameConsumer.updatePoints();
|
||||
}
|
||||
}
|
||||
|
||||
void addTime(int timeToAdd) {
|
||||
if (timeInSeconds != 0 && running) {
|
||||
timeInSeconds += timeToAdd;
|
||||
gameConsumer.updateTime();
|
||||
}
|
||||
}
|
||||
|
||||
void endGame() {
|
||||
running = false;
|
||||
counterTimer?.cancel();
|
||||
gameConsumer.gameStopped();
|
||||
}
|
||||
|
||||
Future<void> countDown() async {
|
||||
do {
|
||||
timeInSeconds--;
|
||||
gameConsumer.updateTime();
|
||||
if (timeInSeconds > 0) {
|
||||
await Future.delayed(Duration(seconds: 1));
|
||||
}
|
||||
} while (timeInSeconds > 0);
|
||||
if (running) {
|
||||
endGame();
|
||||
}
|
||||
}
|
||||
|
||||
StoneColors? getStoneColor(StoneLocation location) {
|
||||
return board.getStone(location)?.getStoneColor();
|
||||
}
|
||||
|
||||
Stone? getStone(StoneLocation location) {
|
||||
return board.getStone(location);
|
||||
}
|
||||
|
||||
void start() {
|
||||
if (!running) {
|
||||
timeInSeconds = startTime;
|
||||
points = 0;
|
||||
board = Board(this);
|
||||
gameConsumer.updateStones();
|
||||
counterTimer = Timer.periodic(Duration(seconds: 1), (_) => countDown());
|
||||
gameConsumer.updatePoints();
|
||||
running = true;
|
||||
}
|
||||
}
|
||||
|
||||
void stop() {
|
||||
if (running) {
|
||||
running = false;
|
||||
timeInSeconds = 0;
|
||||
counterTimer.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
bool swapStones(StoneLocation sl1, StoneLocation sl2) {
|
||||
return board.swapStones(sl1, sl2);
|
||||
}
|
||||
|
||||
void updateBoard() {
|
||||
if (running) {
|
||||
gameConsumer.updateStones();
|
||||
}
|
||||
}
|
||||
|
||||
bool isRunning() => running;
|
||||
|
||||
bool swap(StoneLocation sl) {
|
||||
if (stoneToSwap.row == -1) {
|
||||
stoneToSwap = sl;
|
||||
return false;
|
||||
} else {
|
||||
swapStones(stoneToSwap, sl);
|
||||
stoneToSwap = StoneLocation(row: -1, column: -1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool performSpecialStone(StoneLocation sl) {
|
||||
Stone? s = getStone(sl);
|
||||
/*if (s is TriggerableSpecialStone) {
|
||||
s.setActivationLocation(sl);
|
||||
board.performSpecialStone(s, sl);
|
||||
return true;
|
||||
}*/
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
import '../Board.dart';
|
||||
import 'SpecialStone.dart';
|
||||
import 'StoneLocation.dart';
|
||||
|
||||
class PentaSpecialStone extends SpecialStone {
|
||||
PentaSpecialStone(Board board) : super(board);
|
||||
|
||||
int getSpecialStoneNumber() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
void performSpecialStoneAction() {
|
||||
StoneLocation sl = StoneLocation(row: -1, column: -1);
|
||||
for (int i = 0; i < Board.boardSize; ++i) {
|
||||
for (int j = 0; j < Board.boardSize; ++j) {
|
||||
sl.row = i;
|
||||
sl.column = j;
|
||||
if (this == board.getStone(sl)) {
|
||||
continue;
|
||||
}
|
||||
if (board.getStone(sl)?.getStoneColor() == this.getStoneColor()) {
|
||||
board.removeStone(sl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
import '../Board.dart';
|
||||
import 'Stone.dart';
|
||||
|
||||
abstract class SpecialStone extends Stone {
|
||||
final Board board;
|
||||
|
||||
SpecialStone(this.board);
|
||||
|
||||
/// Returns the associated number of the special stone
|
||||
int getSpecialStoneNumber();
|
||||
|
||||
/// Performs the action of the special stone
|
||||
void performSpecialStoneAction();
|
||||
}
|
|
@ -1,10 +1,11 @@
|
|||
import 'dart:math';
|
||||
import '../../enums/Color.dart';
|
||||
|
||||
import '../../enums/StoneColor.dart';
|
||||
|
||||
/// Class to represent a stone on the board.
|
||||
class Stone {
|
||||
/// Color of the stone
|
||||
late Color color;
|
||||
late StoneColors stoneColor;
|
||||
|
||||
Stone() {
|
||||
setRandomColor();
|
||||
|
@ -12,16 +13,17 @@ class Stone {
|
|||
|
||||
/// Getter for the color.
|
||||
/// \return color
|
||||
Color getColor() => color;
|
||||
StoneColors getStoneColor() => stoneColor;
|
||||
|
||||
/// Setter for the color
|
||||
/// \param color
|
||||
void setColor(Color color) {
|
||||
this.color = color;
|
||||
void setColor(StoneColors stoneColor) {
|
||||
this.stoneColor = stoneColor;
|
||||
}
|
||||
|
||||
/// method that sets a random color
|
||||
void setRandomColor() {
|
||||
color = Color.values[Random().nextInt(Color.values.length)];
|
||||
stoneColor =
|
||||
StoneColors.values[Random().nextInt(StoneColors.values.length)];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
/// Simple structure that stores two ints to locate a stone on the board.
|
||||
class StoneLocation {
|
||||
int row;
|
||||
int column;
|
||||
|
||||
StoneLocation({
|
||||
required this.row,
|
||||
required this.column,
|
||||
});
|
||||
}
|
208
lib/main.dart
208
lib/main.dart
|
@ -1,7 +1,11 @@
|
|||
import 'dart:math';
|
||||
|
||||
import 'package:bubbletwist/enums/StoneColor.dart';
|
||||
import 'package:bubbletwist/game/Game.dart';
|
||||
import 'package:bubbletwist/game/IGameConsumer.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'game/stone/Stone.dart';
|
||||
import 'game/stone/StoneLocation.dart';
|
||||
|
||||
void main() {
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
@ -9,7 +13,7 @@ void main() {
|
|||
class MyApp extends StatelessWidget {
|
||||
const MyApp({super.key});
|
||||
|
||||
final int gridSize = 12;
|
||||
final int gridSize = 8;
|
||||
|
||||
// This widget is the root of your application.
|
||||
@override
|
||||
|
@ -20,7 +24,7 @@ class MyApp extends StatelessWidget {
|
|||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
|
||||
useMaterial3: true,
|
||||
),
|
||||
home: const MyHomePage(title: 'Flutter Demo Home Page', gridSize: 12),
|
||||
home: const MyHomePage(title: 'Flutter Demo Home Page', gridSize: 8),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -44,44 +48,25 @@ class MyHomePage extends StatefulWidget {
|
|||
State<MyHomePage> createState() => _MyHomePageState();
|
||||
}
|
||||
|
||||
class _MyHomePageState extends State<MyHomePage> {
|
||||
late List<List<int>> _grid;
|
||||
int _selectedRow = -1;
|
||||
int _selectedCol = -1;
|
||||
int _score = 0;
|
||||
|
||||
class _MyHomePageState extends State<MyHomePage> implements IGameConsumer {
|
||||
late List<List<Stone?>> _grid;
|
||||
late Game game;
|
||||
final int _score = 0;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_initializeGrid();
|
||||
}
|
||||
|
||||
void _initializeGrid() {
|
||||
game = Game(this);
|
||||
_grid = List.generate(widget.gridSize,
|
||||
(_) => List.generate(widget.gridSize, (_) => Random().nextInt(5)));
|
||||
_removeInitialMatches();
|
||||
}
|
||||
|
||||
void _removeInitialMatches() {
|
||||
bool hasMatches;
|
||||
do {
|
||||
hasMatches = _removeMatches();
|
||||
_applyGravity();
|
||||
} while (hasMatches);
|
||||
_score = 0;
|
||||
(index) => List.generate(widget.gridSize, (index) => Stone()));
|
||||
game.start();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text('Candy Crush'),
|
||||
],
|
||||
),
|
||||
title: Text(widget.title),
|
||||
),
|
||||
body: Center(
|
||||
child: Column(
|
||||
|
@ -90,12 +75,11 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
'Score: $_score',
|
||||
style: TextStyle(fontSize: 24),
|
||||
style: const TextStyle(fontSize: 24),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: GridView.builder(
|
||||
shrinkWrap: true,
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: widget.gridSize,
|
||||
),
|
||||
|
@ -103,13 +87,18 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||
itemBuilder: (BuildContext context, int index) {
|
||||
int row = index ~/ widget.gridSize;
|
||||
int col = index % widget.gridSize;
|
||||
StoneLocation location = StoneLocation(row: row, column: col);
|
||||
return GestureDetector(
|
||||
onTap: () => _onTileTap(row, col),
|
||||
onTap: () {
|
||||
setState(() {
|
||||
//game.handleTap(row, col);
|
||||
});
|
||||
},
|
||||
child: Container(
|
||||
margin: const EdgeInsets.all(2),
|
||||
decoration: BoxDecoration(
|
||||
color: _getColor(_grid[row][col]),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
color: _getColorForStone(game.getStone(location)),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -122,143 +111,50 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
Color _getColor(int value) {
|
||||
switch (value) {
|
||||
case 0:
|
||||
Color _getColorForStone(Stone? stone) {
|
||||
// Beispielhafte Farben basierend auf dem Stein.
|
||||
switch (stone?.getStoneColor()) {
|
||||
case StoneColors.red:
|
||||
return Colors.red;
|
||||
case 1:
|
||||
return Colors.blue;
|
||||
case 2:
|
||||
case StoneColors.green:
|
||||
return Colors.green;
|
||||
case 3:
|
||||
case StoneColors.blue:
|
||||
return Colors.blue;
|
||||
case StoneColors.yellow:
|
||||
return Colors.yellow;
|
||||
case 4:
|
||||
return Colors.orange;
|
||||
default:
|
||||
return Colors.white;
|
||||
return Colors.grey;
|
||||
}
|
||||
}
|
||||
|
||||
void _onTileTap(int row, int col) {
|
||||
@override
|
||||
void gameStopped() {
|
||||
// TODO: implement gameStopped
|
||||
}
|
||||
|
||||
@override
|
||||
void updatePoints() {
|
||||
int _score = game.getPoints();
|
||||
}
|
||||
|
||||
@override
|
||||
void updateStones() {
|
||||
setState(() {
|
||||
if (_selectedRow == -1 && _selectedCol == -1) {
|
||||
_selectedRow = row;
|
||||
_selectedCol = col;
|
||||
} else {
|
||||
if (_isValidMove(_selectedRow, _selectedCol, row, col)) {
|
||||
_swapTiles(_selectedRow, _selectedCol, row, col);
|
||||
while (_removeMatches()) {
|
||||
_applyGravity();
|
||||
}
|
||||
}
|
||||
_selectedRow = -1;
|
||||
_selectedCol = -1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool _isValidMove(int row1, int col1, int row2, int col2) {
|
||||
if ((row1 == row2 && (col1 - col2).abs() == 1) ||
|
||||
(col1 == col2 && (row1 - row2).abs() == 1)) {
|
||||
int temp = _grid[row1][col1];
|
||||
_grid[row1][col1] = _grid[row2][col2];
|
||||
_grid[row2][col2] = temp;
|
||||
|
||||
bool isValid = _findMatches(row1, col1).isNotEmpty ||
|
||||
_findMatches(row2, col2).isNotEmpty;
|
||||
|
||||
_grid[row2][col2] = _grid[row1][col1];
|
||||
_grid[row1][col1] = temp;
|
||||
|
||||
return isValid;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
List<List<int>> _findMatches(int row, int col) {
|
||||
int color = _grid[row][col];
|
||||
List<List<int>> matches = [];
|
||||
|
||||
// Check horizontally
|
||||
List<int> horizontalMatch = [];
|
||||
for (int c = col; c >= 0 && _grid[row][c] == color; c--) {
|
||||
horizontalMatch.add(c);
|
||||
}
|
||||
for (int c = col + 1; c < widget.gridSize && _grid[row][c] == color; c++) {
|
||||
horizontalMatch.add(c);
|
||||
}
|
||||
if (horizontalMatch.length >= 3) {
|
||||
for (int c in horizontalMatch) {
|
||||
matches.add([row, c]);
|
||||
}
|
||||
}
|
||||
|
||||
// Check vertically
|
||||
List<int> verticalMatch = [];
|
||||
for (int r = row; r >= 0 && _grid[r][col] == color; r--) {
|
||||
verticalMatch.add(r);
|
||||
}
|
||||
for (int r = row + 1; r < widget.gridSize && _grid[r][col] == color; r++) {
|
||||
verticalMatch.add(r);
|
||||
}
|
||||
if (verticalMatch.length >= 3) {
|
||||
for (int r in verticalMatch) {
|
||||
matches.add([r, col]);
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
bool _removeMatches() {
|
||||
List<List<int>> allMatches = [];
|
||||
int scoreIncrement = 0;
|
||||
|
||||
// _grid aktualisieren
|
||||
for (int row = 0; row < widget.gridSize; row++) {
|
||||
for (int col = 0; col < widget.gridSize; col++) {
|
||||
List<List<int>> matches = _findMatches(row, col);
|
||||
if (matches.isNotEmpty) {
|
||||
allMatches.addAll(matches);
|
||||
scoreIncrement++; // Increment score based on number of matches
|
||||
_grid[row][col] = game.getStone(StoneLocation(row: row, column: col));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var match in allMatches) {
|
||||
_grid[match[0]][match[1]] = -1; // Mark the tile as removed
|
||||
}
|
||||
|
||||
setState(() {
|
||||
_score += scoreIncrement;
|
||||
});
|
||||
|
||||
return allMatches.isNotEmpty;
|
||||
}
|
||||
|
||||
|
||||
void _applyGravity() {
|
||||
for (int col = 0; col < widget.gridSize; col++) {
|
||||
int emptyRow = widget.gridSize - 1;
|
||||
for (int row = widget.gridSize - 1; row >= 0; row--) {
|
||||
if (_grid[row][col] != -1) {
|
||||
_grid[emptyRow][col] = _grid[row][col];
|
||||
if (emptyRow != row) {
|
||||
_grid[row][col] = -1;
|
||||
}
|
||||
emptyRow--;
|
||||
}
|
||||
@override
|
||||
void updateTime() {
|
||||
// TODO: implement updateTime
|
||||
}
|
||||
|
||||
for (int row = emptyRow; row >= 0; row--) {
|
||||
_grid[row][col] = Random().nextInt(5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _swapTiles(int row1, int col1, int row2, int col2) {
|
||||
int temp = _grid[row1][col1];
|
||||
_grid[row1][col1] = _grid[row2][col2];
|
||||
_grid[row2][col2] = temp;
|
||||
Game getGame() {
|
||||
return game;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue