Модераторы: Partizan, gambit

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Абстракция игрока в крестиках-ноликах 
:(
    Опции темы
YankovskyAndrey
Дата 4.3.2011, 09:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 23.10.2008
Где: СПБ

Репутация: нет
Всего: нет



Я пишу крестики-нолики. хочу создать единый метод для проведения игры внезависимости от типа игроков(человек/компьютер)
то есть должны работать человек-человек, компьютер-компьютер, человек-компьютер.
Пробовал подходить с разных сторон, но в цельную картинку сложить не удаётся.
Туплю

Спасибо.
PM MAIL   Вверх
Экскалупатор
Дата 4.3.2011, 16:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

Репутация: 11
Всего: 24



Цитата(YankovskyAndrey @  4.3.2011,  08:48 Найти цитируемый пост)
хочу создать единый метод для проведения игры внезависимости от типа игроков

можно по подробнее? что имеется в виду? может быть подойдет фабрика классов(абстрактная фабрика)?
PM MAIL ICQ   Вверх
YankovskyAndrey
Дата 4.3.2011, 17:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 23.10.2008
Где: СПБ

Репутация: нет
Всего: нет



у меня есть несколько проблем. примерно картинка такая:
Код

public class Game
{
   public Game(Field field, Player firstPlayer, Player secondPlayer);
   public Field Field;
   public Player FirstPlayer;
   public Player SecondPlayer;
}
public class Field
{
   //реализация не важна
}
abstract Player
{
   public Game Game;
   public abstract MakeMove();
}
public HumanPlayer : Player
{
   //как я здесь переопределю MakeMove()? Пользователь нажимает на клетку и делает таким образом ход.
}
abstract AIPlayer : Player
{
   public abstract EstimatePosition(Field field); // Берём из Game
}
EasyAIPlayer : AIPlayer
{
   public override EstimatePosition(Field field);
   public override MakeMove(); // как связать с EstimatePosition
}
HardAIPlayer : AIPlayer
{
   public override EstimatePosition(Field field);
   public override MakeMove();
}

в коде могут быть ошибки. но проблема, я думаю, ясна

Как свести процесс нажатия на клетку пользователем и процесс высчитывания позиции компьютером под общий интерфейс.
чтобы игра могла проходить в контексте класса Player?
или это всё зря и я дурной?

хочу пробовать разные алгоритмы для компьютера и чтоб они могли соревноваться между собой
+хочу сделать сетевой режим для живых игроков

Добавлено @ 17:26
фабрика не подойдёт насколько я понимаю.
её можно было бы применить, если бы имелось два семейства алгоритмов выбора ходов
и надо было бы провести турнир.
я ведь не могу предложить несколько реализаций человека. не бог же.
я правильно понял принцип?

Это сообщение отредактировал(а) YankovskyAndrey - 4.3.2011, 17:34
PM MAIL   Вверх
YankovskyAndrey
Дата 4.3.2011, 17:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 23.10.2008
Где: СПБ

Репутация: нет
Всего: нет



я ещё игрушку написал, остановка на том же самом месте.
PM MAIL   Вверх
Экскалупатор
Дата 4.3.2011, 20:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

Репутация: 11
Всего: 24



Цитата(YankovskyAndrey @  4.3.2011,  16:18 Найти цитируемый пост)
я правильно понял принцип?

не совсем, фабрика дает возможность использовать разные алгоритмы, т.е. к примеру у тебя есть интерфейс в котором есть метод "сделать ход", при этом программе все равно кто делает ход, компьютер или игрок, вызывающему классу нужен результат, а фабрика инициализирует класс который будет делать то что тебе нужно, очевидно что игрок-компьютер и игрок-человек будут делать одни и те же действия(совершать ходы), а значит у тебя должно быть два класса(или больше) но один должен "работать с человеком"(ждать нажатия и пр.) , а второй запускать работу разработанного тобой ИИ, но для вызывающего класса никакой разницы, в этом и есть суть.

Добавлено через 11 минут и 53 секунды
Цитата(YankovskyAndrey @  4.3.2011,  16:18 Найти цитируемый пост)
//как я здесь переопределю MakeMove()? Пользователь нажимает на клетку и делает таким образом ход.

все поля уже содержаться в твоей программе(ведь ты же их как то рисуешь) сделай что бы твой класс мог "нажимать" на клетки. но вообще я думаю тут надо разделить, надо что бы класс который выполняет обсчет игровой ситуации получал данные от "игроков" и потом рисовал результаты на форме(ну а игроки в свою очередь должны либо генерить ход(как комп), либо ждать информации от игрока), я думаю у тебя сейчас сделано наоборот, т.е. человек нажимает и это сразу видно и потом все передается на обработку.
PM MAIL ICQ   Вверх
YankovskyAndrey
Дата 5.3.2011, 08:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 23.10.2008
Где: СПБ

Репутация: нет
Всего: нет



всё надоело, написал консольную модель игры.
я не знаю почему не мог так раньше сделать. просто бред. два дня сидел.
видимо всё из-за работы с интерфейсом пользовательским
затуманивает разум

Код

class Program
    {
        static void Main(string[] args)
        {
            var game = new Game(new HumanPlayer(), new HumanPlayer());
            game.Start();
            Console.Read();
        }
    }

    public abstract class AbstractPlayer
    {
        public abstract string WriteLetter();
    }

    public class AIPlayer : AbstractPlayer
    {
        public override string WriteLetter()
        {
            return "Q";
        }
    }

    public class HumanPlayer : AbstractPlayer
    {
        public override string WriteLetter()
        {
            var keyInfo = Console.ReadKey(true);
            return keyInfo.KeyChar.ToString();
        }
    }
    
    public class Game
    {
        public Game(AbstractPlayer firstPlayer, AbstractPlayer secondPlayer)
        {
            _firstPlayer = firstPlayer;
            _secondPlayer = secondPlayer;
        }

        public void Start()
        {
            var gameEnded = false;
            var str = "";
            do
            {
                if (_isFirstPlayerTurn)
                    str += _firstPlayer.WriteLetter();
                else
                    str += _secondPlayer.WriteLetter();
                Console.WriteLine(str);
                if (str.Count() > 10)
                    gameEnded = true;
                _isFirstPlayerTurn = !_isFirstPlayerTurn;
            }
            while (!gameEnded);
            Console.WriteLine("-------------END-------------");
        }

        private AbstractPlayer _firstPlayer;
        private AbstractPlayer _secondPlayer;
        private bool _isFirstPlayerTurn;

    }


видимо проблема в этом "я думаю у тебя сейчас сделано наоборот, т.е. человек нажимает и это сразу видно и потом все передается на обработку"
спасибо и извините за глупые вопросы.

Это сообщение отредактировал(а) YankovskyAndrey - 5.3.2011, 08:45
PM MAIL   Вверх
gambit
Дата 5.3.2011, 11:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***
Награды: 1



Профиль
Группа: Комодератор
Сообщений: 1359
Регистрация: 25.6.2006
Где: я?

Репутация: 5
Всего: 40



Посмотри еще паттерн стртегия, я его применял когда писал игру танчики, у меня был игрок и несколько логик для разных танчиков, и все все имели одинаковый доступ к полю
PM MAIL ICQ Skype   Вверх
YankovskyAndrey
Дата 5.3.2011, 12:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 23.10.2008
Где: СПБ

Репутация: нет
Всего: нет



Круто!)

