Вот, что готово. Осталось ИИ написать. С этим возникли трудности, так как я еще ниразу не писал ИИ. Буду рад, если кто-нибудь поможет советом
#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.