Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(246)

Side by Side Diff: samples/pop_pop_win/lib/src/game/game.dart

Issue 786443002: Delete pop-pop-win from the repo (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4 part of pop_pop_win.game;
5
6 class Game {
7 final Field field;
8 final Array2d<SquareState> _states;
9 final StreamController _updatedEvent = new StreamController();
10 final StreamController<GameState> _gameStateEvent =
11 new StreamController<GameState>();
12
13 GameState _state;
14 int _bombsLeft;
15 int _revealsLeft;
16 DateTime _startTime;
17 DateTime _endTime;
18
19 Game(Field field)
20 : this.field = field,
21 _state = GameState.reset,
22 _states = new Array2d<SquareState>(field.width, field.height,
23 SquareState.hidden) {
24 assert(field != null);
25 _bombsLeft = field.bombCount;
26 _revealsLeft = field.length - field.bombCount;
27 }
28
29 int get bombsLeft => _bombsLeft;
30
31 int get revealsLeft => _revealsLeft;
32
33 GameState get state => _state;
34
35 Stream get updated => _updatedEvent.stream;
36
37 Stream get stateChanged => _gameStateEvent.stream;
38
39 SquareState getSquareState(int x, int y) => _states.get(x, y);
40
41 bool get gameEnded => _state == GameState.won || _state == GameState.lost;
42
43 Duration get duration {
44 if (_startTime == null) {
45 assert(state == GameState.reset);
46 return null;
47 } else {
48 assert((state == GameState.started) == (_endTime == null));
49 final end = (_endTime == null) ? new DateTime.now() : _endTime;
50 return end.difference(_startTime);
51 }
52 }
53
54 bool canToggleFlag(int x, int y) {
55 final currentSS = _states.get(x, y);
56 return currentSS == SquareState.hidden || currentSS == SquareState.flagged;
57 }
58
59 void setFlag(int x, int y, bool value) {
60 _ensureStarted();
61 assert(value != null);
62
63 final currentSS = _states.get(x, y);
64 if (value) {
65 require(currentSS == SquareState.hidden);
66 _states.set(x, y, SquareState.flagged);
67 _bombsLeft--;
68 } else {
69 require(currentSS == SquareState.flagged);
70 _states.set(x, y, SquareState.hidden);
71 _bombsLeft++;
72 }
73 _update();
74 }
75
76 bool canReveal(int x, int y) {
77 final currentSS = _states.get(x, y);
78 if (currentSS == SquareState.hidden) {
79 return true;
80 } else if (_canChord(x, y)) {
81 return true;
82 }
83 return false;
84 }
85
86 List<Point> reveal(int x, int y) {
87 _ensureStarted();
88 require(canReveal(x, y), "Item cannot be revealed.");
89 final currentSS = _states.get(x, y);
90
91 List<Point> reveals;
92
93 // normal reveal
94 if (currentSS == SquareState.hidden) {
95 if (field.get(x, y)) {
96 _setLost();
97 reveals = <Point>[];
98 } else {
99 reveals = _doReveal(x, y);
100 }
101 } else if (_canChord(x, y)) {
102 reveals = _doChord(x, y);
103 }
104 _update();
105
106 if (_state == GameState.lost) {
107 return null;
108 } else {
109 return reveals;
110 }
111 }
112
113 String toBoardString() {
114 final buffer = new StringBuffer();
115 for (var y = -2; y < field.height; y++) {
116 if (y > -2) {
117 buffer.write('\n');
118 }
119 for (var x = -2; x < field.width; x++) {
120 var char = null;
121 if (y == -2) {
122 if (x == -2) {
123 char = ' ';
124 } else if (x == -1) {
125 char = '|';
126 } else {
127 char = (x % 10).toString();
128 }
129 } else if (y == -1) {
130 if (x == -1) {
131 char = '+';
132 } else {
133 char = '-';
134 }
135 } else {
136 if (x == -2) {
137 char = (y % 10).toString();
138 } else if (x == -1) {
139 char = '|';
140 } else {
141 switch (getSquareState(x, y)) {
142 case SquareState.flagged:
143 char = '\u2611';
144 break;
145 case SquareState.revealed:
146 var count = field.getAdjacentCount(x, y);
147 char = count.toString();
148 break;
149 case SquareState.hidden:
150 char = '?';
151 break;
152 }
153 }
154 }
155 assert(char != null);
156 buffer.write(char);
157 }
158 }
159 return buffer.toString();
160 }
161
162 bool _canChord(int x, int y) {
163 final currentSS = _states.get(x, y);
164 if (currentSS == SquareState.revealed) {
165 // might be a 'chord' reveal
166 final adjCount = field.getAdjacentCount(x, y);
167 if (adjCount > 0) {
168 final adjHidden = _getAdjacentCount(x, y, SquareState.hidden);
169 if (adjHidden > 0) {
170 final adjFlags = _getAdjacentCount(x, y, SquareState.flagged);
171 if (adjFlags == adjCount) {
172 return true;
173 }
174 }
175 }
176 }
177 return false;
178 }
179
180 List<Point> _doChord(int x, int y) {
181 // this does not repeat a bunch of validations that have already happened
182 // be careful
183 final currentSS = _states.get(x, y);
184 assert(currentSS == SquareState.revealed);
185
186 final flagged = new List<int>();
187 final hidden = new List<int>();
188 final adjCount = field.getAdjacentCount(x, y);
189 assert(adjCount > 0);
190
191 bool failed = false;
192
193 for (final i in field.getAdjacentIndices(x, y)) {
194 if (_states[i] == SquareState.hidden) {
195 hidden.add(i);
196 if (field[i]) {
197 failed = true;
198 }
199 } else if (_states[i] == SquareState.flagged) {
200 flagged.add(i);
201 }
202 }
203
204 // for now we assume counts have been checked
205 assert(flagged.length == adjCount);
206
207 var reveals = <Point>[];
208
209 // if any of the hidden are bombs, we've failed
210 if (failed) {
211 _setLost();
212 } else {
213 for (final i in hidden) {
214 final c = field.getCoordinate(i);
215 if (canReveal(c.item1, c.item2)) {
216 reveals.addAll(reveal(c.item1, c.item2));
217 }
218 }
219 }
220
221 return reveals;
222 }
223
224 List<Point> _doReveal(int x, int y) {
225 assert(_states.get(x, y) == SquareState.hidden);
226 _states.set(x, y, SquareState.revealed);
227 _revealsLeft--;
228 assert(_revealsLeft >= 0);
229 var reveals = [new Point(x, y)];
230 if (_revealsLeft == 0) {
231 _setWon();
232 } else if (field.getAdjacentCount(x, y) == 0) {
233 for (final i in field.getAdjacentIndices(x, y)) {
234 if (_states[i] == SquareState.hidden) {
235 final c = field.getCoordinate(i);
236 reveals.addAll(_doReveal(c.item1, c.item2));
237 assert(state == GameState.started || state == GameState.won);
238 }
239 }
240 }
241 return reveals;
242 }
243
244 void _setWon() {
245 assert(state == GameState.started);
246 for (int i = 0; i < field.length; i++) {
247 if (field[i]) {
248 _states[i] = SquareState.safe;
249 }
250 }
251 _setState(GameState.won);
252 }
253
254 void _setLost() {
255 assert(state == GameState.started);
256 for (int i = 0; i < field.length; i++) {
257 if (field[i]) {
258 _states[i] = SquareState.bomb;
259 }
260 }
261 _setState(GameState.lost);
262 }
263
264 void _update() => _updatedEvent.add(null);
265
266 void _setState(GameState value) {
267 assert(value != null);
268 assert(_state != null);
269 assert((_state == GameState.reset) == (_startTime == null));
270 if (_state != value) {
271 _state = value;
272 if (_state == GameState.started) {
273 _startTime = new DateTime.now();
274 } else if (gameEnded) {
275 _endTime = new DateTime.now();
276 }
277 _gameStateEvent.add(_state);
278 }
279 }
280
281 void _ensureStarted() {
282 if (state == GameState.reset) {
283 assert(_startTime == null);
284 _setState(GameState.started);
285 }
286 assert(state == GameState.started);
287 assert(_startTime != null);
288 }
289
290 int _getAdjacentCount(int x, int y, SquareState state) {
291 int val = 0;
292 for (final i in field.getAdjacentIndices(x, y)) {
293 if (_states[i] == state) {
294 val++;
295 }
296 }
297 return val;
298 }
299 }
OLDNEW
« no previous file with comments | « samples/pop_pop_win/lib/src/game/field.dart ('k') | samples/pop_pop_win/lib/src/game/game_state.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698