private int CalculateValue(ref AIHardDataStruct curDepthData, bool isEndGame) { int value = 0; if (isEndGame) { if (CheckWinner(ref curDepthData)) { //玩家赢则权值最低 value += -10000; } else { //AI赢则权值最高 value += 10000; } } if (curDepthData.depth % 2 == 0) { return(value + CalculateCurValue(ref curDepthData)); } else { return(-(value + CalculateCurValue(ref curDepthData))); } }
private void SelectPiece(ref AIHardDataStruct curDepthData, int x, int y) { Piece[,] curPieces = curDepthData.pieces; List <Piece> curNextPieces = curDepthData.nextPieces; curPieces[x, y].isValid = false; DeletePiece(ref curDepthData, x, y); List <Piece> changedPieces = new List <Piece>();//去掉了注释 若不去掉注释会导致碎裂棋子重复计算 if (x - 1 >= 0 && curPieces[x - 1, y].isValid) { curPieces[x - 1, y].isDownHasPiece = false; if (!changedPieces.Contains(curPieces[x - 1, y])) { changedPieces.Add(curPieces[x - 1, y]); } } if (x + 1 < GameManager.Instance.gamePlayMode.boardSideLength && curPieces[x + 1, y].isValid) { curPieces[x + 1, y].isUpHasPiece = false; if (!changedPieces.Contains(curPieces[x + 1, y])) { changedPieces.Add(curPieces[x + 1, y]); } } if (y - 1 >= 0 && curPieces[x, y - 1].isValid) { curPieces[x, y - 1].isRightHasPiece = false; if (!changedPieces.Contains(curPieces[x, y - 1])) { changedPieces.Add(curPieces[x, y - 1]); } } if (y + 1 < GameManager.Instance.gamePlayMode.boardSideLength && curPieces[x, y + 1].isValid) { curPieces[x, y + 1].isLeftHasPiece = false; if (!changedPieces.Contains(curPieces[x, y + 1])) { changedPieces.Add(curPieces[x, y + 1]); } } foreach (var v in changedPieces) { if (curNextPieces.Contains(v) && !CheckIsCanGoUp(curPieces, x, y)) { curNextPieces.Remove(v); } else if (CheckIsCanGoUp(curPieces, v.x, v.y)) { if (!curNextPieces.Contains(v)) { curNextPieces.Add(v); } } } }
private int ABPruning(ref AIHardDataStruct curDepthData, int alpha, int beta, bool isEndGame) { if (curDepthData.depth > ABPruningDepth || isEndGame) { return(CalculateValue(ref curDepthData, isEndGame)); } Dictionary <PieceColor, List <Piece> > piecesByColor = GroupByColor(curDepthData.nextPieces); int bestValue = -0x7FFFFFF; foreach (var pieces in piecesByColor) { List <List <Piece> > combinations = new List <List <Piece> >(); for (int i = 1; i <= pieces.Value.Count; ++i) { List <Piece[]> tmp; tmp = Algorithms.PermutationAndCombination <Piece> .GetCombination(pieces.Value.ToArray(), i); foreach (var v in tmp) { List <Piece> combination = new List <Piece>(); for (int j = 0; j < v.GetLength(0); ++j) { combination.Add(v[j]); } combinations.Add(combination); } } foreach (var combination in combinations) { AIHardDataStruct nextDepthData = curDepthData.Clone(); bool isNextEndGame = SelectCombination(ref nextDepthData, combination); nextDepthData.depth++; int nextValue = -ABPruning(ref nextDepthData, -beta, -alpha, isNextEndGame); if (nextValue > bestValue) { bestValue = nextValue; curDepthData.bestCombination = combination; } if (bestValue > alpha) { alpha = bestValue; } if (bestValue >= beta) { return(bestValue); } } } return(bestValue); }
private void GetScore(ref AIHardDataStruct curDepthData, PieceColor color) { if (curDepthData.depth % 2 != 0) { curDepthData.playerRecord.secord[(int)color]++; } else { curDepthData.aiRecord.secord[(int)color]++; } }
public AIHardDataStruct Clone() { AIHardDataStruct tar = new AIHardDataStruct(); tar.pieces = CopyPieces(); tar.nextPieces = CopyCurNextPieces(); tar.playerRecord = playerRecord.Clone(); tar.aiRecord = aiRecord.Clone(); tar.depth = depth; return(tar); }
private void DeletePiece(ref AIHardDataStruct curDepthData, int x, int y) { Piece[,] curPieces = curDepthData.pieces; List <Piece> curNextPieces = curDepthData.nextPieces; if (!curNextPieces.Contains(curPieces[x, y])) { Debug.LogError("Not A Valid Piece"); } GetScore(ref curDepthData, curPieces[x, y].pieceColor); curNextPieces.Remove(curPieces[x, y]); curPieces[x, y].isValid = false; }
//true是玩家赢 false是AI赢 private bool CheckWinner(ref AIHardDataStruct curDepthData) { GamePlayMode gpm = GameManager.Instance.gamePlayMode; //先判断是否获得一种颜色的全部棋子 foreach (int s in curDepthData.playerRecord.secord) { if (s >= gpm.boardSideLength) { return(true); } } foreach (int s in curDepthData.aiRecord.secord) { if (s >= gpm.boardSideLength) { return(false); } } int playerControledNum = 0; foreach (var v in curDepthData.playerRecord.secord) { if (v > gpm.boardSideLength / 2) { ++playerControledNum; } } int aiControledNum = 0; foreach (var v in curDepthData.aiRecord.secord) { if (v > gpm.boardSideLength / 2) { ++aiControledNum; } } //再判断谁的分数更高 if (playerControledNum > aiControledNum) { return(true); } else { return(false); } }
//返回true则继续往下递归 返回false则停止 private bool SelectCombination(ref AIHardDataStruct curDepthData, List <Piece> combination) { //选择棋子 foreach (var piece in combination) { SelectPiece(ref curDepthData, piece.x, piece.y); if (CheckEndGame(ref curDepthData)) { return(true); } } if (EngTurn(ref curDepthData)) { return(true); } return(false); }
private void MoveInHardLevel() { Debug.Log("MoveInHardLevel"); BeginCalculate(); if (GameManager.Instance.boardManager.GetPieceRemainNum() > 20) { ABPruningDepth = 4; } else if (GameManager.Instance.boardManager.GetPieceRemainNum() > 10) { ABPruningDepth = 5; } else { ABPruningDepth = 6; } Piece[,] curPieces = boardManager.GetPieces(); List <Piece> curNextPieces = boardManager.GetNextPieces(); PlayerRecord playerRecord = GameManager.Instance.controller.GetScoreValue(); PlayerRecord aiRecord = GameManager.Instance.controller2.GetScoreValue(); int curDepth = 0; int alpha = -0x7FFFFFFE; int beta = 0x7FFFFFFE; AIHardDataStruct curDepthData = new AIHardDataStruct(curPieces, curNextPieces, playerRecord, aiRecord, curDepth); Debug.Log("ABPruningDepth: " + ABPruningDepth); ABPruning(ref curDepthData, alpha, beta, false); Debug.Log("curDepthData.bestCombination count: " + curDepthData.bestCombination.Count); List <Piece> abRes = curDepthData.bestCombination; foreach (var v in abRes) { result.Add(new AIResult(v.x, v.y)); } Debug.Log("EndCalculate"); EndCalculate(); }
private bool EngTurn(ref AIHardDataStruct curDepthData) { List <Piece> nextPieces = curDepthData.nextPieces; Piece[,] pieces = curDepthData.pieces; GamePlayMode gpm = GameManager.Instance.gamePlayMode; bool isChanged = true; while (isChanged) { isChanged = false; if (gpm.doUseCrack) { List <Piece> crackPieces = new List <Piece>(); foreach (var p in nextPieces) { if (p.isValid && p.isCrackPiece) { crackPieces.Add(p); isChanged = true; } } if (isChanged) { foreach (var p in crackPieces) { SelectPiece(ref curDepthData, p.x, p.y); if (CheckEndGame(ref curDepthData)) { return(true); } } } } } return(false); }
private int CalculateCurValue(ref AIHardDataStruct curDepthData) { GamePlayMode gpm = GameManager.Instance.gamePlayMode; int playerValue = 0; int aiValue = 0; for (int i = 0; i < curDepthData.playerRecord.secord.GetLength(0); ++i) { var v = curDepthData.playerRecord.secord[i]; if (curDepthData.aiRecord.secord[i] > gpm.boardSideLength / 2) { playerValue += v > 0 ? 20 : 0; } else if (v > gpm.boardSideLength / 2) { playerValue += 1000; if (curDepthData.aiRecord.secord[i] > 0) { playerValue += (10 + 4 * 10) * 4 / 2; } else { playerValue += (10 + v * 10) * v / 2; } } else { playerValue += (10 + v * 10) * v / 2; } } for (int i = 0; i < curDepthData.aiRecord.secord.GetLength(0); ++i) { var v = curDepthData.aiRecord.secord[i]; if (curDepthData.playerRecord.secord[i] > gpm.boardSideLength / 2) { aiValue += v > 0 ? 20 : 0; } else if (v > gpm.boardSideLength / 2) { aiValue += 1000; if (curDepthData.playerRecord.secord[i] > 0) { aiValue += (10 + 4 * 10) * 4 / 2; } else { aiValue += (10 + v * 10) * v / 2; } } else { aiValue += (10 + v * 10) * v / 2; } } int value = aiValue - playerValue; if (curDepthData.depth % 2 == 0) { return(value); } else { return(value); } }
private bool CheckEndGame(ref AIHardDataStruct curDepthData) { List <Piece> curNextPieces = curDepthData.nextPieces; PlayerRecord curPlayerRecord = curDepthData.playerRecord; PlayerRecord curAiRecord = curDepthData.aiRecord; GamePlayMode gpm = GameManager.Instance.gamePlayMode; if (curNextPieces.Count <= 0) { return(true); } foreach (int s in curPlayerRecord.secord) { if (s >= gpm.boardSideLength) { return(true); } } foreach (int s in curAiRecord.secord) { if (s >= gpm.boardSideLength) { return(true); } } int controllNum = 0; int takeNum = 0; foreach (int s in curAiRecord.secord) { if (s > 0) { takeNum++; } if (s > gpm.boardSideLength / 2) { controllNum++; } } if (controllNum > gpm.boardSideLength / 2 && takeNum >= gpm.boardSideLength) { return(true); } controllNum = 0; takeNum = 0; foreach (int s in curPlayerRecord.secord) { if (s > 0) { takeNum++; } if (s > gpm.boardSideLength / 2) { controllNum++; } } if (controllNum > gpm.boardSideLength / 2 && takeNum >= gpm.boardSideLength) { return(true); } return(false); }