- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
这是我的 minmax 算法的代码:
private static void minmax(){
Move move = max(4, true, null);
//System.out.println(move);
board.makeMove(move.getFromPoint(), move.getToPoint());
}
private static Move max(int depth, boolean player, Move passedMove){
if(depth == 0) return passedMove.setScore(board.boardVal());
Move max = new Move(Integer.MIN_VALUE);
for(int i = 0; i < board.getMoves(player).size(); i++){
Move move = board.getMoves(player).get(i);
board.makeMove(move.getFromPoint(), move.getToPoint());
//System.out.println(board);
Move scoreMove = min(depth - 1, !player, move);
board.undo();
if(scoreMove.getScore() > max.getScore()) max = new Move(move.getFromPoint(), move.getToPoint(), scoreMove.getScore());
}
return max;
}
private static Move min(int depth, boolean player, Move passedMove){
if(depth == 0) return passedMove.setScore(-board.boardVal());
Move min = new Move(Integer.MAX_VALUE);
for(int i = 0; i < board.getMoves(player).size(); i++){
Move move = board.getMoves(player).get(i);
board.makeMove(move.getFromPoint(), move.getToPoint());
//System.out.println(board);
Move scoreMove = max(depth - 1, !player, move);
board.undo();
if(scoreMove.getScore() < min.getScore()) min = new Move(move.getFromPoint(), move.getToPoint(), scoreMove.getScore());
}
return min;
}
Move 是一个对象,它存储从位置、到位置以及移动后与棋盘值相关联的分数。 Move move = max(4, true, null);
行将 null 值分配给“move”(我不明白为什么),并且在运行这些方法后,它使板子处于一个奇怪的状态状态,似乎没有正确撤消移动,但我反复检查了该功能。
这是运行代码的示例(在注释掉 board.makeMove(move.getFromPoint(), move.getToPoint());
行以防止空指针异常之后):
8 [R] [N] [B] [Q] [K] [B] [N] [R]
7 [P] [P] [P] [P] [P] [P] [P] [P]
6 [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]
5 [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]
4 [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]
3 [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]
2 [P] [P] [P] [P] [P] [P] [P] [P]
1 [R] [N] [B] [Q] [K] [B] [N] [R]
a b c d e f g h
a2,a4
8 [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]
7 [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]
6 [ ] [ ] [ ] [ ] [ ] [ ] [N] [ ]
5 [ ] [ ] [N] [ ] [ ] [ ] [R] [K]
4 [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]
3 [ ] [ ] [ ] [ ] [ ] [ ] [B] [B]
2 [ ] [P] [ ] [ ] [ ] [ ] [ ] [ ]
1 [P] [ ] [R] [P] [P] [P] [P] [P]
a b c d e f g h
它只留下电脑的部分,移除所有玩家的部分。
移动类:
public class Move {
private Point fromPoint;
private Point toPoint;
private int score;
public Move(Point fromPoint, Point toPoint, int score){
this.fromPoint = fromPoint;
this.toPoint = toPoint;
this.score = score;
}
public Move(Point fromPoint, Point toPoint){
this(fromPoint, toPoint, 0);
}
public Move(int score){
this(null, null, score);
}
public Point getFromPoint() {
return fromPoint;
}
public Point getToPoint() {
return toPoint;
}
public int getScore() {
return score;
}
public Move setScore(int score){
this.score = score;
return this;
}
@Override
public String toString(){
return "(" + fromPoint.y + ", " + fromPoint.x + ")" + " (" + toPoint.y + ", " + toPoint.x + ") " + score;
}
}
Board 类建立在二维数组的 Stack 上,这里是 move 和 undo 方法:
public void makeMove(Point fromPoint, Point toPoint){
Piece[][] boardNode = new Piece[board.peek().length][];
for(int i = 0; i < boardNode.length; i++){ //this was changed
boardNode[i] = board.peek()[i].clone();
}
boardNode[fromPoint.y][fromPoint.x].setPoint(toPoint);
boardNode[toPoint.y][toPoint.x] = boardNode[fromPoint.y][fromPoint.x];
boardNode[fromPoint.y][fromPoint.x] = null;
board.push(boardNode);
}
public void undo(){
board.pop();
}
public ArrayList<Move> getMoves(boolean color){
ArrayList<Move> moves = new ArrayList<>();
for(Piece[] row : board.peek()){
for(Piece piece : row){
if(piece != null) {
for (Point point : piece.moves()) {
if (piece.getColor() == color && straightLine(piece.getPoint(), point) && (board.peek()[point.y][point.x] == null || board.peek()[point.y][point.x].getColor() != color)) moves.add(new Move(piece.getPoint(), point));
}
}
}
}
return moves;
}
我希望程序返回最佳移动(导致得分最高的棋盘状态的移动)并使棋盘保持执行 minmax 方法之前的状态。这些都没有发生,该方法返回 null 并且板已完全改变。
更改 Board 类中的 makeMove() 方法以正确复制棋盘后,我现在在该方法中收到 NullPointerExceptions:
8 [R] [N] [B] [Q] [K] [B] [N] [R]
7 [P] [P] [P] [P] [P] [P] [P] [P]
6 [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]
5 [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]
4 [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]
3 [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]
2 [P] [P] [P] [P] [P] [P] [P] [P]
1 [R] [N] [B] [Q] [K] [B] [N] [R]
a b c d e f g h
a2,a4
Exception in thread "main" java.lang.NullPointerException
at Board.makeMove(Board.java:45)
at ChessMain.min(ChessMain.java:87)
at ChessMain.max(ChessMain.java:75)
at ChessMain.min(ChessMain.java:89)
at ChessMain.max(ChessMain.java:75)
at ChessMain.minmax(ChessMain.java:63)
at ChessMain.play(ChessMain.java:58)
at ChessMain.main(ChessMain.java:15)
...
public abstract class Piece {
private boolean color;
private Point getPoint;
public Piece(int x, int y, boolean color){
this.color = color;
getPoint = new Point(x, y);
}
abstract int getValue();
public String toString(){
return "";
}
public void setPoint(Point point){
this.getPoint = point;
}
public Point getPoint(){ return getPoint; }
public boolean takable(Point point){ return containsPoint(moves(), point); }
private static boolean containsPoint(ArrayList<Point> list, Point point){
for(Point listPoint: list){
if(listPoint.x == point.x && listPoint.y == point.y) return true;
}
return false;
}
abstract ArrayList<Point> moves();
public boolean getColor(){ return color; }
}
这是一个扩展 Piece 的对象的例子:
import java.util.ArrayList;
public class Bishop extends Piece{
public Bishop(int x, int y, boolean color) {
super(x, y, color);
}
public ArrayList<Point> moves(){
ArrayList<Point> possibleMoves = new ArrayList<>();
int x = 1;
while(getPoint().x + x <= 7 && getPoint().y + x <= 7){
possibleMoves.add(new Point(getPoint().x + x, getPoint().y + x));
x++;
}
x = 1;
while(getPoint().x - x >= 0 && getPoint().y + x <= 7){
possibleMoves.add(new Point(getPoint().x - x, getPoint().y + x));
x++;
}
x = 1;
while(getPoint().x - x >= 0 && getPoint().y - x >= 0){
possibleMoves.add(new Point(getPoint().x - x, getPoint().y - x));
x++;
}
x = 1;
while(getPoint().x + x <= 7 && getPoint().y - x >= 0){
possibleMoves.add(new Point(getPoint().x + x, getPoint().y - x));
x++;
}
return possibleMoves;
}
@Override
public String toString(){ return "B"; }
public int getValue(){ return 3;}
}
如果更多信息有帮助,请告诉我。
感谢任何帮助。
最佳答案
我能看到的一个问题:
public void makeMove(Point fromPoint, Point toPoint){
Piece[][] boardNode = board.peek(); // WARNING!!!
// Instead, make a copy of the previous board state
// so you don't change all board states when you want to change one.
boardNode[fromPoint.y][fromPoint.x].setPoint(toPoint);
boardNode[toPoint.y][toPoint.x] = boardNode[fromPoint.y][fromPoint.x];
boardNode[fromPoint.y][fromPoint.x] = null;
board.push(boardNode); // WARNING!!!
}
您的board
在堆栈的每一层都使用相同的引用。
当你调用 Piece[][] boardNode = board.peek(); ... board.push(boardNode);
您实际上只是对所有板状态使用相同的引用,并且修改其中一个将修改所有它们引用的对象..我认为这不是您的意思想要。
这可能是您问题的根源,如果除此之外还有更多问题,请更新您的问题。
更新:
克隆棋盘状态的二维数组仍然是个问题。您克隆了数组而不是其中的 Piece
,因此当您更新 piece 的位置时,它正在更新该对象的所有状态的棋盘引用。
首先,让Piece实现Cloneable
public abstract class Piece implements Cloneable {
// ...
@Override
public abstract Piece clone();
然后让所有子 Pieces
实际上克隆自己,例如 Pawn
这样做:
@Override
public Pawn clone() {
return new Pawn(getPoint.x, getPoint.y, color);
}
然后克隆你的二维数组:
public void makeMove(Point fromPoint, Point toPoint) {
final Piece[][] prevBoard = board.peek();
final int width = prevBoard.length;
Piece[][] boardNode = new Piece[width][];
for (int i = 0; i < width; i++) {
final int height = prevBoard[i].length;
boardNode[i] = new Piece[height];
for (int j = 0; j < height; j++) {
Piece p = prevBoard[i][j];
if (p == null) {
boardNode[i][j] = null;
} else {
boardNode[i][j] = p.clone();
}
}
}
这似乎让你走上了正确的轨道,但现在看起来对手正在移动玩家的棋子,或者类似的东西。
祝大家好运!
关于Java minmax 算法返回空移动并且无法正确撤消移动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49497793/
滑动窗口限流 滑动窗口限流是一种常用的限流算法,通过维护一个固定大小的窗口,在单位时间内允许通过的请求次数不超过设定的阈值。具体来说,滑动窗口限流算法通常包括以下几个步骤: 初始化:设置窗口
表达式求值:一个只有+,-,*,/的表达式,没有括号 一种神奇的做法:使用数组存储数字和运算符,先把优先级别高的乘法和除法计算出来,再计算加法和减法 int GetVal(string s){
【算法】前缀和 题目 先来看一道题目:(前缀和模板题) 已知一个数组A[],现在想要求出其中一些数字的和。 输入格式: 先是整数N,M,表示一共有N个数字,有M组询问 接下来有N个数,表示A[1]..
1.前序遍历 根-左-右的顺序遍历,可以使用递归 void preOrder(Node *u){ if(u==NULL)return; printf("%d ",u->val);
先看题目 物品不能分隔,必须全部取走或者留下,因此称为01背包 (只有不取和取两种状态) 看第一个样例 我们需要把4个物品装入一个容量为10的背包 我们可以简化问题,从小到大入手分析 weightva
我最近在一次采访中遇到了这个问题: 给出以下矩阵: [[ R R R R R R], [ R B B B R R], [ B R R R B B], [ R B R R R R]] 找出是否有任
我正在尝试通过 C++ 算法从我的 outlook 帐户发送一封电子邮件,该帐户已经打开并记录,但真的不知道从哪里开始(对于 outlook-c++ 集成),谷歌也没有帮我这么多。任何提示将不胜感激。
我发现自己像这样编写了一个手工制作的 while 循环: std::list foo; // In my case, map, but list is simpler auto currentPoin
我有用于检测正方形的 opencv 代码。现在我想在检测正方形后,代码运行另一个命令。 代码如下: #include "cv.h" #include "cxcore.h" #include "high
我正在尝试模拟一个 matlab 函数“imfill”来填充二进制图像(1 和 0 的二维矩阵)。 我想在矩阵中指定一个起点,并像 imfill 的 4 连接版本那样进行洪水填充。 这是否已经存在于
我正在阅读 Robert Sedgewick 的《C++ 算法》。 Basic recurrences section it was mentioned as 这种循环出现在循环输入以消除一个项目的递
我正在思考如何在我的日历中生成代表任务的数据结构(仅供我个人使用)。我有来自 DBMS 的按日期排序的任务记录,如下所示: 买牛奶(18.1.2013) 任务日期 (2013-01-15) 任务标签(
输入一个未排序的整数数组A[1..n]只有 O(d) :(d int) 计算每个元素在单次迭代中出现在列表中的次数。 map 是balanced Binary Search Tree基于确保 O(nl
我遇到了一个问题,但我仍然不知道如何解决。我想出了如何用蛮力的方式来做到这一点,但是当有成千上万的元素时它就不起作用了。 Problem: Say you are given the followin
我有一个列表列表。 L1= [[...][...][.......].......]如果我在展平列表后获取所有元素并从中提取唯一值,那么我会得到一个列表 L2。我有另一个列表 L3,它是 L2 的某个
我们得到二维矩阵数组(假设长度为 i 和宽度为 j)和整数 k我们必须找到包含这个或更大总和的最小矩形的大小F.e k=7 4 1 1 1 1 1 4 4 Anwser是2,因为4+4=8 >= 7,
我实行 3 类倒制,每周换类。顺序为早类 (m)、晚类 (n) 和下午类 (a)。我固定的订单,即它永远不会改变,即使那个星期不工作也是如此。 我创建了一个函数来获取 ISO 周数。当我给它一个日期时
假设我们有一个输入,它是一个元素列表: {a, b, c, d, e, f} 还有不同的集合,可能包含这些元素的任意组合,也可能包含不在输入列表中的其他元素: A:{e,f} B:{d,f,a} C:
我有一个子集算法,可以找到给定集合的所有子集。原始集合的问题在于它是一个不断增长的集合,如果向其中添加元素,我需要再次重新计算它的子集。 有没有一种方法可以优化子集算法,该算法可以从最后一个计算点重新
我有一个包含 100 万个符号及其预期频率的表格。 我想通过为每个符号分配一个唯一(且前缀唯一)的可变长度位串来压缩这些符号的序列,然后将它们连接在一起以表示序列。 我想分配这些位串,以使编码序列的预
我是一名优秀的程序员,十分优秀!