понедельник, 5 января 2026 г.

Кремлевский какаду



Сей рассказ о событиях времени правления Бориса Николаевича и долго был неопубликован по причине малозначительности в глазах автора. Все совпадения случайны и фамилии и должности изменены.
Некто руководитель кремлевской администрации Патрущенко привез из сердца Африки - Анголы, где милые туземцы уже давно никого не едят, ну разве только ритуально, если позавидуют достоинствам, огромного красочного говорящего попугая из породы, как сказали гуманисты - какаду. Попугай хватал целые фразы на лету, и что особенно интересно, складывал новые речевые обороты из старого словарного запаса и некой логики вывода фраз.
-Туземцы сказали, что не могут содержать такую талантливую птицу и дарят ее нам! Поместим его в грановитой палате - сказал Патрущенко - и накроем тряпкой, он будет молчать и слушать, а как тряпку снимем, будет развлекать публику и сыпать госсекретами!
-Ну понимаешь, устал я от балагана. А если он чего не то сболтнет, антиполитичное?
-Усе продумано, господин гетман-атаман! Мы наняли француза мсье Жан-Жака Де Пьерфона, который будет согласно иструкции накрывать птицу если та уклонится так сказать от проторенного политического русла.
-Ну понимаешь смотрите мне!

На другой день клетку с какаду поставили в грановитой палате и тут по случаю слетелись лидеры СНГ, потом подъехал Обама, потом ближневосточные друзья и француз стал понемного снимать тряпку с попугая, выпускать так сказать в свет.

-Долой либералов и соросят!
-отлично-воскликнул француз и протянул птице семечек.
-Ми-6 правит миром! Долой щупальца трансатлантических элит!
-Молодец!
-Денацификация и депидаризация европы!
-Накрываю тряпкой, глупая птица на три дня, не трогай рейх!
Тряпку сняли, когда приехали азербайджанские и турецкие друзья.
-Долой гегемонию США! - заорала птица. -Долой ЦРУ и контроль наркотрафика!
-Неделю штрафа, не трогай сша, не трогай цру!
-Долой гегемонию доллара! Да здравствует брикс!
-Молодей, на орешков!
-Барон Мюнхаузен как и штандартен фюрер СС, никогда не врал!
-Не трогай рейх! Две недели штрафа!
-Миллионер Онасис, владалец танкеров женился на вдове Кеннеди чтобы манипулировать америкой!
-Не трогай греков, не трогай сша!
-Долой венецианскую черную аристократию, долой лондонский иудейский проект! Долой клуб 300!
-Молодец! Поклюй миндаля!
-Андропов 4 года партизанил в Карелии и был завербован абвером. Штирлица сняли чтобы газ пошел в ФРГ за 20% а остальное кремлю и коррумпированной евро верхушке. Идеолог партии Суслов когда партизанил в Ставропольском крае, по совместительству был унтер штурбанфюрером СС!
-Два месяца штрафа, не трогай рейх глупая птица!
-Дело Ленина погибло! Это что за абстракционизм на карте СССР! Николай 2 правил Англией под именем Георга 5! Сталин по указанию царской охранки взрывал в Баку нефтевышки российских промышленников! Наполеона никогда не было в России, просто Багратион получил взятку и отступал до Москвы! Немцев под Москвой никогда не было! Сталина и Гитлера завалили лживыми донесениями! Суворов возвел Наполеона на трон, сковав в Альпах верные Директории войска на время переворота!
-Давай давай! Француз аж привстал и показал птице два мешка - с сушеной клюквой и очищенным фундуком. - Вперед!
-Петр 1 купил Полтаву у Августа за 2 миллиона золотых ефимков, попилил бабло и не хотел возвращаться в Россию из Голландии пока деньги не кончились! Русско японской войны никогда не было, просто США и япония влезли в долю в транзите Владивосток - Вена!
-Уф! - воскликнул француз - мон бон ами - ничего подобного не слышал. -На восточных сладостей! Силь ву пле! 
В конце концов, птица разошлась и стала болтать о каких то островах рядом с Сейншельскими где клуб 300 и МИ-6 закопали бриллианты, ее сначала на радостях накормили миндалем а потом почему то убрали из Грановитой палаты.
-Ну понимаешь, получил я взбучку за сейншельские острова! Откуда птица узнала, никто ж не говорил. Там центральная база США в Тихом океане.
-Не могу знать, наверно с Африки запомнила! Может, речи записывать а потом как будто птица говорит ?
- Не надо. Француз тоже хорош! А если он запишет что Сорос хранит бумажную наличность на Мальдивах и Маргарет Тетчер была в доле потому и двинула флот? Будет международный скандал!
-Может, подарить ее Обаме!
-Ну понимаешь, а если что про них сболтнет. Обама дескать потомок венецианской черной аристократии. Наслушалась тут понимаешь! Найдите хорошего майора в отставке, из комитета, чтоб надежный был, пусть присмотрит за птицей!


пятница, 31 октября 2025 г.

 Программирование игры в уголки.




Это старая бородатая задача, которую можно решить перебором на глубину 3..5 для одной стороны, т.е. ходы противника не учитываются. Но если отойти от примитивизма, до задача становится интересной, потому как одна сторона должна играть в полную силу а ходы другой учитываться, но не во всех случаях.

Правила игры.




Шашки ставятся в углы, и целью является занять угол противника. Шашки могут ходить на одно поля или прыгать через шашки, свои и противника.

Оценка позиции.

