void GenerateNextTetris() { nextTetrisType = randGen.Next(7); //选择类型 nextChangeType = randGen.Next(4); //选择变体 nextChangeType = nextChangeType % changeNum[nextTetrisType]; nextOffset = tetrisOffset[nextTetrisType][nextChangeType]; }
bool RunGridMove(Direction dir) { Grid[] nextGrids = null; switch (dir) { case Direction.DOWN: nextGrids = GetRunGridsAtPos(currentRunGridX, currentRunGridY + 1, currentOffset); if (!CheckNextGridValid(nextGrids)) { return(false); } currentRunGridY++; break; case Direction.LEFT: nextGrids = GetRunGridsAtPos(currentRunGridX - 1, currentRunGridY, currentOffset); if (!CheckNextGridValid(nextGrids)) { return(false); } currentRunGridX--; break; case Direction.RIGHT: nextGrids = GetRunGridsAtPos(currentRunGridX + 1, currentRunGridY, currentOffset); if (!CheckNextGridValid(nextGrids)) { return(false); } currentRunGridX++; break; case Direction.UP: { int changType = (curChangeType + 1) % changeNum[curTetrisType]; SceneOffset offset = tetrisOffset[curTetrisType][changType]; nextGrids = GetRunGridsAtPos(currentRunGridX, currentRunGridY, offset); if (!CheckNextGridValid(nextGrids)) { return(false); } currentOffset = offset; curChangeType = changType; } break; } foreach (Grid g in runGrids) { g.show = false; g.running = false; } runGrids = nextGrids; foreach (Grid g in runGrids) { g.show = true; g.running = true; } return(true); }
//在某个坐标位置生成掉落方块 Grid[] GetRunGridsAtPos(int x, int y, SceneOffset offset) { Grid[] grids = new Grid[4]; grids[0] = GetGridByPos(x + offset.X1, y + offset.Y1); grids[1] = GetGridByPos(x + offset.X2, y + offset.Y2); grids[2] = GetGridByPos(x + offset.X3, y + offset.Y3); grids[3] = GetGridByPos(x + offset.X4, y + offset.Y4); return(grids); }
//预览区初始化 void CalcPreGrids() { SceneOffset offset = nextOffset; foreach (Grid g in nextPreGrids) { if (g != null) { g.show = false; } } nextPreGrids[0] = preGrids[kPreBornX + offset.X1, kPreBornY + offset.Y1]; nextPreGrids[1] = preGrids[kPreBornX + offset.X2, kPreBornY + offset.Y2]; nextPreGrids[2] = preGrids[kPreBornX + offset.X3, kPreBornY + offset.Y3]; nextPreGrids[3] = preGrids[kPreBornX + offset.X4, kPreBornY + offset.Y4]; foreach (Grid g in nextPreGrids) { g.show = true; } }
//一轮下落的开始 void OnNextRound() { currentRunGridX = kRunGridBirthX; currentRunGridY = kRunGridBirthY; if (nextOffset == null) { GenerateNextTetris(); } currentOffset = nextOffset; curChangeType = nextChangeType; curTetrisType = nextTetrisType; //把预览区的offset移到游戏区 runGrids = GetRunGridsAtPos(currentRunGridX, currentRunGridY, currentOffset); if (!CheckNextGridValid(runGrids)) { gameState = GameState.GameOver; return; } foreach (Grid g in runGrids) { g.running = true; g.show = true; } //生成预览区的offset GenerateNextTetris(); //计算预览区网格 CalcPreGrids(); gameState = GameState.NormalDrop; if (IsAiControl) { CalcAICtrl(); } }
//Pierre Dellacherie算法 void CalcAI2() { //先把正在下落的格子显示状态抹除 foreach (var g in runGrids) { g.show = false; } int R_X = 0; //最优坐标 int R_Change = 0; //最优变换次数 int R_ChangeType = 0; int R_Value = -9999; //最优评估值 int changeType = curChangeType; for (int change = 0; change < changeNum[curTetrisType]; change++) { SceneOffset local_offset = localOffset[curTetrisType][changeType]; for (int x = 0; x < kSceneWidth; x++) { Grid[] lastValidGrids = null; for (int y = 0; y < kSceneHeight; y++) { var showGrids = GetRunGridsAtPos(x, y, local_offset); if (!CheckAIGridValid(showGrids)) { break; } lastValidGrids = showGrids; } if (lastValidGrids != null) { int landingHeight = aiCalcLandingHeight(lastValidGrids); int eraseLine = aiCalcEraseLine(lastValidGrids); var finalGrids = aiCalcFinalGrids(lastValidGrids); int boardRowTransitions = aiCalcRow(finalGrids); int boardColTransitions = aiCalcColumn(finalGrids); int boardBuriedHoles = aiCalcHoles(finalGrids); int wells = aiCalcWell(finalGrids); int value = -45 * landingHeight + 34 * eraseLine - 32 * boardRowTransitions - 93 * boardColTransitions - (79 * boardBuriedHoles) - 34 * wells; if (value > R_Value) { R_Value = value; R_X = x; R_Change = change; R_ChangeType = changeType; } } } //遍历所有变形 changeType = (changeType + 1) % changeNum[curTetrisType]; } var offset = tetrisOffset[curTetrisType][R_ChangeType]; int moveX = R_X - offset.X1 - currentRunGridX; foreach (var g in runGrids)//还原显示状态 { g.show = true; } RunAISteps(moveX, R_Change); }
//计算一个结果最好的X坐标落下去 //1.选形状完全匹配的,如果有多个匹配进入2; //2.选消除行数最多的,如果有多个匹配进入3; //3.选高度最低的,如果有多个匹配选第一个; void CalcAI1() { //先把正在下落的格子显示状态抹除 foreach (var g in runGrids) { g.show = false; } List <CheckResult> results = new List <CheckResult>(); int changeType = curChangeType; for (int change = 0; change < changeNum[curTetrisType]; change++) { SceneOffset local_offset = localOffset[curTetrisType][changeType]; for (int x = 0; x < kSceneWidth; x++) { Grid[] lastValidGrids = null; for (int y = 0; y < kSceneHeight; y++) { var showGrids = GetRunGridsAtPos(x, y, local_offset); if (!CheckAIGridValid(showGrids)) { break; } lastValidGrids = showGrids; } if (lastValidGrids != null) { CheckResult result = new CheckResult(); result.Change = change; result.ChangeType = changeType; result.X = x; int minY = kSceneHeight - 1; bool matchShape = true; Dictionary <int, bool> lineY = new Dictionary <int, bool>(); foreach (var g in lastValidGrids) { //计算高度 if (g.sceneY < minY) { minY = g.sceneY; } //匹配形状 if (g.sceneY + 1 < kSceneHeight) { Grid nextGrid = allGrids[g.sceneX, g.sceneY + 1]; if (!GridsContainsGrid(lastValidGrids, nextGrid) && !nextGrid.show) { matchShape = false; } } //计算消除行数 if (!lineY.ContainsKey(g.sceneY)) { lineY.Add(g.sceneY, true); if (CheckLineYFinished(g.sceneY, lastValidGrids)) { result.EraseLine++; } } } result.Height = kSceneHeight - minY; result.MatchShape = matchShape ? 1 : 2; results.Add(result); } } //遍历所有变形 changeType = (changeType + 1) % changeNum[curTetrisType]; } results.Sort((a, b) => { int minH = Math.Min(a.Height, b.Height); if (minH > 10) { if (a.EraseLine == b.EraseLine) { if (a.Height == b.Height) { return(a.MatchShape - b.MatchShape); } return(a.Height - b.Height); } return(b.EraseLine - a.EraseLine); } if (a.MatchShape == b.MatchShape) { if (a.EraseLine == b.EraseLine) { return(a.Height - b.Height); } return(b.EraseLine - a.EraseLine); } else { return(a.MatchShape - b.MatchShape); } }); var finalResult = results[0]; var offset = tetrisOffset[curTetrisType][finalResult.ChangeType]; int moveX = finalResult.X - offset.X1 - currentRunGridX; foreach (var g in runGrids)//还原显示状态 { g.show = true; } RunAISteps(moveX, finalResult.Change); }
void InitTetrisType() { //O tetrisOffset[3] = new List <SceneOffset>(); tetrisOffset[3].Add(new SceneOffset() { X1 = 1, Y1 = 1, X2 = 1, Y2 = 2, X3 = 2, Y3 = 1, X4 = 2, Y4 = 2 }); changeNum[3] = 1; //I tetrisOffset[0] = new List <SceneOffset>(); tetrisOffset[0].Add(new SceneOffset() { X1 = 1, Y1 = 0, X2 = 1, Y2 = 1, X3 = 1, Y3 = 2, X4 = 1, Y4 = 3 }); tetrisOffset[0].Add(new SceneOffset() { X1 = 0, Y1 = 1, X2 = 1, Y2 = 1, X3 = 2, Y3 = 1, X4 = 3, Y4 = 1 }); changeNum[0] = 2; //S tetrisOffset[4] = new List <SceneOffset>(); tetrisOffset[4].Add(new SceneOffset() { X1 = 1, Y1 = 0, X2 = 1, Y2 = 1, X3 = 2, Y3 = 1, X4 = 2, Y4 = 2 }); tetrisOffset[4].Add(new SceneOffset() { X1 = 2, Y1 = 1, X2 = 3, Y2 = 1, X3 = 1, Y3 = 2, X4 = 2, Y4 = 2 }); changeNum[4] = 2; //Z tetrisOffset[6] = new List <SceneOffset>(); tetrisOffset[6].Add(new SceneOffset() { X1 = 1, Y1 = 1, X2 = 2, Y2 = 1, X3 = 2, Y3 = 2, X4 = 3, Y4 = 2 }); tetrisOffset[6].Add(new SceneOffset() { X1 = 2, Y1 = 0, X2 = 2, Y2 = 1, X3 = 1, Y3 = 1, X4 = 1, Y4 = 2 }); changeNum[6] = 2; //L tetrisOffset[2] = new List <SceneOffset>(); tetrisOffset[2].Add(new SceneOffset() { X1 = 1, Y1 = 0, X2 = 1, Y2 = 1, X3 = 1, Y3 = 2, X4 = 2, Y4 = 2 }); tetrisOffset[2].Add(new SceneOffset() { X1 = 1, Y1 = 1, X2 = 2, Y2 = 1, X3 = 3, Y3 = 1, X4 = 1, Y4 = 2 }); tetrisOffset[2].Add(new SceneOffset() { X1 = 1, Y1 = 0, X2 = 2, Y2 = 0, X3 = 2, Y3 = 1, X4 = 2, Y4 = 2 }); tetrisOffset[2].Add(new SceneOffset() { X1 = 3, Y1 = 1, X2 = 3, Y2 = 2, X3 = 2, Y3 = 2, X4 = 1, Y4 = 2 }); changeNum[2] = 4; //J tetrisOffset[1] = new List <SceneOffset>(); tetrisOffset[1].Add(new SceneOffset() { X1 = 2, Y1 = 0, X2 = 2, Y2 = 1, X3 = 2, Y3 = 2, X4 = 1, Y4 = 2 }); tetrisOffset[1].Add(new SceneOffset() { X1 = 1, Y1 = 1, X2 = 1, Y2 = 2, X3 = 2, Y3 = 2, X4 = 3, Y4 = 2 }); tetrisOffset[1].Add(new SceneOffset() { X1 = 1, Y1 = 0, X2 = 2, Y2 = 0, X3 = 1, Y3 = 1, X4 = 1, Y4 = 2 }); tetrisOffset[1].Add(new SceneOffset() { X1 = 1, Y1 = 1, X2 = 2, Y2 = 1, X3 = 3, Y3 = 1, X4 = 3, Y4 = 2 }); changeNum[1] = 4; //T tetrisOffset[5] = new List <SceneOffset>(); tetrisOffset[5].Add(new SceneOffset() { X1 = 1, Y1 = 1, X2 = 2, Y2 = 1, X3 = 3, Y3 = 1, X4 = 2, Y4 = 2 }); tetrisOffset[5].Add(new SceneOffset() { X1 = 2, Y1 = 0, X2 = 1, Y2 = 1, X3 = 2, Y3 = 1, X4 = 2, Y4 = 2 }); tetrisOffset[5].Add(new SceneOffset() { X1 = 2, Y1 = 1, X2 = 1, Y2 = 2, X3 = 2, Y3 = 2, X4 = 3, Y4 = 2 }); tetrisOffset[5].Add(new SceneOffset() { X1 = 1, Y1 = 0, X2 = 1, Y2 = 1, X3 = 1, Y3 = 2, X4 = 2, Y4 = 1 }); changeNum[5] = 4; for (int i = 0; i < tetrisOffset.Length; i++) { localOffset[i] = new List <SceneOffset>(); for (int j = 0; j < tetrisOffset[i].Count; j++) { SceneOffset offset = tetrisOffset[i][j]; localOffset[i].Add(new SceneOffset() { X1 = 0, Y1 = 0, X2 = offset.X2 - offset.X1, Y2 = offset.Y2 - offset.Y1, X3 = offset.X3 - offset.X1, Y3 = offset.Y3 - offset.Y1, X4 = offset.X4 - offset.X1, Y4 = offset.Y4 - offset.Y1 }); } } }