Извините, ничего не найдено.

Не расстраивайся! Лучше выпей чайку!
Регистрация
Справка
Календарь

Вернуться   forum.boolean.name > Проекты > Проекты C++

Ответ
 
Опции темы
Старый 21.01.2006, 12:19   #1
alcoSHoLiK
Дэвелопер
 
Регистрация: 17.01.2006
Сообщений: 1,512
Написано 78 полезных сообщений
(для 110 пользователей)
Вот, что готово. Осталось ИИ написать. С этим возникли трудности, так как я еще ниразу не писал ИИ. Буду рад, если кто-нибудь поможет советом

#include <conio.h>
#include <iostream>
#include <windows.h>
using namespace std;

const int FIELD_SIZE=8;
const int BLACK=1;
const int WHITE=2;

bool white=false;
bool game_over=false;
bool winner=false;
bool ai=false;

int bscore=2;	//score for black
int wscore=2;	//same for white

struct Coord {
	int x, y;
	Coord (int xx=1, int yy=1) : x (xx), y (yy) {}
};

struct AI_tmp {
	int x, y;
	int col;
	AI_tmp () : x (1), y (1), col (0) {}
};

class Field {
	Coord pos;
	AI_tmp ai_pos[64];	//array to keep AI's available moves in
	char temp_pos; //just a helping var

public:
	class Quit { public: Quit() {} };	//exception for the instant break

	char field[FIELD_SIZE+2][FIELD_SIZE+2];	//field must be public

	Field();

	void refresh();   	//set the cursor
	void draw (bool move_skipped=false);

	void set_pos (int x=0, int y=0);
	bool ai_check();
	bool move_check();	//check whether move is available
	bool put();
};

Field::Field() : pos (Coord (1,1))
{
	for (int i=0; i<=FIELD_SIZE+1; i++)
    for (int j=0; j<=FIELD_SIZE+1; j++)
 	field[i][j]='0';

/*	Starting position	*/
	field[4][4]=field[5][5]=WHITE;
	field[4][5]=field[5][4]=BLACK;

	refresh();
	draw();
}

inline void Field::refresh()
{
	for (int i=1; i<=FIELD_SIZE; i++)
 for (int j=1; j<=FIELD_SIZE; j++)
 	if (field[i][j]=='x') field[i][j]=temp_pos;
	
	temp_pos=field[pos.y][pos.x];
	field[pos.y][pos.x]='x';
}

inline void Field::draw(bool move_skipped)
{
	system("cls");

	for (int i=1; i<=FIELD_SIZE; i++) {
 for (int j=1; j<=FIELD_SIZE; j++) {
 	cout<<field[i][j]<<" ";
 }
 cout<<endl;
	}

/*	Display statistics	*/
	cout<<"\nPLAYER vs ";
	if (ai) cout<<"COMPUTER\n";
	else cout<<"PLAYER\n";
	cout<<"\nSCORE:\n\tblack: "<<bscore<<"\n\twhite: "<<wscore<<endl;
	if (game_over) return;
	if (move_skipped) {
 cout<<"\nWARNING: Move skipped.";
 if (ai && white) {
 	cout<<" Press any key...";
 	getch();
 }
	}
	if (white) cout<<"\nWhite's turn.";
	else cout<<"\nBlack's turn.";
}

void Field::set_pos (int x, int y)
{
	switch (x)
	{
	case -1:
 if (pos.x>1) pos.x--;
 break;
	case 1:
 if (pos.x<FIELD_SIZE) pos.x++;
	}
	switch (y)
	{
	case -1:
 if (pos.y>1) pos.y--;
 break;
	case 1:
 if (pos.y<FIELD_SIZE) pos.y++;
	}
	
	refresh();
	draw();
}

bool Field::ai_check()
{
	char piece=WHITE;
	int size=0;

/*	Finding all availabe moves	*/
	for (int i=1; i<=FIELD_SIZE; i++) {
 for (int j=1; j<=FIELD_SIZE; j++) {
 	if (field[i][j]=='0') {
  for (int y=-1; y<=1; y++) {
  	for (int x=-1; x<=1; x++) {
   if (y==0 && x==0) continue;
            
   int subi=i+y;
   int subj=j+x;
   if (field[subi][subj]=='0' || field[subi][subj]==piece) continue;
            int counter=0;
   
   while (field[subi][subj]!=piece && field[subi][subj]!='0') {
   	subi+=y;
   	subj+=x;
   	counter++;
   }

   if (counter && field[subi][subj]==piece) {
   	ai_pos[size].y=i;
   	ai_pos[size].x=j;
   	ai_pos[size].col=counter;
   	size++;
   }
  	}
  }
 	}
 }
	}
	if (!size) return false;	//no moves available

/*	Setting priority	*/
	while (true) {
	/*	Sorting	*/
    for (int i=0; i<size-1; i++) {
 	for (int j=1; j<size; j++)
  if (ai_pos[i].col<ai_pos[j].col) swap (ai_pos[i], ai_pos[j]);
 	if (ai_pos[i].col==0) size--;
 }

	/*	Tactical checks	*/
 bool change=false;
 try { 
 	//Don't give away an angle!
 	for (int i=1; i<=FIELD_SIZE; i+=7) {
  for (int j=1; j<=FIELD_SIZE; j+=7) {
  	for (int y=-1; y<=1; y++) {
   for (int x=-1; x<=1; x++) {
   	int tmp_x=j+x;
   	int tmp_y=i+y;
   	if (ai_pos[0].x==tmp_x && ai_pos[0].y==tmp_y && size>1) {
    ai_pos[0].col=0;
    change=true;
    throw Quit();	//instant break
   	}
   }
  	}
  }
 	}
 }
 catch (...) {}
 if (!change) break;	//nothing to change
	}

/*	Finally setting the position for move */
	pos.x=ai_pos[0].x;
	pos.y=ai_pos[0].y;

	return true;
}