Оценкой может служить просто индекс 0..63 массива для верхних (черных) и инвертированный индекс 63-n для белых. Целевые поля получают премию, свои поля - небольшой штраф, чтобы программа их быстрее оставляла. Центр может получить небольшую премию.
Перед каждым ходом можно инициализировать генератор случайных чисел системным временем и давать для каждой клетки небольшой случайный бонус.

 


///// игра  уголки - основные структры данных и алгоритмы///
#define WHITE 0
#define BLACK 1
#define PAWN 1
#define NOPIECE 0

int pos[64];//фигуры
int color[64];//их цвет
int score[64]={
 0, 0, 0, 4, 5, 6, 7, 8, 
 1, 1, 1,12,13,14,15,16, 
 2, 2, 2,20,21,22,23,24, 
25,26,27,30,31,30,31,32,  
33,34,35,38,39,38,39,40, 
41,42,43,44,45,62,63,64, 
49,50,51,52,53,65,66,67,  
57,58,59,60,61,68,69,70};

int random_score[64];

void InitScore(){
  srand(time(0));
  for(int sq=0;sq<64;sq++)
   random_score[j] = random()%2;
}

int Evaluate(int color, //относительно кого оценка
             int player_color,//цвет игрока
             int ply //глубина поиска
             ){

  int s[2]={0,0}; 

  for(int sq=0;sq<64;sq++)
   if(pos[sq] != NOPIECE)
   {
     if(color[sq]==BLACK)
       s[BLACK] += score[sq] + random_score[sq];
     else  
       s[WHITE] += score[63-sq] + random_score[63-sq];
   }

  if(s[color]>60*9) return INFINITY-ply;//конец игре
  if(c[color^1]>60*9) return -INFINITY+ply;


  //одна из сторон получает большую оценку, чтобы
  //не 'зажимались' фигуры
  
  if(color==player_color)
    return s[color]/3 - s[color^1];
  else
    return s[color] - s[color^1]/3;

 

Поиск.

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


int search(int alpha, int beta, int depth, int color, Move* best){
 Move m=0; 
 if(depth<=0)return Evaluate(color);
 GenerateMoves();
 PickBestMove(*best);
 int cnt_moves=0;
 for(mv in moves){
   cnt_moves++;
   MakeMove(mv);
   if(depth<=2) 

     tmp=-search(-beta,-alpha,depth-1,color^1,&m);
   else{
     for(int d=max(2,(int)sqrt(depth)); d <= depth-1; d++)
     {
       tmp=-search(-beta,-alpha,d,color^1,&m);
       if(tmp<=alpha && cnt_moves>1)break;
     }
   
   }
   
   UnMakeMove(mv);
   if(tmp>alpha) { alpha=tmp; *best=mv;}
   if(alpha>=beta) break;
 }
 return alpha;
}
/////

Заключение.

Этот алгоритм будет работать даже для несложных шахмат, только шахи в оконечном поиске надо расширять (глубину их поиска).
В зключении прилагаю исходники программы, написанно еще на turbo pascal 7.1. Можно запускать под dosemu.
https://disk.yandex.ru/d/QNDvuEpVQVNybg




      



четверг, 23 октября 2025 г.

Программирование игры в русские шашки.



  Статья pdf

В добавление к статье. В шашках как и в шахматах может проявляться эффект горизонта. Совершенно немыслимо написать шахматы не просматривая глубже шахи. Иначе программа может ломаться и сливать игру. В шашках тоже самое. Взятия являются вынужденными ходами и их можно просматривать несколько глубже примерно так. 

      int M = mtl[WHITE] - mtl[BLACK];

       if(side==WHITE){

           if(M >= white_mtl_search_path[ply-5])

             extend++;

       }else{

           if(M <= white_mtl_search_path[ply-5])

             extend++;

       }

Программа будет глубже смотреть строки с разменами и ввигрышами материала. 

Успехов. 

суббота, 11 октября 2025 г.

Логическая задача

 Пример 1.15. Пытаясь вспомнить победителей прошлогоднего турнира, пять бывших зрителей турнира заявили: 1) Антон был вторым, а Борис – пятым. 2) Виктор был вторым, а Денис – третьим. 3) Григорий был первым, а Борис - третьим 4) Антон был третьим, а Евгений – шестым. 5) Виктор был третьим, а Евгений – четвертым. Впоследствии выяснилось, что каждый зритель ошибся в одном из двух своих высказываний. Каково было истинное распределение мест в турнире? Решение. Обозначим высказывания зрителей символом Ху , где Х – первая буква имени участника турнира, а у – номер места, которое он занял в турнире. Так как в паре высказываний каждого зрителя одно истинно, а второе ложно, то будут истинными дизъюнкции этих высказываний А ∨ БK ≡ 1; В ∨ Д ≡ 1; Г ∨ Б ≡ 1; А ∨ ЕO ≡ 1; В ∨ Е ≡ 1. Но тогда истинной будет формула 8 ≡ (- ∨ БK) ∧ (В ∨ Д ) ∧ (Г ∨ Б) ∧ (А ∨ ЕO) ∧ (В ∨ Е) ≡ 1. Путем равносильных преобразований легко показать, что 8 ≡ А ∧ БK ∧ В ∧ Г ∧ Е ≡ 1. Откуда получаем А ≡ 1, БK ≡ 1, В ≡ 1, Г ≡ 1; Е ≡ 1, что и дает ответ задачи

Игра в дурня на python. Deep seek

 Отличная идея! Минимакс с альфа-бета отсечением значительно улучшит силу игры компьютера. Вот улучшенная версия с минимаксом:


