[非原创]2048游戏自动化算法

function AI(grid) {
  this.grid = grid;
}

// static evaluation function
AI.prototype.eval = function() {
  var emptyCells = this.grid.availableCells().length;

  var smoothWeight = 0.1,
      //monoWeight   = 0.0,
      //islandWeight = 0.0,
      mono2Weight  = 1.0,
      emptyWeight  = 2.7,
      maxWeight    = 1.0;

  return this.grid.smoothness() * smoothWeight
       + this.grid.monotonicity2() * mono2Weight
       + Math.log(emptyCells) * emptyWeight
       + this.grid.maxValue() * maxWeight;
};

//AI.prototype.cache = {}

// alpha-beta depth first search
AI.prototype.search = function(depth, alpha, beta, positions, cutoffs) {
  var bestScore;
  var bestMove = -1;
  var result;

  // the maxing player
  if (this.grid.playerTurn) {
    bestScore = alpha;
    for (var direction in [0, 1, 2, 3]) {
      var newGrid = this.grid.clone();
      if (newGrid.move(direction).moved) {
        positions++;
        if (newGrid.isWin()) {
          return { move: direction, score: 10000, positions: positions, cutoffs: cutoffs };
        }
        var newAI = new AI(newGrid);

        if (depth == 0) {
          result = { move: direction, score: newAI.eval() };
        } else {
          result = newAI.search(depth-1, bestScore, beta, positions, cutoffs);
          if (result.score > 9900) { // win
            result.score--; // to slightly penalize higher depth from win
          }
          positions = result.positions;
          cutoffs = result.cutoffs;
        }

        if (result.score > bestScore) {
          bestScore = result.score;
          bestMove = direction;
        }
        if (bestScore > beta) {
          cutoffs++
          return { move: bestMove, score: beta, positions: positions, cutoffs: cutoffs };
        }
      }
    }
  }

  else { // computer's turn, we'll do heavy pruning to keep the branching factor low
    bestScore = beta;

    // try a 2 and 4 in each cell and measure how annoying it is
    // with metrics from eval
    var candidates = [];
    var cells = this.grid.availableCells();
    var scores = { 2: [], 4: [] };
    for (var value in scores) {
      for (var i in cells) {
        scores[value].push(null);
        var cell = cells[i];
        var tile = new Tile(cell, parseInt(value, 10));
        this.grid.insertTile(tile);
        scores[value][i] = -this.grid.smoothness() + this.grid.islands();
        this.grid.removeTile(cell);
      }
    }

    // now just pick out the most annoying moves
    var maxScore = Math.max(Math.max.apply(null, scores[2]), Math.max.apply(null, scores[4]));
    for (var value in scores) { // 2 and 4
      for (var i=0; i) {
        if (scores[value][i] == maxScore) {
          candidates.push( { position: cells[i], value: parseInt(value, 10) } );
        }
      }
    }

    // search on each candidate
    for (var i=0; i) {
      var position = candidates[i].position;
      var value = candidates[i].value;
      var newGrid = this.grid.clone();
      var tile = new Tile(position, value);
      newGrid.insertTile(tile);
      newGrid.playerTurn = true;
      positions++;
      newAI = new AI(newGrid);
      result = newAI.search(depth, alpha, bestScore, positions, cutoffs);
      positions = result.positions;
      cutoffs = result.cutoffs;

      if (result.score < bestScore) {
        bestScore = result.score;
      }
      if (bestScore < alpha) {
        cutoffs++;
        return { move: null, score: alpha, positions: positions, cutoffs: cutoffs };
      }
    }
  }

  return { move: bestMove, score: bestScore, positions: positions, cutoffs: cutoffs };
}

// performs a search and returns the best move
AI.prototype.getBest = function() {
  return this.iterativeDeep();
}

// performs iterative deepening over the alpha-beta search
AI.prototype.iterativeDeep = function() {
  var start = (new Date()).getTime();
  var depth = 0;
  var best;
  do {
    var newBest = this.search(depth, -10000, 10000, 0 ,0);
    if (newBest.move == -1) {
      //console.log('BREAKING EARLY');
      break;
    } else {
      best = newBest;
    }
    depth++;
  } while ( (new Date()).getTime() - start < minSearchTime);
  //console.log('depth', --depth);
  //console.log(this.translate(best.move));
  //console.log(best);
  return best
}

AI.prototype.translate = function(move) {
 return {
    0: 'up',
    1: 'right',
    2: 'down',
    3: 'left'
  }[move];
}