bool Field::move_check()
{
	for (int i=1; i<=FIELD_SIZE; i++) {
 for (int j=1; j<=FIELD_SIZE; j++) {
 	if (field[i][j]=='0') {
  for (int y=-1; y<=1; y++) {
  	for (int x=-1; x<=1; x++) {
   if (y==0 && x==0) continue;

   int subi=i+y;
   int subj=j+x;
   int counter=0;
   char piece=white ? WHITE : BLACK;

  	/*	Counting possible moves	*/
   while (field[subi][subj]==piece) {
   	subi+=y;
   	subj+=x;
   	counter++;
   }

  	/*	Got at least one move	*/
   piece=3-piece;
   if (counter && field[subi][subj]==piece) return true;
  	}
  }
 	}
 }
	}

	return false;
}

bool Field::put()
{
	if (temp_pos!='0') return false;	//cell is not empty


	char piece=white ? WHITE : BLACK;
	bool check=false;

	for (int y=pos.y-1; y<=pos.y+1; y++) {
 for (int x=pos.x-1; x<=pos.x+1; x++) {
 	if (y==pos.y && x==pos.x) continue;
 	if (field[y][x]!='0' && field[y][x]!=piece) check=true;
 }
	}
	if (!check) return false;	//there is nothing useful around


	bool changed=false;
	int* ptr_bscore=&bscore;	//these 2 pointers are
	int* ptr_wscore=&wscore;	//for the comfortable score setting
	if (white) swap(ptr_bscore, ptr_wscore);


/*	Validating the move	*/
	int i=pos.y;
	int j=pos.x;
	for (int y=-1; y<=1; y++) {
 for (int x=-1; x<=1; x++) {
 	if (y==0 && x==0) continue;

 	int subi=i+y;
 	int subj=j+x;
 	if (field[subi][subj]=='0' || field[subi][subj]==piece) continue;
 	int counter=0;

 	while (field[subi][subj]!=piece && field[subi][subj]!='0') {
  subi+=y;
  subj+=x;
  counter++;
 	}

 	if (counter && field[subi][subj]==piece) {
  while (counter) {
  	counter--;
  	subi-=y;
  	subj-=x;
          (*ptr_bscore)++;
  	(*ptr_wscore)--;
  	field[subi][subj]=piece;
  }
  changed=true;
 	}
 }
	}
	if (!changed) return false;	//validation failed


	bool move_skip=false;

	if (!game_over) {
    field[pos.y][pos.x]=piece;
 (*ptr_bscore)++;

 if (wscore==0 || bscore==0 || (wscore+bscore)==64) {
 	game_over=true;
 	winner=bscore>wscore;
 }

 if (move_check()) white=!white;
 else move_skip=true;

 draw(move_skip);

 if (ai && white) {
 	Coord tmp_pos=pos;
 	ai_check();
 	Sleep (500);
 	put();
 	pos=tmp_pos;
 }
	}

	return true;
}


int main()
{
	char comp;
	bool inerror=true;

	while (inerror) {
    cout<<"Play with computer? (y/n)\n";
 comp=getch();
 switch (comp)
 {
 case 27:
 	return 0;
 case 'y':
 	ai=true;
 case 'n':
 	inerror=false;
 	break;
 default:
 	system ("cls");
 	cout<<"INPUT ERROR.\n";
 }
	}

	Field field;
	int key;

	while (true) {
    key=getch();
 switch (key)
 {
 case 72:
 	field.set_pos (0, -1);
 	break;
 case 75:
 	field.set_pos (-1);
 	break;
 case 77:
 	field.set_pos (1);
 	break;
 case 80:
 	field.set_pos (0, 1);
 	break;
 case 32:
 	field.put();
 	break;

 case 27:
 	return 0;
 }
 if (game_over) {
 	cout<<"\nTHE GAME HAS ENDED.\n";
 	if (winner) cout<<"BLACK";
 	else cout<<"WHITE";
 	cout<<" WON!\n";
 	getch();
 	return 0;
 }
	}
}
В аттаче exe.


P.S. Движок форума частично игнорирует табуляцию, поэтому советую использовать функцию цитирования для копирования кода в IDE.
(Offline)
 
Ответить с цитированием
Старый 21.01.2006, 13:44   #2
jimon
 