```python

import random

from typing import List, Tuple, Optional, Dict

from collections import defaultdict

import math


class Card:

    def __init__(self, rank: str, suit: str):

        self.rank = rank

        self.suit = suit

        self.value = self._get_value()

    

    def _get_value(self) -> int:

        values = {'6': 6, '7': 7, '8': 8, '9': 9, '10': 10, 

                 'J': 11, 'Q': 12, 'K': 13, 'A': 14}

        return values[self.rank]

    

    def __str__(self):

        return f"{self.rank}{self.suit}"

    

    def __repr__(self):

        return str(self)

    

    def __eq__(self, other):

        return self.rank == other.rank and self.suit == other.suit

    

    def __hash__(self):

        return hash((self.rank, self.suit))


class Deck:

    def __init__(self):

        ranks = ['6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']

        suits = ['♥', '♦', '♣', '♠']

        self.cards = [Card(rank, suit) for suit in suits for rank in ranks]

        random.shuffle(self.cards)

    

    def deal(self, num_cards: int) -> List[Card]:

        return [self.cards.pop() for _ in range(num_cards)]


class GameState:

    """Класс для представления состояния игры"""

    def __init__(self, players_hands: List[List[Card]], table: List[Card], 

                 trump: str, attacker: int, deck_size: int):

        self.players_hands = [hand.copy() for hand in players_hands]

        self.table = table.copy()

        self.trump = trump

        self.attacker = attacker

        self.defender = 1 - attacker

        self.deck_size = deck_size

    

    def copy(self):

        return GameState(self.players_hands, self.table, self.trump, 

                        self.attacker, self.deck_size)


class FoolGameWithMinimax:

    def __init__(self):

        self.deck = Deck()

        self.players = [[], []]  # [0] - компьютер, [1] - игрок

        self.trump = self.deck.cards[-1].suit

        self.table = []

        self.attacker = 1  # кто ходит первым

        self.defender = 0  # кто отбивается

        self.max_depth = 3  # глубина поиска минимакса

        

    def deal_initial_cards(self):

        for i in range(2):

            self.players[i] = self.deck.deal(6)

            self.sort_hand(self.players[i])

    

    def sort_hand(self, hand: List[Card]):

        hand.sort(key=lambda card: (card.suit != self.trump, card.value))

    

    def get_game_state(self) -> GameState:

        return GameState(self.players, self.table, self.trump, 

                        self.attacker, len(self.deck.cards))

    

    def evaluate_state(self, state: GameState, player: int) -> float:

        """Оценка состояния игры для указанного игрока"""

        if not state.players_hands[player]:

            return 1000  # выигрыш

        

        if not state.players_hands[1 - player]:

            return -1000  # проигрыш

        

        score = 0

        

        # Оценка по картам в руке

        for i, hand in enumerate(state.players_hands):

            player_factor = 1 if i == player else -1

            hand_value = sum(card.value for card in hand)

            

            # Бонус за козыри

            trump_count = sum(1 for card in hand if card.suit == state.trump)

            trump_bonus = trump_count * 5

            

            # Штраф за много высоких карт (их сложнее сбросить)

            high_cards_penalty = sum(max(0, card.value - 10) for card in hand) * 0.5

            

            score += player_factor * (hand_value + trump_bonus - high_cards_penalty)

        

        # Оценка стола

        if state.table:

            if state.attacker == player:

                # Мы атакуем - хорошо иметь много карт на столе

                score += len(state.table) * 2

            else:

                # Мы защищаемся - плохо иметь много карт на столе

                score -= len(state.table) * 3

        

        # Бонус за карты в колоде

        score += state.deck_size * 0.1 * (1 if player == state.attacker else -1)

        

        return score

    

    def minimax(self, state: GameState, depth: int, alpha: float, beta: float, 

                maximizing_player: bool) -> Tuple[float, Optional[Tuple[Card, Optional[Card]]]]:

        """Минимакс с альфа-бета отсечением"""

        if depth == 0 or self.is_terminal_state(state):

            return self.evaluate_state(state, 0), None  # 0 - компьютер

        

        current_player = state.attacker if not state.table else state.defender

        is_computer_turn = (current_player == 0)

        

        if (maximizing_player and is_computer_turn) or (not maximizing_player and not is_computer_turn):

            return self._max_value(state, depth, alpha, beta, maximizing_player)

        else:

            return self._min_value(state, depth, alpha, beta, maximizing_player)

    

    def _max_value(self, state: GameState, depth: int, alpha: float, beta: float, 

                  maximizing_player: bool) -> Tuple[float, Optional[Tuple]]:

        best_value = -math.inf

        best_move = None

        

        for move in self.get_possible_moves(state):

            new_state = self.apply_move(state, move)

            value, _ = self.minimax(new_state, depth - 1, alpha, beta, not maximizing_player)

            

            if value > best_value:

                best_value = value

                best_move = move

            

            alpha = max(alpha, best_value)

            if beta <= alpha:

                break

        

        return best_value, best_move

    

    def _min_value(self, state: GameState, depth: int, alpha: float, beta: float, 

                  maximizing_player: bool) -> Tuple[float, Optional[Tuple]]:

        best_value = math.inf

        best_move = None

        

        for move in self.get_possible_moves(state):

            new_state = self.apply_move(state, move)

            value, _ = self.minimax(new_state, depth - 1, alpha, beta, not maximizing_player)

            

            if value < best_value:

                best_value = value

                best_move = move

            

            beta = min(beta, best_value)

            if beta <= alpha:

                break

        

        return best_value, best_move

    

    def get_possible_moves(self, state: GameState) -> List[Tuple[Card, Optional[Card]]]:

        """Возвращает все возможные ходы для текущего состояния"""

        moves = []

        current_player = state.attacker if not state.table else state.defender

        

        if not state.table:  # Атака

            # Можно пойти любой картой

            for card in state.players_hands[current_player]:

                moves.append((card, None))

        else:  # Защита или дополнительная атака

            if current_player == state.defender:  # Защита

                attacking_card = state.table[-1]

                for card in state.players_hands[current_player]:

                    if self._can_beat(attacking_card, card, state.trump):

                        moves.append((card, None))

                

                # Также можно взять карты

                moves.append((None, None))

            else:  # Дополнительная атака

                table_ranks = {card.rank for card in state.table}

                for card in state.players_hands[current_player]:

                    if card.rank in table_ranks:

                        moves.append((card, None))

        

        return moves

    

    def apply_move(self, state: GameState, move: Tuple[Card, Optional[Card]]) -> GameState:

        """Применяет ход к состоянию и возвращает новое состояние"""

        new_state = state.copy()

        card, _ = move

        

        if card is None:  # Взять карты

            new_state.players_hands[new_state.defender].extend(new_state.table)

            new_state.table.clear()

            new_state.attacker, new_state.defender = new_state.defender, new_state.attacker

        else:  # Сходить картой

            # Убираем карту из руки игрока

            new_state.players_hands[new_state.attacker if not new_state.table else new_state.defender].remove(card)

            new_state.table.append(card)

            

            # Если защита успешна и карты закончились - очищаем стол

            if new_state.table and len(new_state.table) % 2 == 0:

                if not self.can_continue_attack(new_state):

                    new_state.table.clear()

                    new_state.attacker, new_state.defender = new_state.defender, new_state.attacker

        

        return new_state

    

    def can_continue_attack(self, state: GameState) -> bool:

        """Можно ли продолжать атаку"""

        if not state.table or len(state.players_hands[state.attacker]) == 0:

            return False

        

        table_ranks = {card.rank for card in state.table}

        return any(card.rank in table_ranks for card in state.players_hands[state.attacker])

    

    def is_terminal_state(self, state: GameState) -> bool:

        """Проверка конечного состояния"""

        return (not state.players_hands[0] or not state.players_hands[1] or 

                (not state.deck_size and not state.table and 

                 (not state.players_hands[state.attacker] or not state.players_hands[state.defender])))

    

    def _can_beat(self, attacking: Card, defending: Card, trump: str) -> bool:

        """Может ли защищающая карта побить атакующую"""

        if defending.suit == trump and attacking.suit != trump:

            return True

        elif defending.suit == attacking.suit and defending.value > attacking.value:

            return True

        return False

    

    def find_best_move_minimax(self) -> Tuple[Optional[Card], Optional[Card]]:

        """Находит лучший ход с помощью минимакса"""

        state = self.get_game_state()

        _, best_move = self.minimax(state, self.max_depth, -math.inf, math.inf, True)

        return best_move or (None, None)

    

    def make_computer_move(self):

        """Компьютер делает ход на основе минимакса"""

        print("Компьютер думает...")

        card_to_play, _ = self.find_best_move_minimax()

        

        if card_to_play:

            self.players[0].remove(card_to_play)

            self.table.append(card_to_play)

            print(f"Компьютер ходит: {card_to_play}")

            return True

        else:

            print("Компьютер берет карты")

            self.players[0].extend(self.table)

            self.table.clear()

            self.sort_hand(self.players[0])

            return False

    

    def make_player_move(self, card_index: int) -> bool:

        """Игрок делает ход"""

        if 0 <= card_index < len(self.players[1]):

            card = self.players[1][card_index]

            self.players[1].remove(card)

            self.table.append(card)

            print(f"Вы ходите: {card}")

            return True

        return False

    

    def player_defend(self, card_index: int) -> bool:

        """Игрок защищается"""

        if not self.table:

            return False

            

        attacking_card = self.table[-1]

        if 0 <= card_index < len(self.players[1]):

            defending_card = self.players[1][card_index]

            

            if self._can_beat(attacking_card, defending_card, self.trump):

                self.players[1].remove(defending_card)

                self.table.append(defending_card)

                print(f"Вы отбиваете: {defending_card}")

                return True

        

        print("Нельзя побить этой картой!")

        return False

    

    def replenish_hands(self):

        """Добираем карты из колоды"""

        for i in range(2):

            while len(self.players[i]) < 6 and self.deck.cards:

                new_card = self.deck.deal(1)[0]

                self.players[i].append(new_card)

            self.sort_hand(self.players[i])

    

    def display_game_state(self):

        """Показывает текущее состояние игры"""

        print(f"\n{'='*50}")

        print(f"Козырь: {self.trump}")

        print(f"Карт в колоде: {len(self.deck.cards)}")

        print(f"\nСтол: {self.table}")

        print(f"\nВаши карты:")

        for i, card in enumerate(self.players[1]):

            print(f"{i}: {card}")

        print(f"\nКарты компьютера: {len(self.players[0])} карт")


def main():

    game = FoolGameWithMinimax()

    game.deal_initial_cards()

    

    print("Добро пожаловать в игру 'Дурак' с минимакс-ИИ!")

    print("Компьютер использует алгоритм минимакс для поиска лучшего хода.")

    

    while True:

        game.display_game_state()

        

        if game.attacker == 1:  # ход игрока

            if not game.table:  # атака

                print("\nВаш ход (атака). Выберите карту:")

                try:

                    choice = int(input("Введите номер карты: "))

                    if game.make_player_move(choice):

                        game.attacker, game.defender = game.defender, game.attacker

                except (ValueError, IndexError):

                    print("Неверный ввод!")

                    continue

            else:  # дополнительная атака

                print("\nХотите подкинуть карту? (y/n/t - взять)")

                action = input().lower()

                if action == 'y':

                    print("Выберите карту для подкидывания:")

                    try:

                        choice = int(input("Введите номер карты: "))

                        if game.make_player_move(choice):

                            pass

                        else:

                            continue

                    except (ValueError, IndexError):

                        print("Неверный ввод!")

                        continue

                elif action == 't':

                    print("Вы берете карты")

                    game.players[1].extend(game.table)

                    game.table.clear()

                    game.sort_hand(game.players[1])

                    game.replenish_hands()

                    game.attacker = 0

                    game.defender = 1

                else:

                    # Завершаем раунд

                    game.table.clear()

                    game.replenish_hands()

                    game.attacker = 0

                    game.defender = 1

        

        else:  # ход компьютера

            if not game.table:  # атака

                print("\nХод компьютера (атака):")

                if game.make_computer_move():

                    game.attacker, game.defender = game.defender, game.attacker

                else:

                    game.table.clear()

                    game.replenish_hands()

            else:  # защита компьютера

                print("\nХод компьютера (защита):")

                if game.make_computer_move():

                    pass

                else:

                    print("Компьютер берет карты")

                    game.players[0].extend(game.table)

                    game.table.clear()

                    game.sort_hand(game.players[0])

                    game.replenish_hands()

                    game.attacker = 1

                    game.defender = 0

        

        # Проверка конца игры

        if not game.players[0] and not game.players[1]:

            print("Ничья!")

            break

        elif not game.players[0]:

            print("Компьютер проиграл! Вы выиграли!")

            break

        elif not game.players[1]:

            print("Вы проиграли! Компьютер выиграл!")

            break


if __name__ == "__main__":

    main()

```


