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

Side by Side Diff: samples/third_party/pop-pop-win/lib/src/poppopwin/game.dart

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

Powered by Google App Engine
This is Rietveld 408576698