у меня всё ещё есть ступор в плане обобщения компьютера и человека.
то есть как написать с десяток стратегий для танчиков - понятно.
а как запихнуть сюда человека для меня неочевидно. Можно ваши танчики посмотреть?
и я так понимаю в стратегии важно не привязывание разных стратегий(есть другие способы), а возможность их менять налету.

Код

abstract class AbstractStrategy{abstract void DoSomething();}
class AIStrategy1 : AbstractStrategy{override void DoSomething();}
class AIStrategy2 : AbstractStrategy{override void DoSomething();}
class HumanStrategy: AbstractStrategy{override void DoSomething();} //всё равно непонятно
class Tank
{
   AbstractStrategy Strategy;
   Tank(Strategy strategy){ Strategy = strategy;}
   void DoTankAction(){ Strategy.DoSomething();}
}
Main()
{
   var tank = new Tank(new AIStrategy1());
   tank.DoTankAction();
   tank.ChangeStrategy(new HumanStrategy()); //WTF?!)
   tank.DoTankAction();
}


я так понимаю что паттерн хорош для смены стратегий танчиков во время игры. Ориентировка на защиту, на нападение. как-то так.
человек опять ни к месту)

Это сообщение отредактировал(а) YankovskyAndrey - 5.3.2011, 12:16
PM MAIL   Вверх
Экскалупатор
Дата 5.3.2011, 12:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

Репутация: 11
Всего: 24



YankovskyAndrey, а чем не подходит(что не понятно) в том что я написал? отдели логику игры от "игроков"(неважно компьютера или человека), логика должна ждать сообщений от "игроков"(ей должно быть все равно ходит человек или машина). при этом класс реализующий работу машины и класс реализующий работу живого игрока должны наследовать одному интерфейсу, через этот интерфейс и будет происходить передача сообщений.
PM MAIL ICQ   Вверх
YankovskyAndrey
Дата 5.3.2011, 12:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 23.10.2008
Где: СПБ

Репутация: нет
Всего: нет



я сейчас так и делаю)
я так с самого начала пытаюсь делать))
PM MAIL   Вверх
Экскалупатор
Дата 5.3.2011, 13:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

Репутация: 11
Всего: 24