**Основные улучшения с минимаксом:**


1. **Класс GameState** - изолированное состояние игры для поиска

2. **Минимакс с альфа-бета отсечением** - просчет ходов на 3 шага вперед

3. **Функция оценки** учитывает:

   - Количество и ценность карт

   - Козыри

   - Позицию на столе

   - Карты в колоде


4. **Генерация всех возможных ходов** для каждого состояния

5. **Применение ходов** к копиям состояния для симуляции


**Преимущества минимакса:**

- Компьютер думает на несколько ходов вперед

- Учитывает ответные ходы игрока

- Выбирает стратегически выгодные позиции

- Избегает ловушек и использует слабости игрока


**Настройки:**

- `max_depth = 3` - можно увеличить для более сильной игры (но дольше расчет)

- Функцию оценки можно дополнить более сложными эвристиками


Теперь компьютер играет на качественно новом уровне!

суббота, 4 октября 2025 г.

Игра в Уголки на Bisual Basic 6


 

 Игра в уголки играется шашками. Надо занять поле противника ходя на одну клетку или перепрыгивая через. Все просто. Перебор ведется на 3 полухода. Хд противника можно не учитывать. Вводится некоторая случайность в оценке каждой клетки - случайность в пределах разумного.

Скачать исходники и исполняемый файл 

