注意:

本文为前文 再探 游戏 《 2048 》 —— AI方法—— 缘起、缘灭(1) —— Firefox浏览器自动运行篇 接续篇。

===========================================

下面给出在  鬼&泣 / 2048-ai   中对游戏环境的设计。

游戏环境的文件:

cpp_source/enviroment/2048_enviroment.cpp · 鬼&泣/2048-ai - Gitee.com

========================================

核心函数:

void init_tables()

static inline board_t transpose(board_t x)

static int count_empty(board_t x)
static inline board_t execute_move_0(board_t board)
static inline board_t execute_move_1(board_t board)
static inline board_t execute_move_2(board_t board)
static inline board_t execute_move_3(board_t board)

主要函数:

static board_t draw_tile()
 
static board_t insert_tile_rand(board_t board, board_t tile)
 
static board_t initial_board()
 
static float score_board(board_t board)
 
static float score_helper(board_t board, const float* table)
 

==================================================

void init_tables()  函数:

void init_tables() {
for (unsigned row = 0; row < 65536; ++row) {
unsigned line[4] = {
(row >> 0) & 0xf,
(row >> 4) & 0xf,
(row >> 8) & 0xf,
(row >> 12) & 0xf
}; // Score
float score = 0.0f;
for (int i = 0; i < 4; ++i) {
int rank = line[i];
if (rank >= 2) {
// the score is the total sum of the tile and all intermediate merged tiles
score += (rank - 1) * (1 << rank);
}
}
score_table[row] = score; // execute a move to the left
for (int i = 0; i < 3; ++i) {
int j;
for (j = i + 1; j < 4; ++j) {
if (line[j] != 0) break;
}
if (j == 4) break; // no more tiles to the right if (line[i] == 0) {
line[i] = line[j];
line[j] = 0;
i--; // retry this entry
} else if (line[i] == line[j]) {
if(line[i] != 0xf) {
/* Pretend that 32768 + 32768 = 32768 (representational limit). */
line[i]++;
}
line[j] = 0;
}
} row_t result = (line[0] << 0) |
(line[1] << 4) |
(line[2] << 8) |
(line[3] << 12);
row_t rev_result = reverse_row(result);
unsigned rev_row = reverse_row(row); row_left_table [ row] = row ^ result;
row_right_table[rev_row] = rev_row ^ rev_result;
col_up_table [ row] = unpack_col( row) ^ unpack_col( result);
col_down_table [rev_row] = unpack_col(rev_row) ^ unpack_col(rev_result);
}
}

游戏环境对一个游戏状态采用一个64bit长度的整数来进行表示,可以看到一个游戏状态包括16个数字,每个数字用4bit来表示,正好是16*4bit=64bit 。

由于一个格是用4bit来进行表示,那么可以表示的数字为0~15,这里分别用0~15表示0,2**1,2**2,2**3,......,2**15 。

每个格最大可以表示的数值为:

游戏状态中一行数据为4格数字,每个格数字用4bit表示(每个格可以表示的数字为0~15),一行数据用16bit表示,那么一行数据共有2**16种表示,即 65536 。

在函数  init_tables()   中遍历所有可表示状态:

在2048游戏中每一步可以获得一定的得分,该得分是根据该步骤操作可以获得的新数字的大小来计算的,比如将两个2合并为一个4,那么得分就是4;如果把两个8合并为一个16,那么得分就是16。但是需要注意的是游戏自动生成的新块是不进行得分计算的。因此在2048游戏中一个游戏状态在得知整个游戏过程中自动生成的4数字块的个数就可以根据此时的游戏状态计算出此时的游戏得分。在整个游戏过程中计数共自动生成了多少4数字块,scorepenalty 变量为生成的4数字块个数乘以得分4,具体实现为在每一步新块生成时如果是 4则自动为scorepenalty 变量加 4。

计算游戏状态的得分时我们分别根据不同行对应的的得分(score_table中的值)的和再减去 scorepenalty 变量即可。

从上代码可知,每行数据用数组line表示,从左向右分别为:line[0],line[1],line[2],line[3]。

每行数据向左移动的话生成的新的行数据可以如此计算:

需要注意的是在这里我们默认32768为最大表示数字,也就是说两个32768合并得到依然是32768 。

/* Pretend that 32768 + 32768 = 32768 (representational limit). */

得到的新的行数据用64bit来表示:

由于行数据的左移动所得的新行数据等价于原行数据左右调换后的行数据的右移动所得的新行数据,给出下面计算:

也就是说行数据row左移动得到result,row数据的左右调换后的rev_row的右移动得到rev_result数据。

需要注意的一个问题是由于在打印游戏状态时代码:

也就是说计算机中对游戏状态的表示和打印给人看到的状态表示其实是上下互相调换,左右也互相调换的。

=========================================

