Самый быстрый способ определения условия выигрыша - отслеживать все строки, столбцы, диагональные и антидиагональные оценки.
Допустим, у вас есть сетка 3х3. Создайте массив партитур размером 2 * 3 + 2, который будет содержать баллы следующим образом [row1, row2, row3, col1, col2, col3, diag1, diag2] Конечно, не забудьте инициализировать его с 0.
Далее после каждого хода вы добавляете +1 для игрока 1 или вычитаете -1 для игрока 2 следующим образом.
оценка [строка] + = точка; // где точка равна +1 или -1
оценка [gridSize + col] + = точка;
if (row == col) Score [2 * gridSize] + = point;
if (gridSize - 1 - col == row) Score [2 * gridSize + 1] + = point;
Затем все, что вам нужно сделать, это перебрать массив результатов один раз и обнаружить +3 или -3 (GRID_SIZE или -GRID_SIZE).
Я знаю, что код говорит больше, чем слова, так что вот прототип на PHP. Это довольно просто, поэтому я не думаю, что у вас возникнут проблемы с переводом на другой язык.
<?php
class TicTacToe {
const PLAYER1 = 'X';
const PLAYER1_POINT = 1;
const PLAYER2 = 'O';
const PLAYER2_POINT = -1; // must be the opposite of PLAYER1_POINT
const BLANK = '';
/**
* Level size.
*/
private $gridSize;
/**
* Level data.
* Two dimensional array of size GRID_SIZE x GRID_SIZE.
* Each player move is stored as either 'X' or 'O'
*/
private $grid;
/**
* Score array that tracks score for rows, cols and diagonals.
* e.g. for 3x3 grid [row1, row2, row3, col1, col2, col3, diag1, diag2]
*/
private $score;
/**
* Avaialable moves count for current game.
*/
private $movesLeft = 0;
/**
* Winner of the game.
*/
private $winner = null;
public function __construct($size = 3) {
$this->gridSize = $size;
$this->grid = array();
for ($i = 0; $i < $this->gridSize; ++$i) {
$this->grid[$i] = array_fill(0, $this->gridSize, self::BLANK);
}
$this->score = array_fill(0, 2*$this->gridSize + 2, 0);
$this->movesLeft = $this->gridSize * $this->gridSize;
$this->winner = null;
}
public function getWinner() {
return $this->winner;
}
public function displayGrid() {
$this->display("--------\n");
for ($row = 0; $row < $this->gridSize; ++$row) {
for ($col = 0; $col < $this->gridSize; ++$col) {
if (self::BLANK == $this->grid[$row][$col]) $this->display(' ');
else $this->display($this->grid[$row][$col].' ');
}
$this->display("\n");
}
$this->display("--------\n");
}
public function play(MoveInput $input) {
$this->display("NEW GAME\n");
$nextPlayer = self::PLAYER1;
$done = false;
while(!$done) {
$move = $input->getNextMove($nextPlayer);
if (NULL == $move) {
$this->display("ERROR! NO MORE MOVES\n");
break;
}
$error = false;
$this->makeMove($move['player'], $move['row'], $move['col'], $error);
if ($error) {
$this->display("INVALID MOVE! Please try again.\n");
continue;
}
$nextPlayer = ($nextPlayer == self::PLAYER1) ? self::PLAYER2 : self::PLAYER1;
$this->displayGrid();
$done = $this->checkScore();
}
}
private function makeMove($player, $row, $col, &$error) {
$error = false;
if (!$this->isValidMove($row, $col) || self::BLANK != $this->grid[$row][$col]) {
$error = true;
return;
}
$this->grid[$row][$col] = $player;
--$this->movesLeft;
$point = 0;
if (self::PLAYER1 == $player) $point = self::PLAYER1_POINT;
if (self::PLAYER2 == $player) $point = self::PLAYER2_POINT;
$this->score[$row] += $point;
$this->score[$this->gridSize + $col] += $point;
if ($row == $col) $this->score[2*$this->gridSize] += $point;
if ($this->gridSize - 1 - $col == $row) $this->score[2*$this->gridSize + 1] += $point;
}
private function checkScore() {
if (0 == $this->movesLeft) {
$this->display("game is a DRAW\n");
return true;
}
for ($i = 0; $i < count($this->score); ++$i) {
if ($this->player1TargetScore() == $this->score[$i]) {
$this->display("player 1 WIN\n");
$this->winner = self::PLAYER1;
return true;
}
if ($this->player2TargetScore() == $this->score[$i]) {
$this->display("player 2 WIN\n");
$this->winner = self::PLAYER2;
return true;
}
}
return false;
}
private function isValidMove($row, $col) {
return (0 <= $row && $row < $this->gridSize) &&
(0 <= $col && $col < $this->gridSize);
}
private function player1TargetScore() {
return $this->gridSize * self::PLAYER1_POINT;
}
private function player2TargetScore() {
return $this->gridSize * self::PLAYER2_POINT;
}
private function display($string) {
echo $string;
}
}
interface MoveInput {
public function getNextMove($player);
}
class QueuedMoveInput implements MoveInput {
private $moves;
public function __construct($movesArray) {
$this->moves = $movesArray;
}
public function getNextMove($player) {
return array_shift($this->moves);
}
}
class InteractiveMoveInput implements MoveInput {
public function getNextMove($player) {
while(true) {
echo "Please enter next move for player $player: [row,col] ";
$line = trim(fgets(STDIN));
list($row, $col) = sscanf($line, "%D,%D");
if (is_numeric($row) && is_numeric($col)) {
return array('player' => $player, 'row' => $row, 'col' => $col);
}
}
}
}
// helpers
function p1($row, $col) {
return array('player' => TicTacToe::PLAYER1, 'row' => $row, 'col' => $col);
}
function p2($row, $col) {
return array('player' => TicTacToe::PLAYER2, 'row' => $row, 'col' => $col);
}
// TESTING!!!!! ;]
// GAME 1 - testing diagonal (0,0) -> (2,2) win condition
$game = new TicTacToe();
$moves = new QueuedMoveInput(array(p1(1,1), p2(0,1), p1(2,0), p2(0,2), p1(0,0), p2(1,0), p1(2,2), p2(2,1)));
$game->play($moves);
assert($game->getWinner() == TicTacToe::PLAYER1);
// GAME 2 - using invalid move, testing straight line (0,0) -> (0,2) win condition
$game = new TicTacToe();
$moves = new QueuedMoveInput(array(p1(1,1), p2(1,1), p2(2,0), p1(2,1), p2(0,1), p1(2,2), p2(0,0), p1(1,0), p2(0,2)));
$game->play($moves);
assert($game->getWinner() == TicTacToe::PLAYER2);
// GAME 3 - testing draw condition
$game = new TicTacToe();
$moves = new QueuedMoveInput(array(p1(1,1), p2(2, 2), p1(1,2), p2(1,0), p1(2,0), p2(0,2), p1(0,1), p2(2,1), p1(0,0)));
$game->play($moves);
assert($game->getWinner() == NULL);
// GAME 4 - testing diagonal (2,0) -> (0,2) win condition
$game = new TicTacToe();
$moves = new QueuedMoveInput(array(p1(2,0), p2(1, 2), p1(0,2), p2(2,2), p1(0,1), p2(0,0), p1(1,1)));
$game->play($moves);
assert($game->getWinner() == TicTacToe::PLAYER1);
// GAME 5 - testing straight line (0,0) -> (2,0) win condition
$game = new TicTacToe();
$moves = new QueuedMoveInput(array(p2(1,1), p1(0,0), p2(0,2), p1(2,0), p2(2,1), p1(1,0)));
$game->play($moves);
assert($game->getWinner() == TicTacToe::PLAYER1);
// GAME 6 - 5x5 grid, testing diagonal (0,0) -> (4,4) win condition
$game = new TicTacToe(5);
$moves = new QueuedMoveInput(array(p1(1,1), p2(0,1), p1(2,0), p2(0,2), p1(0,0), p2(1,0), p1(2,2), p2(4,2), p1(3,3), p2(4,3), p1(4,4)));
$game->play($moves);
assert($game->getWinner() == TicTacToe::PLAYER1);
// GAME 7 - Interactive game.
$game = new TicTacToe();
$game->play(new InteractiveMoveInput());
Надеюсь, это поможет;]