Для запуска программы могут потребоваться DLL Visual Basic 6. Придется его установить. Он очень небольшой по объему. 

Пример кода главного модуля:

Attribute VB_Name = "frmMain"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
'Corners 2012.02.11
'Wrote Nifont I.,

Const black_pawn = 1
Const white_pawn = 2
Const empty_square = 0

Dim init_pos ' 0..63
Dim click_sq(0 To 1) As Integer

Dim pos(0 To 63) As Integer
Const MaxPly = 10
Dim tree(0 To 1000) As move_type
Dim tree_cnt(0 To MaxPly) As Integer
Dim ply As Integer

Dim exist(0 To 63) As Integer

Const Max_Pieces = 9

Dim black_score_tbl ' (0 to 63)
Dim black_score_tbl_init
Dim target_tbl '      (0 to 63)
Dim static_score(1 To 2) As Integer
Dim end_piece_cnt(1 To 2) As Integer
Dim start_piece_cnt(1 To 2) As Integer
Dim xside(1 To 2) As Integer
Const INF = 30000
Dim find_best(0 To MaxPly) As move_type


Sub mix(ByVal min As Integer, ByVal max As Integer)
 Dim a%, b%, j%
 Dim mv As move_type
 
 If min < max Then
  Randomize
  For j = 0 To 20
    a = Int((max - min) * Rnd + min)
    b = Int((max - min) * Rnd + min)
    mv = tree(a)
    tree(a) = tree(b)
    tree(b) = mv
  Next j
 End If
End Sub



Function search(ByVal d As Integer, _
                ByVal side As Integer _
                ) As Integer
  Dim j%, score%
 
  find_best(ply).a = 0
  find_best(ply).b = 0
 
  If is_end_game > 0 Then
     search = (INF - ply)
  ElseIf (d <= 0) Or (ply >= MaxPly - 1) Then
     search = evaluate(side)
  Else
     search = -INF
     generate (side)
     If ply = 0 Then mix 0, tree_cnt(1) - 1
     
     For j = tree_cnt(ply) To tree_cnt(ply + 1) - 1
            
       make_move tree(j).a, tree(j).b
       ply = ply + 1
            
       score = search(d - 1, side)
       ply = ply - 1
       un_make_move tree(j).a, tree(j).b
       If score > search Then
         search = score
         find_best(ply) = tree(j)
       End If
     Next j
  End If
