added Brain for second Player

This commit is contained in:
Shuozhe 2021-07-25 01:21:22 +02:00
parent 0edb73d8a3
commit 1a110b213a
8 changed files with 109 additions and 43 deletions

View File

@ -35,10 +35,10 @@ namespace ProjectGrid.Controllers
[HttpGet] [HttpGet]
[Route("api/ttt/Restart")] [Route("api/ttt/Restart")]
public void RestartGame() public void RestartGame(TicTacToc.Mode mode = TicTacToc.Mode.CROSS_PLAYER)
{ {
_logger.LogTrace("RestartGame called."); _logger.LogTrace("RestartGame called.");
_manager.Restart(); _manager.Restart(mode);
} }
[HttpPost] [HttpPost]

View File

@ -16,7 +16,7 @@ namespace ProjectGrid.Data
} }
public Models.TicTacTocBrain GetBoard() public TicTacTocBoard GetBoard()
{ {
throw new System.NotImplementedException(); throw new System.NotImplementedException();
} }

View File

@ -4,7 +4,7 @@ namespace ProjectGrid.Data
{ {
public interface ITicTacToctRepository public interface ITicTacToctRepository
{ {
TicTacTocBrain GetBoard(); TicTacTocBoard GetBoard();
bool AddPiece(TicTacTocRequest user); bool AddPiece(TicTacTocRequest user);
} }

View File

@ -2,6 +2,7 @@ using ProjectGrid.Models;
using ProjectGrid.TicTacToc; using ProjectGrid.TicTacToc;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
namespace ProjectGrid.AI namespace ProjectGrid.AI
@ -13,10 +14,10 @@ namespace ProjectGrid.AI
private List<int> _prio; private List<int> _prio;
public TicTacTocBrain(TicTacTocBoard board, Player player) public TicTacTocBrain(TicTacTocBoard board, int player)
{ {
_board = board; _board = board;
_player = (int)player; _player = player;
var rand = new Random(); var rand = new Random();
_prio = (new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8 }).OrderBy(i => rand.Next()).ToList(); _prio = (new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8 }).OrderBy(i => rand.Next()).ToList();
@ -24,45 +25,68 @@ namespace ProjectGrid.AI
public int Turn() public int Turn()
{ {
if (_board.Field[5] == (int)Player.EMPTY) if (_board.Field[4] == (int)Player.EMPTY)
{ {
//_board.SetFieldValue(_player, 5); //_board.SetFieldValue(_player, 5);
return 5; return 4;
} }
int blocking = -1;
for (int x = 0; x < TicTacTocBoard._winning.GetLength(0); x++) for (int x = 0; x < TicTacTocBoard._winning.GetLength(0); x++)
{ {
var _1 = TicTacTocBoard._winning[x, 0]; var _1 = _board.Field[TicTacTocBoard._winning[x, 0]];
var _2 = TicTacTocBoard._winning[x, 1]; var _2 = _board.Field[TicTacTocBoard._winning[x, 1]];
var _3 = TicTacTocBoard._winning[x, 2]; var _3 = _board.Field[TicTacTocBoard._winning[x, 2]];
int result = Match2(_1, _2, _3); // any field set?
if (result > 0) if (_1 + _2 + _3 == 0)
{ continue;
//_board.SetFieldValue(_player, );
return TicTacTocBoard._winning[x, result]; var result = MatchWinning(_1, _2, _3);
} if (result.Item1 >= 0)
return TicTacTocBoard._winning[x, result.Item1];
if (result.Item2 >= 0)
blocking = TicTacTocBoard._winning[x, result.Item2];
} }
if (blocking >= 0)
return blocking;
foreach (var i in _prio) foreach (var i in _prio)
if (_board.Field[i] == 0) if (_board.Field[i] == 0)
return i; return i;
Debug.Fail("Brain found no valid move!");
return -1; return -1;
} }
private int Match2(int _1, int _2, int _3) private (int win, int block) MatchWinning(int _1, int _2, int _3)
{ {
if (_1 == _player && _2 == _player && _3 == 0) (int win, int block) result = (-1, -1);
return 3; if (_1 == _2 && _1 != 0 && _3 == 0)
{
if (_1 == _player)
result.win = 2;
else
result.block = 2;
}
else if (_1 == _3 && _1 != 0 && _2 == 0)
{
if (_1 == _player)
result.win = 1;
else
result.block = 1;
}
else if (_2 == _3 && _2 != 0 && _1 == 0)
{
if (_1 == _player)
result.win = 0;
else
result.block = 0;
}
if (_1 == _player && _2 == 0 && _3 == _player) return result;
return 2;
if (_1 == 0 && _2 == _player && _3 == _player)
return 1;
return 0;
} }
} }
} }

View File