Сообщений: n/a
я так и непонял чем управлять
ps. если capslock включон - понажимай k и m
 
Ответить с цитированием
Старый 21.01.2006, 14:04   #3
AsmLover
Оператор ЭВМ
 
Регистрация: 12.01.2006
Сообщений: 21
Написано 0 полезных сообщений
(для 0 пользователей)
А выбор в switch (key) тебе ничего не говорит?

Имхо, фоновые нолики сбивают контраст, надо бы вместо них точки ...
Выигрышный алгоритм х.з. Лучше делай шахматы.
(Offline)
 
Ответить с цитированием
Старый 21.01.2006, 17:50   #4
alcoSHoLiK
Дэвелопер
 
Регистрация: 17.01.2006
Сообщений: 1,512
Написано 78 полезных сообщений
(для 110 пользователей)
jimon
Двигать стрелками, ход - пробел.
(Offline)
 
Ответить с цитированием
Старый 21.01.2006, 22:01   #5
jimon
 
Сообщений: n/a
похоже я незнаю правил игры
 
Ответить с цитированием
Старый 22.01.2006, 04:03   #6
Kain
ПроЭктировщик
 
Регистрация: 03.12.2005
Сообщений: 111
Написано 0 полезных сообщений
(для 0 пользователей)
Не разбираюсь в C++,но походу комп не следит за возможностью моего хода:
закончил 57 против 6 и 1 пустая,сори он тоже ходить не может ,
значит в завершение баг,а какой алгоритм у тебя ? (если не секрет)

У меня есть 2(или 3) реверси :одна флешка(безбашенная),вторая на 1С как
док. 1С предприятие( исходник, там же )оказалось что по русски
ещё труднее разобраться ,за что и не люблю енглиш ,гад !

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

Если я воспользуюсь твоим кодом (в теория или практике) ето наказуемо ?,

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

вот почему я с тобой спорил по поводу отвлечься ,сейчас отвлекся на муз.прогу
на Блице(как только подключил библиотеку)

а ваще алгоритм надо у себя подсмотреть,то как ты ходишь: делай анализ,затем сортируй (думаю версии 3-4(игры)) и можно сделать самый-самый II
ну ладно а то разошолся ....
PS вот сайт електронной библиотеки http://lib.mexmat.ru/

все через день затру.......
стер....
(Offline)
 
Ответить с цитированием
Старый 22.01.2006, 04:27   #7
Kain
ПроЭктировщик
 
Регистрация: 03.12.2005
Сообщений: 111
Написано 0 полезных сообщений
(для 0 пользователей)
Не утерпел, при
CapsLock и RU-складке
З =вниз
Р =вверх
Ь =вправо
Л =влево

AsmLover
Выигрышный алгоритм х.з. Лучше делай шахматы.
Он есть, только я неграмотный, наверняка через двоичную систему находиться
я про одну игру читал, все сводиться к безопасному и опасному ходу (не буду умничать, могу черкануть заметку с учбника по ТПаскалю = игра Ним)
jimon
похоже я незнаю правил игры
в кратце правилатаковы:
если Крестики-Нолики константы,
то Реверси переменные
(Offline)
 
Ответить с цитированием
Старый 22.01.2006, 11:42   #8
alcoSHoLiK
Дэвелопер
 
Регистрация: 17.01.2006
Сообщений: 1,512
Написано 78 полезных сообщений
(для 110 пользователей)
Не разбираюсь в C++,но походу комп не следит за возможностью моего хода:
закончил 57 против 6 и 1 пустая,сори он тоже ходить не может ,
значит* в завершение баг,а какой алгоритм у тебя ? (если не секрет)
Т.е. осталась одна пустая клетка, и никто из вас не может походить?

Если я воспользуюсь твоим кодом (в теория или практике) ето наказуемо ?,
Нет.


Алгоритм виден в коде. Сейчас ИИ почти не думает. Он выполняет только сортировку, а затем делает ход, при котором он заберет наибольшее количество очков. Естественно, это ведет к проигрышу.

Отдельное спасибо Jet'у за помощь с функцией move_check().


P.S. Kain, твоя ссылка тут не в тему. На форуме есть отдельный раздел для этого.
(Offline)
 
Ответить с цитированием
Старый 22.01.2006, 22:37   #9
Kain
ПроЭктировщик
 
Регистрация: 03.12.2005
Сообщений: 111
Написано 0 полезных сообщений
(для 0 пользователей)
Originally posted by alcoSHoLiK@Jan 22 2006, 10:42 AM
Т.е. осталась одна пустая клетка, и никто из вас не может походить?

Нет.
Алгоритм виден в коде. Сейчас ИИ почти не думает. Он выполняет только сортировку, а затем делает ход, при котором он заберет наибольшее количество очков. Естественно, это ведет к проигрышу.
первая часть да,и игра не заканчивается,ожидает мой ход (вроде)
второе осмелюсь спорить
не обязательно,ведь он не подставу тебе делает
у меня будет такой ИИ:

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


Опции темы

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Часовой пояс GMT +4, время: 22:58.


vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot
Style crйe par Allan - vBulletin-Ressources.com