[gnome-2048] Implement persistence
- From: Juan R. Garcia Blanco <juanrgar src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-2048] Implement persistence
- Date: Sat, 10 Jan 2015 14:29:20 +0000 (UTC)
commit 7003ef2219f3e56f0d644f01c4f9a72f6a3598c0
Author: Juan R. GarcĂa Blanco <juanrgar gmail com>
Date: Sat Jan 10 15:21:21 2015 +0100
Implement persistence
Game state is preserved between launches.
src/application.vala | 5 +-
src/game.vala | 84 ++++++++++++++++++++++++--
src/grid.vala | 162 ++++++++++++++++++++++++++++++++++++-------------
3 files changed, 202 insertions(+), 49 deletions(-)
---
diff --git a/src/application.vala b/src/application.vala
index 177ae47..1a8eafe 100644
--- a/src/application.vala
+++ b/src/application.vala
@@ -70,13 +70,16 @@ public class Application : Gtk.Application
_create_about_dialog ();
_create_preferences_dialog (builder);
- _game.new_game ();
+ if (!_game.restore_game ())
+ _game.new_game ();
}
protected override void shutdown ()
{
base.shutdown ();
+ _game.save_game ();
+
_settings.set_int ("window-width", _window_width);
_settings.set_int ("window-height", _window_height);
_settings.set_boolean ("window-maximized", _window_maximized);
diff --git a/src/game.vala b/src/game.vala
index 0060256..c63dda5 100644
--- a/src/game.vala
+++ b/src/game.vala
@@ -26,7 +26,8 @@ public class Game : GLib.Object
MOVING_RIGHT,
MOVING_LEFT,
SHOWING_FIRST_TILE,
- SHOWING_SECOND_TILE
+ SHOWING_SECOND_TILE,
+ RESTORING_TILES
}
private int BLANK_ROW_HEIGHT = 10;
@@ -52,6 +53,8 @@ public class Game : GLib.Object
private GLib.Settings _settings;
+ private string _saved_path;
+
public signal void finished ();
public Game (GLib.Settings settings)
@@ -69,6 +72,8 @@ public class Game : GLib.Object
_to_hide = new Gee.LinkedList<TileMovement?> ();
_to_show = new Gee.LinkedList<Tile?> ();
+ _saved_path = Path.build_filename (Environment.get_user_data_dir (), "gnome-2048", "saved");
+
_state = GameState.STOPPED;
}
@@ -93,6 +98,49 @@ public class Game : GLib.Object
_create_random_tile ();
}
+ public void save_game ()
+ {
+ string contents = "";
+
+ contents += _grid.save ();
+ contents += _score.to_string() + "\n";
+
+ try {
+ DirUtils.create_with_parents (Path.get_dirname (_saved_path), 0775);
+ FileUtils.set_contents (_saved_path, contents);
+ debug ("game saved successfully");
+ } catch (FileError e) {
+ warning ("Failed to save game: %s", e.message);
+ }
+ }
+
+ public bool restore_game ()
+ {
+ string contents;
+ string[] lines;
+
+ try {
+ FileUtils.get_contents (_saved_path, out contents);
+ } catch (FileError e) {
+ warning ("Failed to save game: %s", e.message);
+ return false;
+ }
+
+ if (!_grid.load (contents))
+ return false;
+
+ lines = contents.split ("\n");
+ score = (uint)int.parse (lines[lines.length-2]);
+
+ _n_rows = _grid.rows;
+ _n_cols = _grid.cols;
+ _init_background ();
+ _restore_foreground ();
+
+ debug ("game restored successfully");
+ return true;
+ }
+
public bool key_pressed (Gdk.EventKey event)
{
if (_state != GameState.IDLE) {
@@ -220,6 +268,7 @@ public class Game : GLib.Object
_create_tile (tile);
_to_show.add (tile);
_show_tile (tile.pos);
+ _show_hide_trans.start ();
}
}
@@ -382,8 +431,6 @@ public class Game : GLib.Object
trans.set_remove_on_complete (true);
trans.set_duration (50);
view.actor.add_transition ("show", trans);
-
- _show_hide_trans.start ();
}
private void _move_tile (GridPosition from, GridPosition to)
@@ -463,9 +510,36 @@ public class Game : GLib.Object
}
}
+ private void _restore_foreground ()
+ {
+ uint val;
+ GridPosition pos;
+ Tile tile;
+
+ _create_show_hide_transition ();
+
+ for (int i = 0; i < _n_rows; i++) {
+ for (int j = 0; j < _n_cols; j++) {
+ val = _grid[i,j];
+ if (val != 0) {
+ pos = { i, j };
+ tile = { pos, val };
+ _create_tile (tile);
+ _to_show.add (tile);
+ _show_tile (pos);
+ }
+ }
+ }
+
+ if (_to_show.size > 0) {
+ _state = GameState.RESTORING_TILES;
+ _show_hide_trans.start ();
+ }
+ }
+
private void _on_move_trans_stopped (bool is_finished)
{
- debug ("move animation stopped");
+ debug (@"move animation stopped; finished $is_finished");
debug (@"$_grid");
uint delta_score;
@@ -493,7 +567,7 @@ public class Game : GLib.Object
private void _on_show_hide_trans_stopped (bool is_finished)
{
- debug ("show/hide animation stopped");
+ debug (@"show/hide animation stopped; finished $is_finished");
debug (@"$_grid");
_show_hide_trans.remove_all ();
diff --git a/src/grid.vala b/src/grid.vala
index 7a0d371..52133c4 100644
--- a/src/grid.vala
+++ b/src/grid.vala
@@ -18,24 +18,22 @@
public class Grid : GLib.Object
{
- private int _n_rows;
- private int _n_cols;
-
private uint[,] _grid;
- public Grid (int n_rows, int n_cols)
+ public Grid (int rows, int cols)
{
- Object ();
+ Object (rows: rows, cols: cols);
- _n_rows = n_rows;
- _n_cols = n_cols;
+ _grid = new uint[rows, cols];
+ clear ();
+ }
- _grid = new uint[_n_rows, _n_cols];
+ public int rows {
+ get; set;
}
- construct
- {
- clear ();
+ public int cols {
+ get; set;
}
public void clear ()
@@ -87,16 +85,16 @@ public class Grid : GLib.Object
to_hide.clear ();
to_show.clear ();
- for (int i = 0; i < _n_cols; i++) {
- free = { _n_rows, i };
+ for (int i = 0; i < _cols; i++) {
+ free = { _rows, i };
- for (int j = 0; j < _n_rows; j++) {
- row = _n_rows - j - 1;
+ for (int j = 0; j < _rows; j++) {
+ row = _rows - j - 1;
cur = { row, i };
val = _grid[cur.row,cur.col];
if (val == 0) {
- if (free.row == _n_rows) {
+ if (free.row == _rows) {
free.row = row;
}
continue;
@@ -120,7 +118,7 @@ public class Grid : GLib.Object
if (has_match) {
debug (@"matching tile found at $match");
- if (free.row == _n_rows) {
+ if (free.row == _rows) {
free.row = row; // temporarily
}
mov = { cur, free };
@@ -136,7 +134,7 @@ public class Grid : GLib.Object
_grid[free.row,free.col] = val*2;
free.row--;
- } else if (free.row != _n_rows) {
+ } else if (free.row != _rows) {
debug (@"moving $cur to $free");
mov = { cur, free };
@@ -168,10 +166,10 @@ public class Grid : GLib.Object
to_hide.clear ();
to_show.clear ();
- for (int i = 0; i < _n_cols; i++) {
+ for (int i = 0; i < _cols; i++) {
free = { -1, i };
- for (int j = 0; j < _n_rows; j++) {
+ for (int j = 0; j < _rows; j++) {
row = j;
cur = { row, i };
val = _grid[cur.row,cur.col];
@@ -186,7 +184,7 @@ public class Grid : GLib.Object
// search for matches
match = { 0, 0 };
has_match = false;
- for (int k = row + 1; k < _n_rows; k++) {
+ for (int k = row + 1; k < _rows; k++) {
uint k_val = _grid[k,cur.col];
if (k_val != 0) {
@@ -249,10 +247,10 @@ public class Grid : GLib.Object
to_hide.clear ();
to_show.clear ();
- for (int i = 0; i < _n_rows; i++) {
+ for (int i = 0; i < _rows; i++) {
free = { i, -1 };
- for (int j = 0; j < _n_cols; j++) {
+ for (int j = 0; j < _cols; j++) {
col = j;
cur = { i, col };
val = _grid[cur.row,cur.col];
@@ -267,7 +265,7 @@ public class Grid : GLib.Object
// search for matches
match = { 0, 0 };
has_match = false;
- for (int k = col + 1; k < _n_rows; k++) {
+ for (int k = col + 1; k < _rows; k++) {
uint k_val = _grid[cur.row,k];
if (k_val != 0) {
@@ -330,16 +328,16 @@ public class Grid : GLib.Object
to_hide.clear ();
to_show.clear ();
- for (int i = 0; i < _n_rows; i++) {
- free = { i, _n_cols };
+ for (int i = 0; i < _rows; i++) {
+ free = { i, _cols };
- for (int j = 0; j < _n_cols; j++) {
- col = _n_cols - j - 1;
+ for (int j = 0; j < _cols; j++) {
+ col = _cols - j - 1;
cur = { i, col };
val = _grid[cur.row,cur.col];
if (val == 0) {
- if (free.col == _n_cols) {
+ if (free.col == _cols) {
free.col = col;
}
continue;
@@ -363,7 +361,7 @@ public class Grid : GLib.Object
if (has_match) {
debug (@"matching tile found at $match");
- if (free.col == _n_cols) {
+ if (free.col == _cols) {
free.col = col; // temporarily
}
mov = { cur, free };
@@ -379,7 +377,7 @@ public class Grid : GLib.Object
_grid[free.row,free.col] = val*2;
free.col--;
- } else if (free.col != _n_cols) {
+ } else if (free.col != _cols) {
debug (@"moving $cur to $free");
mov = { cur, free };
@@ -401,15 +399,15 @@ public class Grid : GLib.Object
if (!_grid_is_full ())
return false;
else {
- for (int i = 0; i < _n_rows; i++) {
- for (int j = 0; j < _n_cols; j++) {
+ for (int i = 0; i < _rows; i++) {
+ for (int j = 0; j < _cols; j++) {
val = _grid[i,j];
- if (i < (_n_rows - 1))
+ if (i < (_rows - 1))
if (val == _grid[i+1,j])
return false;
- if (j < (_n_cols - 1))
+ if (j < (_cols - 1))
if (val == _grid[i,j+1])
return false;
}
@@ -419,24 +417,102 @@ public class Grid : GLib.Object
return true;
}
+ public uint get (int row, int col)
+ {
+ if ((row >= _rows) || (col >= _cols))
+ return 0;
+
+ return _grid[row,col];
+ }
+
+ public string save ()
+ {
+ string ret = "";
+
+ ret += _rows.to_string () + " ";
+ ret += _cols.to_string () + "\n";
+
+ ret += _convert_to_string ();
+
+ return ret;
+ }
+
+ public bool load (string content)
+ {
+ return _load_from_string (content);
+ }
+
public string to_string ()
{
+ string ret = "\n";
+ ret += _convert_to_string ();
+ return ret;
+ }
+
+ private string _convert_to_string ()
+ {
string ret = "";
- for (uint i = 0; i < _n_rows; i++) {
- ret += "\n";
- for (uint j = 0; j < _n_cols; j++) {
- ret += " " + _grid[i,j].to_string () + " ";
+ for (uint i = 0; i < _rows; i++) {
+ for (uint j = 0; j < _cols; j++) {
+ ret += "%u%s".printf (_grid[i,j], (j == (_cols-1)) ? "\n" : " ");
}
}
return ret;
}
+ private bool _load_from_string (string contents)
+ {
+ int rows = 0;
+ int cols = 0;
+ string[] lines;
+ string[] tokens;
+ uint[,] grid;
+
+ lines = contents.split ("\n");
+
+ // check that at least it contains 2 rows
+ if (lines.length < 3)
+ return false;
+
+ tokens = lines[0].split (" ");
+ if (tokens.length != 2)
+ return false;
+
+ rows = int.parse (tokens[0]);
+ cols = int.parse (tokens[1]);
+
+ if ((rows < 2) || (cols < 2))
+ return false;
+ // we don't need to be strict here
+ if (lines.length < (rows+1))
+ return false;
+
+ grid = new uint[rows, cols];
+
+ for (int i = 0; i < rows; i++) {
+ tokens = lines[i+1].split (" ");
+ // we do need to be strict here
+ if (tokens.length != cols)
+ return false;
+
+ for (int j = 0; j < cols; j++) {
+ grid[i,j] = int.parse (tokens[j]);
+ }
+ }
+
+ _rows = rows;
+ _cols = cols;
+ _grid = grid;
+
+ return true;
+ }
+
private bool _grid_is_full ()
{
- for (uint i = 0; i < _n_rows; i++) {
- for (uint j = 0; j < _n_cols; j++) {
+ for (uint i = 0; i < _rows; i++) {
+ for (uint j = 0; j < _cols; j++) {
if (_grid[i,j] == 0) {
return false;
}
@@ -448,8 +524,8 @@ public class Grid : GLib.Object
private GridPosition _random_position ()
{
- GridPosition ret = { Random.int_range (0, (int)_n_rows),
- Random.int_range (0, (int)_n_cols) };
+ GridPosition ret = { Random.int_range (0, (int)_rows),
+ Random.int_range (0, (int)_cols) };
return ret;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]