再探 游戏 《 2048 》 —— AI方法—— 缘起、缘灭(2) —— 游戏环境设计篇的更多相关文章

  1. 跟k8s工作负载Deployments的缘起缘灭

    跟k8s工作负载Deployments的缘起缘灭 考点之简单介绍一下什么是Deployments吧? 考点之怎么查看 Deployment 上线状态? 考点之集群中能不能设置多个Deployments ...

  2. 再探JS数组原生方法—没想到你是这样的数组

    最近作死又去做了一遍javascript-puzzlers上的44道变态题,这些题号称"JS语言专业八级"的水准,建议可以去试试,这里我不去解析这44道题了, ...

  3. 2048游戏分析、讨论与扩展 - Part I - 游戏分析与讨论

    2048这个游戏从刚出開始就风靡整个世界. 本技术博客的目的是想对2048涉及到相关的全部问题进行仔细的分析与讨论,得到一些大家能够接受而且理解的结果. 在这基础上,扩展2048的游戏性,使其变得更好 ...

  4. Android 带你玩转实现游戏2048 其实2048只是个普通的控件(转)

    1.概述 博主本想踏入游戏开放行业,无奈水太深,不会游泳:于是乎,只能继续开发应用,但是原生Android也能开发游戏么,2048.像素鸟.别踩什么来着:今天给大家带来一篇2048的开发篇,别怕不分上 ...

  5. Android 带你玩转实现游戏2048 其实2048只是个普通的控件

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/40020137,本文出自:[张鸿洋的博客] 1.概述 博主本想踏入游戏开放行业,无 ...

  6. 制作 2D 素材|基于 AI 5 天创建一个农场游戏,第 4 天

    欢迎使用 AI 进行游戏开发! 在本系列中,我们将使用 AI 工具在 5 天内创建一个功能完备的农场游戏.到本系列结束时,您将了解到如何将多种 AI 工具整合到游戏开发流程中.本系列文章将向您展示如何 ...

  7. ChatGPT 设计游戏剧情 | 基于 AI 5 天创建一个农场游戏,完结篇!

    欢迎使用 AI 进行游戏开发! 在本系列中,我们将使用 AI 工具在 5 天内创建一个功能完备的农场游戏.到本系列结束时,您将了解到如何将多种 AI 工具整合到游戏开发流程中.本文将向您展示如何将 A ...

  8. 【再探backbone 02】集合-Collection

    前言 昨天我们一起学习了backbone的model,我个人对backbone的熟悉程度提高了,但是也发现一个严重的问题!!! 我平时压根没有用到model这块的东西,事实上我只用到了view,所以昨 ...

  9. 再探jQuery

    再探jQuery 前言:在使用jQuery的时候发现一些知识点记得并不牢固,因此希望通过总结知识点加深对jQuery的应用,也希望和各位博友共同分享. jQuery是一个JavaScript库,它极大 ...

  10. [老老实实学WCF] 第五篇 再探通信--ClientBase

    老老实实学WCF 第五篇 再探通信--ClientBase 在上一篇中,我们抛开了服务引用和元数据交换,在客户端中手动添加了元数据代码,并利用通道工厂ChannelFactory<>类创 ...

随机推荐

  1. vits-simple-api搭建

    根据vits-simple-api中文文档指南自行搭建后端 以下步骤均在windows平台cpu推理搭建为例 选择你的vits模型(注意是vits!不是So-Vits Bert Vits2 Gpt V ...

  2. Java序列化和反序列化 Serializable BeanUtils.copyProperties赋值属性方法

    Java序列化和反序列化 Serializable BeanUtils.copyProperties赋值属性方法 package com.example.core.mydemo.java; impor ...

  3. 使用64位Office2016处理万级数据的过程

    先放下载和安装教程https://mp.weixin.qq.com/s/5ym9950_NZROlN0s2ZmLTg 由于同事电脑在使用Mysql for Excel插件处理十万级数据,如下图: 爆出 ...

  4. [UG 二次开发 PYTHON] 添加螺纹规格

    NX 1988 系列 在添加螺纹特征时,不能自定义螺纹规格, 从网上找到的资料上讲,改一个XML文件,在文件中添加自定义的螺纹规格,从而实现需要的效果. 自己写了一个小程序,方便手动添加螺纹规格. 效 ...

  5. spring-关于组件的注入及获取流程

    一.组件注入的基本流程: 容器初始化: Spring应用启动时,会读取配置(如XML配置.注解配置等),并根据这些配置创建Bean定义(BeanDefinition). 根据Bean定义,Spring ...

  6. 《Programming from the Ground Up》阅读笔记:p19-p48

    <Programming from the Ground Up>学习第2天,p19-p48总结,总计30页. 一.技术总结 1.object file p20, An object fil ...

  7. SpringBoot 整合Activiti 7.X 从入门到精通

    简介 Activiti 是一个轻量级工作流程和业务流程管理 (BPM) 平台,面向业务人员.开发人员和系统管理员.其核心是一个超快且坚如磐石的 Java BPMN 2 流程引擎.它是开源的,并根据 A ...

  8. Spring5.X的注解配置项目

    pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="htt ...

  9. SpringBoot 1.x 2.x配置文件指定服务项目名

    SpringBoot版本1.x: server.context-path=/demo SpringBoot版本2.x: server.servlet.context-path=/demo

  10. Unity无法安装Entities 1.2.0 Package的解决方法

    会出现如下的错误提示: 本质原因是国内版的Unity使用了自己的Package加速CDN:packages.unity.cn,而不是官方的packages.unity.com.而这个CDN更新了Ent ...