Data structures 游戏点和盒的数据结构

Data structures 游戏点和盒的数据结构,data-structures,Data Structures,什么样的数据结构可以代表游戏的状态 我想到了使用两个布尔矩阵,用于水平线和垂直线,但可能有一种更优雅的方法(以及操作:添加线、检查线、检查平方)。使用一对称为linesX和linesY的二维布尔数组对我来说很有意义。在给定的X/Y方向上,每个阵列的行/列比电路板上的正方形总数多一行/列。下面是使用该解决方案的check square的代码示例: bool isSquareComplete(int x, int y) { return linesX[x][y] && lin

什么样的数据结构可以代表游戏的状态


我想到了使用两个布尔矩阵,用于水平线和垂直线,但可能有一种更优雅的方法(以及操作:添加线、检查线、检查平方)。

使用一对称为
linesX
linesY
的二维布尔数组对我来说很有意义。在给定的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];
}

我将使用一个与游戏区域大小相对应的二维数组。然后,数组中的每个元素都可以存储一个对象(或结构,取决于使用的语言),该对象包含4个布尔值,每边一个。检查一个框是否完整变得非常简单,只需返回给定坐标处对象的逻辑AND即可


单个二维阵列使维护和故障排除更加容易

我最近做了这件事,并使用了长方体对象的贴图。映射是元组和长方体对象。这允许非常快速的访问,并且更容易实现边缘算法。与特殊情况下的左边缘相比,检查未成功要容易得多。为了避免数据重复,有一个表示边缘的数组,box对象知道如何访问它


使用长方体对象而不仅仅是数组的一个优点是,它使策略算法更容易。您通常希望跟踪接近满盒的盒子列表等。这在阵列中很难做到。

我的可玩游戏,具有可调的W、H和Numplayer,如下所示:

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

对于数据模型,我使用了一个大小为w×h的二维数组。每个单元格都有一个边列表(在这个正方形网格中有四条边),当所有边都被“填充”时,这些边将变为“填充”。请注意,用户将获得额外的回合数。此外,有时一个动作会导致两个细胞同时被填满

// 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);
            }
        }
    }

...
}
这是实际的视图模型

// 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).
        }
    }
...
//视图模型
exports.SquareGridView=函数(gameModel、appId、resetFuncString){
//准备渲染模型中最新的内容
this.refresh=函数(){
var h=this.gridModel.height;
var w=this.gridModel.width;
//初始化UI表,其维度大于
//模特的。
var viewPm=[];
var hh=视图坐标(h);
var ww=视图坐标(w);
对于(变量i=0;i
下面是实际的呈现为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");

...
var t=[];//html文本
//TODO:将HTML位拆分为模板文件?使用React或Elm?
...
t、 推送('\n');
变量tdClass,tdId;/‘顶点’,‘0.0’;
对于(变量i=0;i

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

我不喜欢在这里多次存储数据,允许出现不可能的状态。例如,框(0,0)与框(0,1)共享一个侧面,但它们都包含各自的布尔值作为其状态,这些值可能会发生冲突。我自己的解决方案与nybbler的相同,如果指向边缘对象而不是普通布尔值,则效果很好,然后可以由两个相邻的单元格共享。将0.0的右边缘或0.1的左边缘设置为“填充”则是同义操作s、 然而,为了使代码更简单,我需要每个边缘(或者至少每个潜在的共享边缘)要触发对两个单元格的重新检查,查看当前玩家是否捕获了一个或两个单元格。这会影响棋盘状态以及当前玩家是否获得另一个回合。这是可行的,但可能不足以满足实际游戏空间,因为您需要跟踪谁捕获了给定单元格。因此,我的解决方案(Steve和nybbler的)是使用一个2D单元格对象数组来代替。当然,只需添加第三个2D数组来表示哪些单元格属于哪个玩家(或者不属于任何人)是很容易的。这使得坐标系比我的解决方案更容易转换,因为对于给定的单元格,“顶部”是
i
,左侧是
j
,“右侧”是
j+1
,底部是
i+1
,就像上面的一样。不过,在将模型横切为三个数组并制作整个代码库规范之前,我要三思fic到方形单元格(SquareGrid)。只需保留每个玩家当前分数的计数,就可以略过保留哪些单元格属于哪个玩家的表示。关于检查
-1
失败的有用性,这一点很好。这可能有助于我优化。
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");

...