YankovskyAndrey, так расскажи что конкретно не выходит. у тебя должны получиться несколько "независимых" друг от друга слоев. 
1. логика игры
2. логика игроков(разных)
3. собственно поле игры
4. интерфейс на котором все это будет отображаться
*это на вскидку в реале может и отличаться

логика игры не должна вообще знать кто играет, она просто опрашивает игроков и получает от них информацию о ходах. потом изменяет поле(не интерфейс, а то где хранятся данные по игре(может матрица какая или еще что)), а потом рисует эти изменения на экране что бы пользователь видел. в случае класса "ИИ" все просто, получил данные от класса, изменил на экране... PROFIT!!!. с игроком сложнее потому что игрок пользуется тем же интерфейсом для ввода данных что и логика для вывода, но с другой стороны, если форма ждет нажатия значит должны отработать события которые изменяют класс игрока и сообщают логике что событие таки произошло, в остальных случаях логика просто изменяет данные на форме.

Добавлено через 1 минуту и 19 секунд
при этом, как мне кажется, лучше сделать что бы форма отображала данные именно из слоя 3(поле игры - данные), а не хранила данные о ходах в себе.
PM MAIL ICQ   Вверх
YankovskyAndrey
Дата 5.3.2011, 13:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 23.10.2008
Где: СПБ

Репутация: нет
Всего: нет



мне кажется я уже близок
я делаю silverlight + MVVM 
проблема была ещё и в том, что я логику игры(читай модель) загонял в ViewModel.
там и корень зол видимо.
мне ещё пара часов нужна и вроде заработает
PM MAIL   Вверх
Экскалупатор
Дата 5.3.2011, 13:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

Репутация: 11
Всего: 24



тут главное не спутать логику программы и логику собственно игры, я в своем описании имел ввиду именно логику программы
PM MAIL ICQ   Вверх
YankovskyAndrey
Дата 5.3.2011, 15:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 23.10.2008
Где: СПБ

Репутация: нет
Всего: нет



хорошо, я не понимаю как ждать пользовательского ввода)

нашёл "The problem is you are trying to make a procedural system in an event driven environment. If you switch to an event driven system, then this will no longer be a problem."
вот тут такой же как я 
http://www.gamedev.net/topic/488236-waitin...-c-gui-program/
))

мне стыдно, но я не понимаю

у меня сейчас есть в классе Player метод void MakeMove()
видимо надо двигать к событию OnMoveMaked
м?)

Добавлено @ 15:36
вот мой базовый класс игры
Код

    public abstract class Game
    {
        internal Game()
        {
            Start();
        }

        public event EventHandler<EventArgs> OnGameEnded;

        private void Start()
        {
            var gameState = GameState.NotFinished;
            do
            {
                MakeTurn();
                if (AreWinConditionsPerformed())
                    gameState = GameState.WinnerExist;
                else if (IsDrawAble)
                    if (AreDrawConditionsPerformed())
                        gameState = GameState.Draw;
                else
                    ChangePlayerTurn();
            } while (gameState == GameState.NotFinished);

            if (OnGameEnded != null)
                OnGameEnded(this, new GameEndedEventArgs(gameState));
        }

        protected abstract void MakeTurn();

        protected abstract void ChangePlayerTurn();

        protected abstract bool AreWinConditionsPerformed();

        protected abstract bool AreDrawConditionsPerformed();

        protected bool IsDrawAble = false;        

    }


Добавлено @ 15:40
игра для двух игроков
Код

    public abstract class TwoPlayerGame : Game
    {
        public TwoPlayerGame(Player firstPlayer, Player secondPlayer, bool isFirstPlayerTurn) : base()
        {
            FirstPlayer = firstPlayer;
            FirstPlayer.GamesCount++;
            SecondPlayer = secondPlayer;
            SecondPlayer.GamesCount++;
            IsFirstPlayerTurn = isFirstPlayerTurn;
        }

        public Player FirstPlayer { get; private set; }
        public Player SecondPlayer { get; private set; }
        public bool IsFirstPlayerTurn { get; private set; }

        protected sealed override void MakeTurn()
        {
            if (IsFirstPlayerTurn)
                FirstPlayer.MakeTurn();
            else
                SecondPlayer.MakeTurn();
        }

        protected sealed override void ChangePlayerTurn()
        {
            IsFirstPlayerTurn = !IsFirstPlayerTurn;
        }

    }

игрок
Код

    public abstract class Player
    {
        public abstract void MakeTurn();
    }


Это сообщение отредактировал(а) YankovskyAndrey - 5.3.2011, 15:41
PM MAIL   Вверх
YankovskyAndrey
Дата 5.3.2011, 16:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 23.10.2008
Где: СПБ

Репутация: нет
Всего: нет



всю малину портит ожидание пользовательских действий
надо видимо поменять в Player MakeTurn на что-то)

Добавлено через 8 минут и 59 секунд
event driven environment
event driven environment
event driven environment
event driven environment
event driven environment
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.1145 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.