public void move(FieldState state, ref Move move, Rules rules) { System.Threading.Thread.Sleep(150); if (optimalMove.Count == 0) // this holds only on the first move of the iteration { int nonDiagonalCounter = 0; // then find the optimal move int width = state.Field.GetLength(0); int[] dx, dy; if (rules.AllowDiagonal == true) { dx = new int[] { 1, 0, -1, 0, 1, 1, -1, -1 }; dy = new int[] { 0, 1, 0, -1, 1, -1, 1, -1 }; } else { dx = new int[] { 1, 0, -1, 0 }; dy = new int[] { 0, 1, 0, -1 }; } for (int i = 0; i < width; ++i) { for (int j = 0; j < width; ++j) { Stack <FieldTreeNode> st = new Stack <FieldTreeNode>(); if (state.Field[i, j] == '\0') { // if there is space in the current cell for (int k = 0; k < 32; ++k) { // add every possible letter if (prefixTree[0, k] != -1) { st.Push(new FieldTreeNode(true, true, null, j, i, k, prefixTree[0, k])); } } } else { // there is only one possible start node // if there are words that start with this letter if (prefixTree[0, state.Field[i, j] - 'А'] != -1) { st.Push(new FieldTreeNode(false, false, null, j, i, state.Field[i, j] - 'А', prefixTree[0, state.Field[i, j] - 'А'])); } } while (st.Count > 0) { FieldTreeNode cur = st.Pop(); int cx = cur.x, cy = cur.y; // add all it's neighbours for (int k = 0; k < dx.Length; ++k) { try { if (!rules.AllowIntersections) { if (cur.containsCoords(cx + dx[k], cy + dy[k])) { continue; } } // if the neighbour contains a space and it can be filled with a new letter if (state.Field[cy + dy[k], cx + dx[k]] == '\0' && !cur.newLetterUsed) { for (int l = 0; l < 32; ++l) { if (prefixTree[cur.prefixTreeIndex, l] != -1) { st.Push(new FieldTreeNode(true, true, cur, cx + dx[k], cy + dy[k], l, prefixTree[cur.prefixTreeIndex, l])); } } } // if the neighbour contains a letter and there is a corresponding prefix if (isCapitalRussianLetter(state.Field[cy + dy[k], cx + dx[k]]) && prefixTree[cur.prefixTreeIndex, state.Field[cy + dy[k], cx + dx[k]] - 'А'] != -1) { st.Push(new FieldTreeNode(false, cur.newLetterUsed, cur, cx + dx[k], cy + dy[k], state.Field[cy + dy[k], cx + dx[k]] - 'А', prefixTree[cur.prefixTreeIndex, state.Field[cy + dy[k], cx + dx[k]] - 'А'])); } } catch (IndexOutOfRangeException) { // this is OK, do nothing } catch (Exception ex) { MessageBox.Show(ex.Message); } } // check if cur is a word if (isWord[cur.prefixTreeIndex] && cur.newLetterUsed == true) { if (!cur.containsDiagonal()) { ++nonDiagonalCounter; } // then add a corresponding move to our list of moves FieldTreeNode newLetter = cur.findNewLetter(); Stack <Move> newWord = new Stack <Move>(); Move lol = new Move(); lol.Action = ActionType.EndTurn; newWord.Push((Move)lol.Clone()); string word = ""; while (cur != null) { word = (char)(cur.letter + 'А') + word; lol.Action = ActionType.SelectLetter; lol.X = cur.x; lol.Y = cur.y; newWord.Push((Move)lol.Clone()); cur = cur.parent; } if (word == "ОСА") { int q = 0; } lol.Action = ActionType.EnterLetter; lol.X = newLetter.x; lol.Y = newLetter.y; lol.Letter = (char)(newLetter.letter + 'А'); newWord.Push((Move)lol.Clone()); // we cannot place words from ProhibitedWords, so check this if (!state.ProhibitedWords.Contains(word)) { words.Add(word); possibleMoves.Add(newWord); } } } } } if (possibleMoves.Count == 0) // we have not found any possible word { // in this case we can only pass a turn Move tmp = new Move(); tmp.Action = ActionType.PassTurn; optimalMove.Push(tmp); } else { possibleMoves.Sort((list1, list2) => list1.Count - list2.Count); int optimalIndex = 0; switch (str) { case StrategyStrength.Easy: optimalIndex = 0; break; case StrategyStrength.Medium: optimalIndex = possibleMoves.Count / 2; break; case StrategyStrength.Hard: optimalIndex = possibleMoves.Count - 1; break; } optimalMove = possibleMoves[optimalIndex]; } move = optimalMove.Pop(); } else { move = optimalMove.Pop(); if (optimalMove.Count == 0) { possibleMoves.Clear(); } } return; }
private void processPlayer(Player player, int currentIndex) { timeIsUp = false; bool correctEndTurn = false; Move move = new Move(); //time = new TimeSpan(0, Rules.TimeLimit, 0); time = new TimeSpan(0, Rules.TimeLimit, 0); gamingForm.updateTimer(time); MessageBox.Show("Ходит игрок " + player.Name); gamingForm.updatePlayersScore(Players, currentIndex); do { if (timeIsUp == false) { gamingForm.updateForm(State, Rules); player.Strategy.move(State, ref move, Rules); } else { move.Action = ActionType.PassTurn; } switch (move.Action) { case ActionType.EnterLetter: { int x = move.X, y = move.Y; int width = State.Field.GetLength(0); if (x < 0 || x >= width || y < 0 || y >= width) { // indices out of range break; } move.Letter = Char.ToUpper(move.Letter); if (!isCapitalRussianLetter(move.Letter)) { // incorrect character break; } if (State.NewX != -1 && State.NewY != -1) { // user already entered new letter break; } State.NewX = x; State.NewY = y; State.Field[y, x] = move.Letter; } break; case ActionType.SelectLetter: { int wordLength = State.X.Count; int x = move.X, y = move.Y; bool isCorrect = true; int width = State.Field.GetLength(0); if (x < 0 || x >= width || y < 0 || y >= width) { // indices out of range break; } char nullLetter = '\0'; if (State.Field[y, x] == nullLetter) { //user must select only letters; break; } if (wordLength == 0) { State.X.Add(x); State.Y.Add(y); break; } if (!Rules.AllowIntersections) { for (int i = 0; i < wordLength; i++) { if (State.X[i] == x && State.Y[i] == y) { //new coordinate intersects with the word isCorrect = false; break; } } if (!isCorrect) { break; } } if (Rules.isNeighbours(x, y, State.X[wordLength - 1], State.Y[wordLength - 1])) { State.X.Add(x); State.Y.Add(y); } else { break; } } break; case ActionType.EndTurn: { bool foundLetter = false; string word = ""; //check if the word contains the newly enter letter if (State.NewX == -1 && State.NewY == -1) { MessageBox.Show("Введите букву"); break; } if (State.X.Count == 0 && State.Y.Count == 0) { MessageBox.Show("Выберите слово"); break; } for (int i = 0; i < State.X.Count; i++) { if (State.X[i] == State.NewX && State.Y[i] == State.NewY) { foundLetter = true; break; } } if (!foundLetter) { MessageBox.Show("Слово не содержит поставленную букву"); resetTurn(); break; } for (int i = 0; i < State.X.Count; i++) { int x = State.X[i]; int y = State.Y[i]; word += State.Field[y, x]; } if (!wordBase.Contains(word)) { MessageBox.Show(String.Format("База не содержит слова - {0}", word)); resetTurn(); break; } if (State.ProhibitedWords.Contains(word)) { MessageBox.Show("Cлово " + word + " уже было"); resetTurn(); break; } State.ProhibitedWords.Add(word); player.Score += word.Length; State.NewX = -1; State.NewY = -1; State.X.Clear(); State.Y.Clear(); ListViewItem item = new ListViewItem(word); item.ForeColor = player.PlayerColor; gamingForm.addNewWord(item); consequtiveTurnPasses = 0; correctEndTurn = true; return; } break; case ActionType.Reset: { resetTurn(); } break; case ActionType.PassTurn: { consequtiveTurnPasses++; resetTurn(); return; } break; } }while (!((move.Action == ActionType.EndTurn && correctEndTurn == true) || move.Action == ActionType.PassTurn)); // if the user chose non-existing word, we should ask him for another word instead of exitting // the very last turn will not be shown otherwise gamingForm.updatePlayersScore(Players, currentIndex); }