End Function



Function search_best(ByVal side) As Boolean
  Dim score%, d%, j%
  
   d = 3
   If end_piece_cnt(black_pawn) >= Max_Pieces - 1 Then
     d = 4
   End If
   
   score = search(3, side)
   
  search_best = find_best(0).a <> find_best(0).b
End Function


Function is_end_game() As Integer
  If (end_piece_cnt(white_pawn) >= Max_Pieces) Then
     is_end_game = white_pawn
  ElseIf (end_piece_cnt(black_pawn) >= Max_Pieces) Then
     is_end_game = black_pawn
  Else
     is_end_game = 0
  End If
End Function

Function evaluate(ByVal side As Integer) As Integer
 Dim score%
 
 score = static_score(white_pawn) - _
         static_score(black_pawn)
         
 If frmMain.optMaster.Value = True Then
   If start_piece_cnt(white_pawn) = 0 Then
     score = score + 70
   End If
 
   If start_piece_cnt(black_pawn) = 0 Then
     score = score - 70
   End If
 End If
 
 
 If side = white_pawn Then
  evaluate = score
 Else
  evaluate = -score
 End If
End Function


Sub insert_piece(ByVal p As Integer, _
                 ByVal sq As Integer)
                 
                 

                 
  pos(sq) = p
  If p = black_pawn Then
    static_score(p) = _
      static_score(p) + black_score_tbl(sq) + _
      target_tbl(sq)
    
  Else 'white_pawn
    static_score(p) = _
      static_score(p) + black_score_tbl(63 - sq) + _
      target_tbl(63 - sq)
  End If
  
  If init_pos(sq) = xside(p) Then
    end_piece_cnt(p) = end_piece_cnt(p) + 1
  ElseIf init_pos(sq) = p Then
    start_piece_cnt(p) = start_piece_cnt(p) + 1
  End If
End Sub



Sub remove_piece(ByVal p As Integer, _
                 ByVal sq As Integer)
  pos(sq) = 0
  If p = black_pawn Then
    static_score(p) = _
      static_score(p) - black_score_tbl(sq) - _
      target_tbl(sq)

  Else 'white_pawn
    static_score(p) = _
      static_score(p) - black_score_tbl(63 - sq) - _
      target_tbl(63 - sq)
  End If
  
  If init_pos(sq) = xside(p) Then
    end_piece_cnt(p) = end_piece_cnt(p) - 1
  ElseIf init_pos(sq) = p Then
    start_piece_cnt(p) = start_piece_cnt(p) - 1
  End If
End Sub

                 
Sub make_move(a As Integer, b As Integer)
   Debug.Assert (pos(a) > 0) And (pos(b) = 0)
   
   p = pos(a)
   remove_piece p, a
   insert_piece p, b
End Sub

Sub un_make_move(a As Integer, b As Integer)

   Debug.Assert (pos(b) > 0) And (pos(a) = 0)
   
   p = pos(b)
   remove_piece p, b
   insert_piece p, a
End Sub



Sub link_move(a As Integer, b As Integer)

  Debug.Assert (pos(a) > 0) And (pos(b) = 0)

  With tree(tree_cnt(ply + 1))
    .a = a
    .b = b
  End With
  tree_cnt(ply + 1) = tree_cnt(ply + 1) + 1
End Sub

 

Sub jamp_piece(ByVal start_sq As Integer, _
               ByVal sq As Integer)
  
 If exist(sq) = 0 Then
  
  exist(sq) = 1
  If sq <> start_sq Then
    link_move start_sq, sq
  End If
 
  If sq + 16 <= 63 Then _
   If pos(sq + 8) > 0 Then _
    If pos(sq + 16) = 0 Then _
      jamp_piece start_sq, sq + 16
  
  If sq - 16 >= 0 Then _
   If pos(sq - 8) > 0 Then _
    If pos(sq - 16) = 0 Then _
      jamp_piece start_sq, sq - 16
    
  If (sq And 7) > 1 Then _
   If pos(sq - 1) > 0 Then _
    If pos(sq - 2) = 0 Then _
      jamp_piece start_sq, sq - 2
  
  If (sq And 7) < 6 Then _
   If pos(sq + 1) > 0 Then _
    If pos(sq + 2) = 0 Then _
      jamp_piece start_sq, sq + 2
   
  exist(sq) = 0
 End If
End Sub


Sub move_piece(sq As Integer)
  If sq + 8 <= 63 Then
   If pos(sq + 8) = 0 Then
    link_move sq, (sq + 8)
   End If
  End If
  If sq - 8 >= 0 Then
   If pos(sq - 8) = 0 Then
    link_move sq, (sq - 8)
   End If
  End If
  If (sq And 7) < 7 Then
   If pos(sq + 1) = 0 Then
    link_move sq, (sq + 1)
   End If
  End If
  If (sq And 7) > 0 Then
   If pos(sq - 1) = 0 Then
    link_move sq, (sq - 1)
   End If
  End If
End Sub

Sub generate(ByVal side As Integer)
  tree_cnt(ply + 1) = tree_cnt(ply)
  For j = 0 To 63
    If pos(j) = side Then
       move_piece (j)
       jamp_piece j, j
    End If
  Next j
