游戏点和盒子的数据结构

时间:2011-01-21 23:07:30

标签: data-structures

什么是表示游戏状态的良好数据结构Dots and Boxes

我提出使用2个布尔矩阵,用于水平和垂直线,但也许有更优雅的方法(以及操作:添加行检查行< / em>, check square )。

4 个答案:

答案 0 :(得分:2)

使用一对名为linesXlinesY的二维布尔数组对我来说很有意义。在给定的X / Y方向上,每个阵列将比板上的方块总数多一行/列。以下是使用该解决方案的 check square 的代码示例:

bool isSquareComplete(int x, int y) {
    return linesX[x][y] && linesX[x + 1][y] && linesY[x][y] && linesY[x][y + 1];
}

答案 1 :(得分:2)

我最近这样做并使用了盒子对象的地图。地图是一个元组和框对象。这允许非常快速的访问并且更容易实现边缘算法。对于&lt; -1,0&gt;检查失败要容易得多。而不是特殊情况下的左边缘。为避免数据重复,有一个表示边的数组,而且框对象知道如何访问它。

使用box对象而不仅仅是数组的一个优点是它使策略算法更容易。您经常希望跟踪接近满的盒子列表等。这在数组中不能轻易完成。

答案 2 :(得分:1)

我会使用一个与游戏区域大小相对应的二维数组。然后,数组中的每个元素都可以存储包含4个bool的对象(或结构,具体取决于所使用的语言),每个元素一个。检查框是否完整就像在给定坐标处返回对象的逻辑和那样简单。

单个二维阵列使维护和故障排除错误变得更加容易。

答案 3 :(得分:1)

我的可玩游戏,可调节的W,H和numPlayers,在这里:   http://pconstrictor.github.io/cellsurround/

(源代码也在那里。仍然需要重构为ES6模块语法,并希望使用FP重写。所以,如果有更简单的模型设计,我很乐意知道。)

对于数据模型,我使用了一个大小为w乘以h的单个2D数组。每个单元格都有一个边的列表(在这个正方形网格的情况下为四个)并且变为“填充”。当所有方面都被填满时#39;请注意,然后用户获得额外的转弯。此外,有时单个动作会导致两个单元同时被填充。

// MODEL
exports.SquareGrid = function(width, height, players) {

    // reset (also serves as init)
    this.reset = function(w, h, players) {
        this.players = players;
        this.player = players.firstPlayer();
        var m = [];
        this.matrix = m; // will be a 2D array (well, array of arrays)
        this.height = h;
        this.width = w;

        // fill matrix
        var toLeft = null, above = null; // these will be used for cells
                                            // sharing sides
        for (var row = 0; row < h; row++) {
            m[row] = [];
            for (var col = 0; col < w; col++) {
                toLeft = col ? m[row][col - 1] : null;
                above = row ? m[row - 1][col] : null;
                m[row][col] = exports.createSquareCell(above, toLeft);
            }
        }
    }

...
}

对于实际显示 UI,我使用单个2D数组(大小为2w + 1乘2h + 1)作为视图模型,其中点,边和单元都被简单地表示无论是填充还是空。 (点开始填充并始终保持如此。)这很好地转换为一个HTML表,可以使用两个循环轻松渲染,没有额外的逻辑。这是与9x4模型相对应的7乘9阵列。请注意,理想情况下,这些伪列和行应以交替的大小显示,只是出于视觉原因。

(w = 3, h = 4) so (ww = 7, hh = 9)
. ___ . ___ . ___ .
|     |     |     |
|     |  p1 | p1  |
.     . ___ . ___ .
|     |     |     |
|     |  p1 |  p2 |
.     . ___ . ___ .
|     |           |
|     |           |
.     . ___ .     .
|                 |
|                 |
. ___ . ___ . ___ .

这是实际的视图模型。

// VIEW MODEL

exports.SquareGridView = function(gameModel, appId, resetFuncString) {

// prepare to render the latest of whatever is in the model
this.refresh = function() {
    var h = this.gridModel.height;
    var w = this.gridModel.width;

    // Initialize the UI table, whose dimensions are bigger than the
    // model's.
    var viewPm = [];
    var hh = viewCoord(h);
    var ww = viewCoord(w);
    for (var i = 0; i < hh; i++) {
        viewPm[i] = [];
    }

    // But loop over the model when actually filling it in. (Shared
    // cells cause double writes to viewPm, but oh well.)
    for (var row = 0; row < h; row++) {
        for (var col = 0; col < w; col++) {
            var cell = this.gridModel.matrix[row][col];
            var i = viewCoord(row), j = viewCoord(col);
            viewPm[i][j] = cell.owner;
            viewPm[i - 1][j] = cell.sides['top'];
            viewPm[i + 1][j] = cell.sides['bottom'];
            viewPm[i][j - 1] = cell.sides['left'];
            viewPm[i][j + 1] = cell.sides['right'];
            // Note: vertices can be either filled or left undefined here (and hard-coded as filled in the HTML).
        }
    }
...

这里是实际的render-as-html步骤:

var t = []; // the html text
// TODO: split the HTML bits out into a template file? Use React or Elm?
...

t.push('<table class="squaregrid">\n');
var tdClass, tdId; // 'vertex', '0.0';
for (var i = 0; i < hh; i++) {
    t.push("  <tr> \n");
    for (var j = 0; j < ww; j++) {
        t.push(this.tdHtml(viewPm, i, j));
    }
    t.push(" </tr>\n");
}
t.push("</table>\n");

...

省略tdHtml()函数 - 它生成一个具有正确ID和类的TD。