@ -15,6 +15,8 @@ namespace ProjectGrid.Models
private int _lastSetValue; private int _lastSetValue;
public int LastSetValue => _lastSetValue; public int LastSetValue => _lastSetValue;
public bool Full => !!!_field.Contains(0);
private int PosToIdx(int x, int y) private int PosToIdx(int x, int y)
{ {
Debug.Assert(x >= 0 && x <= 3 Debug.Assert(x >= 0 && x <= 3

View File

@ -1,3 +1,4 @@
using ProjectGrid.AI;
using ProjectGrid.Models; using ProjectGrid.Models;
using ProjectGrid.TicTacToc; using ProjectGrid.TicTacToc;
using System; using System;
@ -22,6 +23,9 @@ namespace ProjectGrid
} }
private State _state; private State _state;
private Mode _mode;
private TicTacTocBrain _brain;
//private ITicTacToctRepository _repo; //private ITicTacToctRepository _repo;
@ -36,7 +40,7 @@ namespace ProjectGrid
{ {
//_repo = repo; //_repo = repo;
_currentPlayer = 1; _currentPlayer = 1;
Restart(Mode.TWO_PLAYER); Restart(Mode.CROSS_PLAYER);
} }
public TicTacTocResponse NextMove(TicTacTocRequest move) public TicTacTocResponse NextMove(TicTacTocRequest move)
@ -45,8 +49,8 @@ namespace ProjectGrid
if (_state != State.GAME_OVER) if (_state != State.GAME_OVER)
{ {
_board.SetFieldValue(_currentPlayer, move.Field); if (_board.SetFieldValue(_currentPlayer, move.Field))
{
response.Winning = _board.ValueWon(_currentPlayer); response.Winning = _board.ValueWon(_currentPlayer);
if (_currentPlayer > 0 && response.Winning != null) if (_currentPlayer > 0 && response.Winning != null)
{ {
@ -54,10 +58,41 @@ namespace ProjectGrid
_state = State.GAME_OVER; _state = State.GAME_OVER;
_playerScore[_currentPlayer]++; _playerScore[_currentPlayer]++;
} }
else if (null != _brain)
{
if (_board.Full)
{
_playerScore[0]++;
_state = State.GAME_OVER;
response.PlayerWon = 0;
return response;
}
int ai = 3 - _currentPlayer;
var turn = _brain.Turn();
Console.WriteLine($"Brain made move {turn} for player {ai}");
_board.SetFieldValue(ai, turn);
response.Winning = _board.ValueWon(ai);
if (response.Winning != null)
{
response.PlayerWon = ai;
_playerScore[ai]++;
_state = State.GAME_OVER;
}
}
else
{
// switch between 1 and 2 // switch between 1 and 2
_currentPlayer = 3 - _currentPlayer; _currentPlayer = 3 - _currentPlayer;
} }
}
if (_board.Full)
{
_playerScore[0]++;
_state = State.GAME_OVER;
}
}
response.Board = _board.Field; response.Board = _board.Field;
response.PlayerScore = new List<int>(_playerScore); response.PlayerScore = new List<int>(_playerScore);
@ -67,9 +102,14 @@ namespace ProjectGrid
public void Restart(Mode mode) public void Restart(Mode mode)
{ {
_currentPlayer = new Random().Next(1, 2); _mode = mode;
_currentPlayer = 1;
_board = new TicTacTocBoard(); _board = new TicTacTocBoard();
_state = State.PLAYING; _state = State.PLAYING;
_brain = null;
if (Mode.TWO_PLAYER != mode)
_brain = new TicTacTocBrain(_board, 3 - (int)mode);
} }

View File

@ -4,14 +4,14 @@ namespace ProjectGrid.TicTacToc
{ {
public enum Mode public enum Mode
{ {
TWO_PLAYER, TWO_PLAYER = 0,
CROSS_PLAYER, CROSS_PLAYER = 1,
CIRCLE_PLAYER, CIRCLE_PLAYER = 2,
} }
public enum Player public enum Player
{ {
EMPTY = 0; EMPTY = 0,
CROSS = 1, CROSS = 1,
CIRCLE = 2, CIRCLE = 2,
} }

View File

@ -47,7 +47,7 @@ namespace ProjectGrid
// Manager // Manager
services.AddSingleton<TicTacTocManager>(new TicTacTocManager()); services.AddSingleton<TicTacTocManager>(new TicTacTocManager());
services.AddScoped<TicTacTocTypes, TicTacTocManager>(); services.AddScoped<ITicTacTocManager, TicTacTocManager>();
// DataAccess // DataAccess
services.AddScoped<ITicTacToctRepository, DataAccessContext>(); services.AddScoped<ITicTacToctRepository, DataAccessContext>();