Original: https://www.cnblogs.com/ryuasuka/p/3611839.html
Author: 飞鸟_Asuka
Title: [非原创]2048游戏自动化算法

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/608927/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Python List 中的append 和 extend 的区别

    方法的参数不同 append 方法是向原list的末尾添加一个对象(任意对象;如元组,字典,列表等),且只占据一个原list的索引位,添加后无返回值,直接在原列表中添加。 list…

    Linux 2023年6月7日
    094
  • CentOS7.6 单用户模式下修改root密码

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Linux 2023年6月7日
    0103
  • 异步、邮件、定时任务

    异步、邮件、定时任务 14.1 异步任务 编写一个业务测试类 文件路径:com–dzj–service–AsynService.java @Se…

    Linux 2023年6月14日
    0106
  • 搭建Nginx七层反向代理

    基于https://www.cnblogs.com/Dfengshuo/p/11911406.html这个基础上,在来补充下七层代理的配置方式。简单理解下四层和七层协议负载的区别吧…

    Linux 2023年6月8日
    0125
  • samba服务设置与访问共享文件夹

    samba服务设置与访问共享文件夹 linux设置文件夹共享 windows连接共享文件夹(运行->//IP/route) linux连接共享文件夹 1、基本服务安装与配置 …

    Linux 2023年5月27日
    0110
  • 理论知识

    多线程的实现方式:1.继承Thread类;2.实现runnable接口;3.实现callable接口通过futrueTask包装器来创建Thread线程; 是继承Thread类号还…

    Linux 2023年6月7日
    0114
  • 安卓手机改造服务器——基本环境配置(CentOS7 arm32)

    安装好CentOS系统之后,我们需要对环境进行一些基本的配置,让Linux更好用 注意:本文章是针对 arm32的 CentOS7进行配置的,其他系统或不同架构不要尝试。 1、首先…

    Linux 2023年6月8日
    0117
  • JavaScript快速入门-03-数据类型

    3 数据类型 3.1 简介 JavaScript中的每个值都是属于一种特定的数据类型。JavaScript中一共有以下几种数据类型,详细如下所示: 原始类型: Undefined、…

    Linux 2023年6月7日
    0164
  • Vim配置文件-详解(.vimrc)

    Vim配置文件的作用 Vim启动时,会根据配置文件(.vimrc)来设置 Vim,因此我们可以通过此文件来定制适合自己的 Vim 所有系统用户在启动Vim时,都会加载这个配置文件。…

    Linux 2023年6月13日
    092
  • 认识2020年的苹果设计奖获奖者

    苹果设计奖表彰那些在苹果平台上反映最佳设计、创新和技术的开发者的创造性艺术和技术成就。 塑钢3DShapr3D Zrt. 运行CAD软件通常需要一台具有相当处理能力的台式电脑。Sh…

    Linux 2023年6月7日
    078
  • Conda虚拟环境中的pip,python 等路径是base环境而非本虚拟环境

    现象 一次运行项目发现,原本可以正常运行的项目,突然提示有个包不存在,但是经过 pip list 发现在我的虚拟环境中是存在这个包的,并且此时我是正常的位于我的虚拟环境中。 报错:…

    Linux 2023年6月7日
    098
  • Golang 实现 Redis(6): 实现 pipeline 模式的 redis 客户端

    本文是使用 golang 实现 redis 系列的第六篇, 将介绍如何实现一个 Pipeline 模式的 Redis 客户端。 通常 TCP 客户端的通信模式都是阻塞式的: 客户端…

    Linux 2023年5月28日
    087
  • 跨平台(32bit和64bit)的 printf 格式符 %lld 输出64位的解决方式

    在 C/C++ 开发中,使用 printf 打印 64 位变量比较常用,通常在 32 位系统中使用 %lld 输出 64 位的变量,而在 64 位系统中则使用 %ld; 如果在 3…

    Linux 2023年6月7日
    095
  • 【原创】Linux虚拟化KVM-Qemu分析(二)之ARMv8虚拟化

    背景 Read the fucking source code! –By 鲁迅 A picture is worth a thousand words. –…

    Linux 2023年6月8日
    0101
  • Linux 下安装 node.js

    这里介绍两种安装方式: 编译安装和使用编译后的安装包安装。 安装目录: /usr/local 一、使用编译安装包安装 1、进入安装目录: 2、下载安装包: 3、解压: 4、进入解压…

    Linux 2023年6月13日
    0100
  • MSSQL中UPDATE与 INNER JOIN联用的语法结构

    | 0.16分钟 | 267.2字符 | 1、引言&背景 2、解决方案 3、声明与参考资料 | SCscHero | 2022/4/30 PM9:36 | 系列 | 已完成…

    Linux 2023年6月14日
    080
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球