End Sub




       
Private Sub show_pos()
  For j = 0 To 63
   If pos(j) = black_pawn Then
     frmMain.Image1(j).Picture = _
     frmMain.img_black_ch.Picture
   ElseIf pos(j) = white_pawn Then
     frmMain.Image1(j).Picture = _
     frmMain.img_white_ch.Picture
   Else
     frmMain.Image1(j).Picture = _
     frmMain.img_empty_sq.Picture
   End If
  Next j
End Sub



Private Sub cmdAbout_Click()
  frmAbout.Show (modal)
End Sub

Private Sub cmd3_Click()
  img_shape.Visible = False
  
  
  'play_file "d:\src\corners_vb\Eingebne.wav"
 
  
  end_piece_cnt(1) = 0
  end_piece_cnt(2) = 0
  
  start_piece_cnt(1) = 0
  start_piece_cnt(2) = 0
  
  static_score(1) = 0
  static_score(2) = 0
  
  For j = 0 To 63
   pos(j) = 0
   If init_pos(j) <> 0 Then
     insert_piece init_pos(j), j
   End If
  Next j
  show_pos
  
End Sub

Private Sub cmdNew_Click()
  Randomize
  img_shape.Visible = False
  
  end_piece_cnt(1) = 0
  end_piece_cnt(2) = 0
  
  start_piece_cnt(1) = 0
  start_piece_cnt(2) = 0
  
  static_score(1) = 0
  static_score(2) = 0
  
  For j = 0 To 63
   pos(j) = 0
   If init_pos(j) <> 0 Then
     insert_piece init_pos(j), j
   End If
   black_score_tbl(j) = Int(black_score_tbl_init(j) * Rnd)
  Next j
  show_pos
  'play_file "burg.wav"
End Sub

Private Sub Form_Load()
  init_pos = Array _
      (1, 1, 1, 0, 0, 0, 0, 0, _
       1, 1, 1, 0, 0, 0, 0, 0, _
       1, 1, 1, 0, 0, 0, 0, 0, _
       0, 0, 0, 0, 0, 0, 0, 0, _
       0, 0, 0, 0, 0, 0, 0, 0, _
       0, 0, 0, 0, 0, 2, 2, 2, _
       0, 0, 0, 0, 0, 2, 2, 2, _
       0, 0, 0, 0, 0, 2, 2, 2)
  click_sq(0) = 0
  click_sq(1) = 0
  
  black_score_tbl = Array _
      (1, 2, 3, 4, 5, 6, 7, 8, _
       2, 9, 10, 11, 12, 13, 14, 15, _
       3, 10, 16, 17, 18, 19, 20, 21, _
       4, 11, 17, 22, 23, 24, 25, 26, _
       5, 12, 18, 23, 27, 28, 29, 30, _
       6, 13, 19, 24, 28, 31, 32, 33, _
       7, 14, 20, 25, 29, 32, 34, 35, _
       8, 15, 21, 26, 30, 33, 35, 36)
 black_score_tbl_init = Array _
      (1, 2, 3, 4, 5, 6, 7, 8, _
       2, 9, 10, 11, 12, 13, 14, 15, _
       3, 10, 16, 17, 18, 19, 20, 21, _
       4, 11, 17, 22, 23, 24, 25, 26, _
       5, 12, 18, 23, 27, 28, 29, 30, _
       6, 13, 19, 24, 28, 31, 32, 33, _
       7, 14, 20, 25, 29, 32, 34, 35, _
       8, 15, 21, 26, 30, 33, 35, 36)
  
  target_tbl = Array _
  (-2, -2, -2, 0, 0, 0, 0, 0, _
   -2, -2, -2, 0, 0, 0, 0, 0, _
   -2, -2, -2, 2, 2, 2, 0, 0, _
    0, 0, 2, 2, 2, 2, 0, 0, _
    0, 0, 2, 2, 2, 2, 0, 0, _
    0, 0, 2, 2, 2, 60, 60, 60, _
    0, 0, 0, 0, 0, 60, 60, 60, _
    0, 0, 0, 0, 0, 60, 60, 60)
    
 xside(1) = 2
 xside(2) = 1
    
 cmdNew_Click
 
    
End Sub

Private Sub Image1_Click(Index As Integer)
 Dim L%, T%
 Dim find As Boolean
 
 
 If is_end_game > 0 Then
   MsgBox ("Game Over! Click 'New' or EXit")
   Exit Sub
 End If
 
 
 'frmMain.img_shape.Move(left,top)
 L = frmMain.Image1(Index).Left
 T = frmMain.Image1(Index).Top
 frmMain.img_shape.Left = L
 frmMain.img_shape.Top = T
 frmMain.img_shape.Visible = True
' frmMain.img_shape.Top = True
 click_sq(0) = click_sq(1)
 click_sq(1) = Index
 
 'user move ?
 If pos(click_sq(0)) = white_pawn Then
  If pos(click_sq(1)) = 0 Then
     
     generate white_pawn
     find = False
     For j = 0 To tree_cnt(1) - 1
       If tree(j).a = click_sq(0) Then
        If tree(j).b = click_sq(1) Then
         find = True
        End If
       End If
     Next j
     
     If find Then
       make_move click_sq(0), click_sq(1)
       
      ' un_make_move click_sq(0), click_sq(1)
              
       
       click_sq(0) = click_sq(1)
       show_pos
       DoEvents
              
       If is_end_game > 0 Then
          play_file "Eingebne.wav"
          MsgBox ("Congratulate! Game Over!")
       Else
       
         Screen.MousePointer = vbHourglass
         find_move = search_best(black_pawn)
         Screen.MousePointer = vbDefault
         
         If find_move Then
          make_move find_best(0).a, _
                    find_best(0).b
          show_pos
          DoEvents
          If is_end_game > 0 Then
            MsgBox ("Sorry! Game Over")
          End If
         Else
           MsgBox ("?! No moves found!")
         End If
         
       End If
       
     End If
  End If
 End If
