- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我已经为此工作了很长时间,以至于它不再有趣了。我正在尝试在 Tic Tac Toe 上实现 Minmax,虽然我已经获得了多个版本的 AI,这些版本可以做出合理的初始 Action ,但我永远无法做出永不失败的 AI。
我无法解决的问题之一是启发值。它目前在第一次 Minmax 调用时返回 -10,而它应该返回 0(无论发生什么,它都应该能够绘制)。
另一个问题是它运行了 400,000 次迭代,而 322,000 是最大值并且在早期获胜的情况下,甚至应该停止在 250,000 左右。
任何帮助将不胜感激。
int MiniMax(TGameBoard _GameBoard)
{
//Always goes for max of course, just expanded in case you wanted two AIs
int iBestMove;
int iHeuristicReturned = 0;
if (_GameBoard.ePlayer == COMPUTER)
{
iHeuristicReturned = MaxMove(_GameBoard, iBestMove);
}
else
{
iHeuristicReturned = MinMove(_GameBoard, iBestMove);
}
//cout<<"\nHeuristic is "<<iHeuristicReturned<<endl;
g_iHeuristic = iHeuristicReturned;
return iBestMove;
}
int MaxMove(TGameBoard _GameBoard, int& _iMove)
{
//Logic
//If its an end node, calculate the score
//Otherwise, do minmax until the end node, and pass back the value
//If returned value is greater than v, then pass the move back upwards
++g_iIterations;
if(_GameBoard.CheckWinner(_GameBoard) || _GameBoard.IsFull())
{
int x;
x = EvaluateStaticPosition(_GameBoard, MAX);
return EvaluateStaticPosition(_GameBoard, MAX);
}
vector<int> moveList;
GenerateMoveList(_GameBoard, moveList);
int iNumMoves = moveList.size();
int v = -10000;
for(int i = 0; i < iNumMoves; ++i)
{
int iMove = moveList[i];
_GameBoard.Set(iMove, CROSS);
int opponentsBestMove;
++g_iDepth;
int curRating = MinMove(_GameBoard, opponentsBestMove);
--g_iDepth;
if (curRating > v)
{
v = curRating;
_iMove = iMove;
}
RetractMove(&_GameBoard, iMove);
}
return v;
}
int MinMove(TGameBoard _GameBoard, int& _iMove)
{
++g_iIterations;
if (g_iIterations > 320000)
{
int x = 0;
}
if(_GameBoard.CheckWinner(_GameBoard) || _GameBoard.IsFull())
{
return EvaluateStaticPosition(_GameBoard, MIN);
}
vector<int> moveList;
GenerateMoveList(_GameBoard, moveList);
int iNumMoves = moveList.size();
int v = 10000;
for(int i = 0; i < iNumMoves; ++i)
{
int iMove = moveList[i];
_GameBoard.Set(iMove, NAUGHT);
int opponentsBestMove;
++g_iDepth;
int curRating = MaxMove(_GameBoard, opponentsBestMove);
--g_iDepth;
if (curRating < v)
{
v = curRating;
_iMove = iMove;
}
RetractMove(&_GameBoard, iMove);
}
return v;
}
int EvaluateStaticPosition(TGameBoard _GameBoard, EGoal _eGoal)
{
if(_GameBoard.CheckWinner(_GameBoard, COMPUTER))
{
return 10;
}
if(_GameBoard.CheckWinner(_GameBoard, PLAYER))
{
return -10;
}
return 0;
}
其他相关功能可以在这里检查,但我很确定它们没问题。 http://pastebin.com/eyaNfBsq
是的,我知道有一些不必要的参数 - 在我自己的版本失败后,我尝试按照互联网上的教程进行操作。不幸的是,他们给出了相同的结果。
我已经处理了 12 个小时,这似乎是一项如此简单的任务,无法找出问题所在
最佳答案
以下代码可能对您有所帮助:
(奖励:检查不到 8000 个板的字母表。)
#include <algorithm>
#include <array>
#include <cassert>
#include <iostream>
enum class Square
{
Empty,
O,
X
};
Square other(Square c) {
switch (c) {
case Square::O: return Square::X;
case Square::X: return Square::O;
default: assert(0); return Square::Empty;
};
}
template <typename STREAM>
STREAM& operator << (STREAM& stream, Square c)
{
switch (c)
{
case Square::Empty: stream << "."; break;
case Square::X: stream << "X"; break;
case Square::O: stream << "O"; break;
}
return stream;
}
class Board
{
public:
Board() : board({{Square::Empty, Square::Empty, Square::Empty,
Square::Empty, Square::Empty, Square::Empty,
Square::Empty, Square::Empty, Square::Empty}})
{}
void display() const {
for (int y = 0; y != 3; ++y) {
for (int x = 0; x != 3; ++x) {
std::cout << board[3 * y + x] << " ";
}
std::cout << std::endl;
}
}
void play(unsigned int x, unsigned int y, Square c)
{
assert(x < 3);
assert(y < 3);
board[3 * y + x] = c;
}
void play(unsigned int offset, Square c)
{
assert(offset < 9);
board[offset] = c;
}
bool isFull() const {
return std::find(board.cbegin(), board.cend(), Square::Empty) == board.cend();
}
int computeScore(Square c) const
{
for (int i = 0; i < 3; ++i) {
if (board[3 * i] != Square::Empty && board[3 * i] == board[3 * i + 1] && board[3 * i] == board[3 * i + 2]) {
return board[3 * i] == c ? 1 : -1;
}
if (board[i] != Square::Empty && board[i] == board[i + 3] && board[i] == board[i + 6]) {
return board[i] == c ? 1 : -1;
}
}
if (board[4] == Square::Empty) {
return 0;
}
if ((board[4] == board[0] && board[4] == board[8])
|| (board[4] == board[2] && board[4] == board[6])) {
return board[4] == c ? 1 : -1;
}
return 0;
}
int minmax(Square c, unsigned int* counter, unsigned int* pos = NULL)
{
const int currentScore = computeScore(c);
if (currentScore != 0 || isFull()) {
if (counter) {++*counter; }
return currentScore;
}
int bestScore = -10;
for (unsigned int i = 0; i != 9; ++i) {
if (board[i] != Square::Empty) { continue; }
play(i, c);
int score = -minmax(other(c), counter);
if (bestScore < score) {
bestScore = score;
if (pos) { *pos = i; }
}
play(i, Square::Empty);
}
return bestScore;
}
int alphabeta(Square c, int alpha, int beta, unsigned int* counter, unsigned int* pos = NULL)
{
const int currentScore = computeScore(c);
if (currentScore != 0 || isFull()) {
if (counter) {++*counter; }
return currentScore;
}
for (unsigned int i = 0; i != 9; ++i) {
if (board[i] != Square::Empty) { continue; }
play(i, c);
int score = -alphabeta(other(c), -beta, -alpha, counter);
if (beta <= score) {
if (pos) { *pos = i; }
play(i, Square::Empty);
return score;
}
if (alpha < score) {
alpha = score;
if (pos) { *pos = i; }
}
play(i, Square::Empty);
}
return alpha;
}
private:
std::array<Square, 9> board;
};
int main()
{
Board b;
Square c = Square::X;
while (b.computeScore(Square::X) == 0 && b.isFull() == false) {
std::cout << c << " to play" << std::endl;
b.display();
unsigned int counter = 0;
unsigned int pos;
const int s = b.minmax(c, &counter, &pos);
//const int s = b.alphabeta(c, -10, 10, &counter, &pos);
b.play(pos, c);
std::cout << "score for "<< c <<" = " << s << std::endl;
std::cout << "#final boards examined = " << counter << std::endl;
std::cout << "----------------" << std::endl;
c = other(c);
}
std::cout << "Final score for X = " << b.computeScore(Square::X) << std::endl;
b.display();
return 0;
}
“迭代”的计数是最终检查的电路板的数量。
关于C++ 最小最大失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18590305/
“用 Haskell 进行函数式思考”中的练习之一是使用融合定律使程序更加高效。我在尝试复制答案时遇到了一些麻烦。 部分计算要求您将 maximum (xs++ map (x+) xs) 转换为 ma
我正在尝试获得 R 中最大/最小的可表示数字。 输入“.Machine”后 我有: $double.xmin [1] 2.225074e-308 $double.xmax [1] 1.797693e+
有没有办法更改浏览器验证消息 请检查所附图片。 我目前正在使用 wooCommerce 目前它显示小于或等于 X 个数字,我想更改为请求超过 X 个项目的报价。 请多多指教 最佳答案 您需要使用oni
我正在尝试将解决方案从 Excel 求解器复制到 R 中,但不知道从哪里开始。 问题: 每小时选择 5 个选项(5 行),以最大化“分数”的总和,而无需在多个小时内选择同一组 2 次。 换句话说: 最
Haskell 中是否有这样的功能: max_of_type :: (Num a) => a 所以: max_of_type :: Int == 2 ^ 31 - 1 // for example,
我有这两个表示时间范围(秒)的输入字段,我需要这样设置,以便“from/min”字段不能高于“to/max”,反之亦然。 到目前为止我得到了这个: jQuery(document).ready(fun
我有一个看起来像这样的表: http://sqlfiddle.com/#!9/152d2/1/0 CREATE TABLE Table1 ( id int, value decimal(10,
我会尝试尽可能简单地解释它: 首先是一些带有虚拟数据的数据库结构。 结构 tb_spec_fk feature value ----------------- 1 1 1
我有两个表。 表 1: +---------+---------+ | Lead_ID | Deal_ID | +---------+---------+ | 2323 | null |
我的数据库中有一个字段可以包含数字,例如8.00 或范围编号,例如8.00 - 10.00。 如果您将每个数字作为单独的数字,我需要从表中获取 MIN() 和 MAX()。例如当范围为 8.00 -
max(float('nan'), 1) 计算结果为 nan max(1, float('nan')) 计算结果为 1 这是预期的行为吗? 感谢您的回答。 max 在 iterable 为空时引发异常
我想问一下如何在 CSS 中创建一个页脚栏,它具有最小宽度(比如 650 像素),并且会根据窗口大小进行拉伸(stretch),但仅限于某个点(比如 1024 像素)。 我的意思是当窗口大小为例如 1
我尝试调整表格列宽(下一个链接上的“作者”列 http://deploy.jtalks.org/jcommune/branches/1?lang=en)。我已将最小/最大属性添加到 .author-c
在 C# 中,是否有用于将最小值和最大值存储为 double 值的内置类? 此处列出的要点 http://msdn.microsoft.com/en-us/library/system.windows
问题: 每个任务队列是否可以每秒处理超过 500 个任务? 每个 GAE 应用是否可以每秒处理超过 50,000 个任务? 详细信息: Task queue quota文档说: Push Queue
我想知道是否允许最大或最小堆树具有重复值?我试图仅通过在线资源查找与此相关的信息,但一直没有成功。 最佳答案 是的,他们可以。您可以在“算法简介”(Charles E. Leiserson、Cliff
首先,我是 .NET 开发人员,喜欢 C# 中的 LINQ 和扩展方法。 但是当我编写脚本时,我需要相当于 Enumerable extension methods 的东西 任何人都可以给我任何建议/
这是一个检查最大 malloc 大小的简单程序: #include std::size_t maxDataSize = 2097152000; //2000mb void MallocTest(vo
我想找到我的数据的最小值和最大值。 我的数据文件: 1 2 4 5 -3 -13 112 -3 55 42 42 而我的脚本: {min=max=$1} {if ($1max) {max=$1}
我想查询我的Elastic-Search以获取仅具有正值的最低价格价格。我的价格也可以为零和-1;所以我不希望我的最小聚合返回0或-1。我知道我应该向查询(或过滤器)添加脚本,但是我不知道如何。我当前
我是一名优秀的程序员,十分优秀!