End Sub


 

 

 

Игра в Дурня на Си под ДОС

Когда то давным давно я в отпуске купил компьютер ZX-Spectrum, подключил его к телевизору и о чудо, там была брошюрка по программированию на бейсике для данного компа. Причем, включая звук и прочие прибамбасы. Так я познакомился с условиями и циклами и за отпуск успел написать карточную игру в дурня для текстового режима. Играла программа строго по алгоритму. Ходила с наименьшей и подкидывала всегда не жалея. Там надо было только добавить случайный выбор приоритета в пределах разумного но как то это до меня не сразу дошло и много лет спустя уже на ватком Си я пытался прикрутить альфа-бета процедуру поиска (подобно полному перебору). Дурень как известно мастерам - игра комбинационная. Так родилась сия программка. Она сочетает Монте Карло случайный выбор хода с поискам лучшей линии для двух сторон (стороны по очереди ходят по алгоритму). Это конечо не совсем комбинационный стиль игры но все же.
Ссылка исходников и экзешника для DOSBOX. Можно компильнуть в текстовом режиме на Visual C. Не судите за графику. Что мог так сказать.
Заглавочный файл программы:

 

 #ifndef KARD_H
#define KARD_H
///////////////

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <conio.h>
#include <sys/timeb.h>
#include <assert.h>
#include <limits.h>


#if INT_MAX==32767
  #define MS_DOS_REAL_MOVE  // comment this line
#endif
#if (_MSC_VER > 1200)
  #define kbhit _kbhit
  #define getch _getch
  #define getche _getche
 // #define sscanf sscanf_s
 // #define sprintf sprintf_s
#endif

enum Status{END_GAME=0, ZAHOD_COMP  =1, OTBOY_COMP  =2,
            ZAHOD_PLAYER=3, OTBOY_PLAYER=4};

enum Side{PLAYER,COMP,NOSIDE};
enum Mast{CHERVY,BUBY,KRESTY,PIKI};               //масть карты
enum Dost{K_6,K_7,K_8,K_9,K_10,K_J,K_D,K_K,K_T};  //достоинство карты
enum GameResult{DRAW=1, WINE=1000, LOSE=-1000};
#define NOKARD -1
#define NOMAST -1
#define KEY_EXIT  100 //user input
#define KEY_GO    101 //user input
#define dost(k) (k%9)   // return 0..8, '6'..'tuz'
#define mast(k) (k/9)   // return 0..3, 'chervy'..'piki'
extern char *dost_str[];
extern char *mast_str[];

struct Dec{
  int v[36],cnt;
};
struct Game{
  struct Dec player, comp, koloda, igra,
         koleso_fortuny;
  struct Dec *p[2];
  int kozyr;
  enum Status game_state;
  enum GameResult result[2];
  int is_load;
  int cnt_list_player_kard;
};
#define GAME_FILE_NAME "gamelst.dat"
#define MSG_HOD  "Pick the kard or press Enter('q'-exit)"
//"Enter the card number (0..31) or key-ENTER(retreat) or 'q' to quit"
#define MSG_LEFT "Do you want pass kard left?"
//"Do you want pass kard left? Card number (0..31) or key-ENTER"
//функции - предварительное описание
int new_game(void); int show_pos(void); int delay(void);
int razdacha(void); int check_end(void); int user_input(const char msg[]); int
iq_can_move_left(int kard,int side);
int shiftleft(struct Dec* x,int min,int max); int mics_dec(struct Dec *koloda);
int less_kard(struct Dec* z, int mast);int pick_kard(struct Dec *p, int kard);
int user_player_other_input(void); unsigned long gettickcount(void);
int run(void);
int find_kard(struct Dec *p, int kard); int find_dost(struct Dec *p, int dos);
int find_mast(struct Dec *p, int mast);
int is_kard_capture(int k0, int k1); char* kard_to_str(int kard,int N);
int clear_key_buf(void);int sort_kard(int v[], int sz);
enum Side getside(void);
enum Side opside(enum Side side);
int do_move(int k); int beru(void); int otboy(void);
int is_zahod(void); int proverka(void);
int get_first_kard_zahod_comp(int side);
int get_next_kard_zahod_comp(int side);
int end_game(void); int find_kard_otboy_comp(int k0,int side);
int get_first_kard_zahod_player(void);
int get_next_kard_zahod_player(void);
int find_kard_otboy_player(int kard0);
int zahod_player1(void); int otboy_player1(void);
int zahod_comp1(void); int otboy_comp1(void);
int save_game(void);
int load_game(void);
int get_other_kards_left_player(void);
int get_other_kards_left(void);
int compare_kard_order(int k0,int k1);
int get_other_kards_left_player_helper(void);
int get_cnt_starshih_kozyrey(int side);
int is_kards_bad(struct Dec *p);
int iq_check_zahod_kard_mid_game(int kard, int side);
int print_str_status(const char s[]);
int read_score(int c);
int Song(void); int Song1(void);
int show_game_result(void);
int get_koleso_fortuny();
////



//переменные игры
extern struct Game g, old_g;
extern int last_wine;
extern unsigned long diff; //задержка во времени в (1/18.2 sec)
extern int is_search; //? идет поиск
extern int is_text_mode;







////////////////
#endif