Читать книгу Справочник Жаркова по проектированию и программированию искусственного интеллекта. Том 2: Программирование на Visual C# искусственного интеллекта (продолжение 1) - Валерий Алексеевич Карданов, Дарья Андреевна Самсонова, Наталья Сергеевна Кузьмина - Страница 10
Введение
12.4. Код программы
ОглавлениеОткрываем файл Form1.cs (например, по схеме: File, Open, File) и в классе Form1 записываем следующие переменные и метод.
Листинг 12.1. Переменные и метод.
public int cx = 15;
public int cy = 70;
public int Level = 3;
public Connect4Board b = new Connect4Board ();
public void Draw (Graphics g)
{
Pen p = new Pen (Color. Black);
g. DrawRectangle (p, 15, 70, 210, 180);
int q = 0;
int w = 5;
for (int y = cy; y <cy +180; y += 30)
{
for (int x = cx; x <cx +210; x += 30)
{
if (b.arr [q, w] == 0)
g.FillEllipse (new SolidBrush (Color. White),
x +3, y +3, 27, 27);
if (b.arr [q, w] == 1)
g.FillEllipse (new SolidBrush (Color. Yellow),
x +3, y +3, 27, 27);
if (b.arr [q, w] == 2)
g.FillEllipse (new SolidBrush(Color.Red),
x +3, y +3, 27, 27);
g. DrawEllipse (p, x +3, y +3, 27, 27);
q++;
}
q = 0;
w – ;
}
}
В панели Properties (для Form1) на вкладке Events дважды щёлкаем по имени события Paint. Появившийся шаблон метода Form1_Paint после записи нашего кода принимает следующий вид. Напомним, что другие варианты вывода изображения, например, на элемент управления PictureBox и после щелчка по какому-либо элементу управления уже приводились ранее.
Листинг 12.2. Метод для рисования изображений.
private void Form1_Paint (object sender, PaintEventArgs e)
{
e.Graphics.FillRectangle (new SolidBrush(Color.RoyalBlue),
15, 70, 210, 180);
Draw(e.Graphics);
}
В панели Properties (для Form1) на вкладке Events дважды щёлкаем по имени события MouseDown. Появившийся шаблон метода Form1_MouseDown после записи нашего кода принимает следующий вид.
Листинг 12.3. Метод для обработки щелчка экрана мышью.
private void Form1_MouseDown (object sender, MouseEventArgs e)
{
Microsoft.VisualBasic.Interaction.Beep ();
if (b. endt == 0)
{
if ((e.X> cx) && (e.X <cx +210))
{
if ((e.Y> cy) && (e.Y <cy +180))
{
int selection = (e.X – cx) / 30;
if ((selection> = 0) && (selection <7))
{
if (b.add (selection, b.plr) == 0)
{
Draw(this.CreateGraphics ());
b. turncheck ();
b. turn = b. cpu;
if (b. endt == 0)
{
int ck;
b.col = b.Think ();
ck = b.add(b.col, b. cpu);
if (ck == 0)
{
b.lin = 6 – b.tops[b.col];
b. turn = b.plr;
}
}
Draw(this.CreateGraphics ());
b. turncheck ();
}
}
}
}
}
}
Дважды щёлкаем по команде Begins the player (Начинает игрок) для элемента управления MenuStrip (или в панели Properties на вкладке Events выбираем событие Click). Появляется шаблон метода, который после записи нашего кода принимает следующий вид.
Листинг 12.4. Метод-обработчик выбора команды.
private void playerFirstToolStripMenuItem_Click (
object sender, EventArgs e)
{
//Player First
b = new Connect4Board ();
b.rec = Level;
Invalidate ();
}
Дважды щёлкаем по команде Begins the computer (Начинает компьютер) для элемента управления MenuStrip. Появляется шаблон метода, который после записи нашего кода принимает следующий вид.
Листинг 12.5. Метод-обработчик выбора команды.
private void computerFirstToolStripMenuItem_Click (
object sender, EventArgs e)
{
//CPU First
b = new Connect4Board ();
b.rec = Level;
Draw(this.CreateGraphics ());
b. turn = b. cpu;
if (b. endt == 0)
{
int ck;
b.col = b.Think ();
ck = b.add(b.col, b. cpu);
if (ck == 0)
{
b.lin = 6 – b.tops[b.col];
b. turn = b.plr;
}
}
Draw(this.CreateGraphics ());
b. turncheck ();
}
Дважды щёлкаем по команде Usual (Обычный). Появляется шаблон метода, который после записи нашего кода принимает следующий вид.
Листинг 12.6. Метод-обработчик выбора команды.
private void easyToolStripMenuItem_Click (
object sender, EventArgs e)
{
easyToolStripMenuItem.Checked = true;
hardToolStripMenuItem.Checked = false;
normalToolStripMenuItem.Checked = false;
//Easy
Level = 3;
b = new Connect4Board ();
b.rec = Level;
Invalidate ();
}
Дважды щёлкаем по команде Normal (Нормальный). Появляется шаблон метода, который после записи нашего кода принимает следующий вид.
Листинг 12.7. Метод-обработчик выбора команды.
private void normalToolStripMenuItem_Click (
object sender, EventArgs e)
{
hardToolStripMenuItem.Checked = false;
easyToolStripMenuItem.Checked = false;
normalToolStripMenuItem.Checked = true;
//Normal
Level = 5;
b = new Connect4Board ();
b.rec = Level;
Invalidate ();
}
Дважды щёлкаем по команде Difficult (Сложный). Появляется шаблон метода, который после записи нашего кода принимает следующий вид.
Листинг 12.8. Метод-обработчик выбора команды.
private void hardToolStripMenuItem_Click (
object sender, EventArgs e)
{
hardToolStripMenuItem.Checked = true;
easyToolStripMenuItem.Checked = false;
normalToolStripMenuItem.Checked = false;
//Hard
Level = 7;
b = new Connect4Board ();
b.rec = Level;
Invalidate ();
}
Схема записи и вывода справочной информации, например, с правилами игры после выбора дополнительной команды Справка (для элемента управления MenuStrip) дана ранее и в наших книгах на сайте ZharkovPress.ru в параграфе «Методика добавления информации в справочную форму».
Мы закончили написание программы в главный класс Form1 (для формы Form1 с пользовательским интерфейсом игры).
Теперь в наш проект добавляем новый файл (для программирования соответствующих игровых действий).
Добавить в проект файл можно по двум вариантам.
По первому варианту, добавляем в проект нужный файл по обычной схеме: в панели Solution Explorer выполняем правый щелчок по имени проекта, в контекстном меню выбираем Add, Existing Item, в панели Add Existing Item в окне «Files of type» выбираем «All Files», в центральном окне находим (например, в папке компьютера файл, скопированный из Интернета), выделяем имя этого файла и щёлкаем кнопку Add (или дважды щёлкаем по имени этого файла).
По второму варианту, в панели Solution Explorer выполняем правый щелчок по имени проекта и в контекстном меню выбираем Add, New Item, в панели Add New Item выделяем шаблон Code File, в окне Name записываем имя Connect4Board. cs и щёлкаем кнопку Add. В проект (и в панель Solution Explorer) добавляется этот файл, открывается пустое окно редактирования кода, в которое записываем код со следующего листинга.
Листинг 12.9. Новый файл.
using System;
using System. Drawing;
using System.Collections;
using System.Windows.Forms;
namespace Connect4
{
public class Connect4Board
{
public Random random = new Random ();
public int [,] arr = new int [7, 6];
public int [,] thn = new int [7, 6];
public int [] tops = new int [7];
public int player, computer, endt = 0;
public int plr = 1, cpu = 2, rec = 3, turn = 1;
public int m, n, r, temp, so, ch, col, t, y;
public int plrcoin, cpucoin;
public int lin;
public Connect4Board ()
{
}
public int Think ()
{
int i;
i = rec;
return check (i, -9999999, 9999999);
}
public void turncheck ()
{
int temp;
char [] toto = new char [20];
temp = checkwin ();
if (temp == plr)
{
MessageBox.Show («You won!»);
endt = 1; return;
}
if (temp == cpu)
{
MessageBox.Show («You lost.»);
endt = 1; return;
}
if (temp == 0)
{
for (t = 0; t <= 6; t++)
if (tops [t] <6) temp = 1;
if (temp == 0)
{
//drawn ();
endt = 1;
return;
}
}
}
public int check (int i, int alpha, int beta)
{
int co, score, t, g, j = 0, p;
i – ;
if (i == -1) {score = position (); return score;}
if (i % 2 == 0)
{
int max = 0, k;
j = 0; co = 0;
for (t = 0; t <7; t++)
{
g = add (t, cpu);
if (g == 0)
{
if (checkwin () == cpu)
{
sub (t);
if (i == rec – 1)
return t;
else return 9000;
}
k = check (i, alpha, 999999);
if (k> alpha) alpha = k;
sub (t);
if (k> beta) return k;
if (co == 0) {max = k; co = 1; j = t;}
if (k == max)
{
p = (random.Next (6)) +1;
if (p> 4) j = t;
}
if (k> max) {max = k; j = t;}
}
}
score = max;
}
else
{
int min = 0, k = 0;
co = 0;
for (t = 0; t <7; t++)
{
g = add (t, plr);
if (g == 0)
{
if (checkwin () == plr)
{
sub (t);
/*if (i==rec-1) return t; else*/
return -10000;
}
k = check (i, -99999, beta);
if (k <beta) beta = k;
sub (t);
if (k <alpha) return k;
if (co == 0) {min = k; co = 1; j = t;}
if (k <min) {min = k; j = t;}
}
}
score = min;
}
if (i == rec – 1) return j;
return score;
}
public int add (int c, int coin)
{
if (tops [c] <6)
{
arr [c, tops [c]] = coin;
tops [c] ++; return 0;
}
return 1;
}
public int sub (int c)
{
tops [c] – ;
arr [c, tops [c]] = 0;
return 0;
}
public int position ()
{
int u, o, x, y, j, score;
int gh = 0, hg = 0;
score = 0;
//Empty the think array
for (x = 0; x <7; x++)
{
for (y = 0; y <6; y++)
{
thn [x, y] = 0;
}
}
//Sum the score of every opportunity to the score
for (y = 0; y <6; y++)
{
for (x = 0; x <7; x++)
{
if (arr [x, y] == 0)
score = score + checkhole (x, y);
if (y> 0)
{
if ((thn [x, y] == cpu) &&
(arr [x, y – 1]!= 0)) gh++;
if ((thn [x, y] == plr) &&
(arr [x, y – 1]!= 0))
{hg++; score = score – 4000;}
}
else
{
if (thn [x, y] == cpu) gh++;
if (thn [x, y] == plr)
{hg++; score = score – 4000;}
}
}
}
if (gh> 1) score = score + (gh – 1) * 500;
if (gh == 1) score = score – 100;
if (hg> 1) score = score – (hg – 1) * 500;
for (x = 0; x <7; x++)
{
gh = 0;
for (y = 1; y <6; y++)
{
/*if (gh==0)
if ((thn [x,y]> 0) && (arr [x,y-1] ==0)) {
gh=1;
} */
if ((thn [x, y] == cpu) &&
(thn [x, y – 1] == cpu))
{
u = 0; j = 0;
for (o = y – 1; o> -1; o – )
{
if (thn [x, o] == plr) u = 1;
if (arr [x, o] == 0) j++;
}
if (u == 0) score = score +1300 – j * 7;
if (u == 1) score = score +300;
}
if ((thn [x, y] == plr) &&
(thn [x, y – 1] == plr))
{
u = 0; j = 0;
for (o = y – 1; o> -1; o – )
{
if (thn [x, o] == cpu) u = 1;
if (arr [x, o] == 0) j++;
}
if (u == 0) score = score – 1500 + j * 7;
if (u == 1) score = score – 300;
}
if (thn [x, y] == plr)
{
u = 0;
for (o = y – 1; o> -1; o – )
{
if (thn [x, o] == cpu) u = 1;
}
if (u == 1) score = score +30;
}
if (thn [x, y] == cpu)
{
u = 0;
for (o = y – 1; o> -1; o – )
{
if (thn [x, o] == plr) u = 1;
}
if (u == 1) score = score – 30;
}
}
}
return score;
}
public int checkhole (int x, int y)
{
int score = 0;
int max, min;
int d0 = 0, d1 = 0, d2 = 0, d3 = 0;
if (((x +1) <7) && ((y – 1)> -1))
{
if (arr [x +1, y – 1] == cpu)
{
d1++;
if (((x +2) <7) && ((y – 2)> -1))
{
if (arr [x +2, y – 2] == cpu)
{
d1++;
if (((x +3) <7) && ((y – 3)> -1))
{
if (arr [x +3, y – 3] == cpu)
d1++;
}
}
}
}
}
if (((x – 1)> -1) && ((y +1) <6))
{
if (arr [x – 1, y +1] == cpu)
{
d1++;
if (((x – 2)> -1) && ((y +2) <6))
{
if (arr [x – 2, y +2] == cpu)
{
d1++;
if (((x – 3)> -1) && ((y +3) <6))
{
if (arr [x – 3, y +3] == cpu) d1++;
}
}
}
}
}
if (((x – 1)> -1) && ((y – 1)> -1))
{
if (arr [x – 1, y – 1] == cpu)
{
d2++;
if (((x – 2)> -1) && ((y – 2)> -1))
{
if (arr [x – 2, y – 2] == cpu)
{
d2++;
if (((x – 3)> -1) && ((y – 3)> -1))
{
if (arr [x – 3, y – 3] == cpu) d2++;
}
}
}
}
}
if (((x +1) <7) && ((y +1) <6))
{
if (arr [x +1, y +1] == cpu)
{
d2++;
if (((x +2) <7) && ((y +2) <6))
{
if (arr [x +2, y +2] == cpu)
{
d2++;
if (((x +3) <7) && ((y +3) <6))
{
if (arr [x +3, y +3] == cpu) d2++;
}
}
}
}
}
if ((y – 1)> -1) if (arr [x, y – 1] == cpu)
{
d0++;
if ((y – 2)> -1) if (arr [x, y – 2] == cpu)
{
d0++;
if ((y – 3)> -1)
if (arr [x, y – 3] == cpu) d0++;
}
}
if (x – 1> -1)
{
if (arr [x – 1, y] == cpu)
{
d3++;
if (x – 2> -1)
{
if (arr [x – 2, y] == cpu)
{
d3++;
if (x – 3> -1)
if (arr [x – 3, y] == cpu) d3++;
}
}
}
}
if (x +1 <7)
{
if (arr [x +1, y] == cpu)
{
d3++;
if (x +2 <7)
{
if (arr [x +2, y] == cpu)
{
d3++;
if (x +3 <7)
if (arr [x +3, y] == cpu) d3++;
}
}
}
}
max = d0;
if (d1> max) max = d1;
if (d2> max) max = d2;
if (d3> max) max = d3;
if (max == 2) score = score +5;
if (max> 2)
{
score = score +71; thn [x, y] = cpu;
if ((d1 <3) && (d2 <3) && (d3 <3))
score = score – 10;
}
if (((x +1) <7) && ((y – 1)> -1))
{
if (arr [x +1, y – 1] == plr)
{
d1++;
if (((x +2) <7) && ((y – 2)> -1))
{
if (arr [x +2, y – 2] == plr)
{
d1++;
if (((x +3) <7) && ((y – 3)> -1))
{
if (arr [x +3, y – 3] == plr) d1++;
}
}
}
}
}
if (((x – 1)> -1) && ((y +1) <6))
{
if (arr [x – 1, y +1] == plr)
{
d1++;
if (((x – 2)> -1) && ((y +2) <6))
{
if (arr [x – 2, y +2] == plr)
{
d1++;
if (((x – 3)> -1) && ((y +3) <6))
{
if (arr [x – 3, y +3] == plr) d1++;
}
}
}
}
}
if (((x – 1)> -1) && ((y – 1)> -1))
{
if (arr [x – 1, y – 1] == plr)
{
d2++;
if (((x – 2)> -1) && ((y – 2)> -1))
{
if (arr [x – 2, y – 2] == plr)
{
d2++;
if (((x – 3)> -1) && ((y – 3)> -1))
{
if (arr [x – 3, y – 3] == plr) d2++;
}
}
}
}
}
if (((x +1) <7) && ((y +1) <6))
{
if (arr [x +1, y +1] == plr)
{
d2++;
if (((x +2) <7) && ((y +2) <6))
{
if (arr [x +2, y +2] == plr)
{
d2++;
if (((x +3) <7) && ((y +3) <6))
{
if (arr [x +3, y +3] == plr) d2++;
}
}
}
}
}
if ((y – 1)> -1) if (arr [x, y – 1] == plr)
{
d0++;
if ((y – 2)> -1) if (arr [x, y – 2] == plr)
{
d0++;
if ((y – 3)> -1)
if (arr [x, y – 3] == plr) d0++;
}
}
if (x – 1> -1)
{
if (arr [x – 1, y] == plr)
{
d3++;
if (x – 2> -1)
{
if (arr [x – 2, y] == plr)
{
d3++;
if (x – 3> -1)
if (arr [x – 3, y] == plr) d3++;
}
}
}
}
if (x +1 <7)
{
if (arr [x +1, y] == plr)
{
d3++;
if (x +2 <7)
{
if (arr [x +2, y] == plr)
{
d3++;
if (x +3 <7)
if (arr [x +3, y] == plr) d3++;
}
}
}
}
min = d0;
if (d1> min) min = d1;
if (d2> min) min = d2;
if (d3> min) min = d3;
if (min == 2) score = score – 4;
if (min> 2)
{
score = score – 70; thn [x, y] = plr;
if ((d1 <3) && (d2 <3) && (d3 <3))
score = score +10;
}
return score;
}
public int checkwin ()
{
int r, x, y;
r = 0;
for (y = 2; y> -1; y – )
{
for (x = 0; x <7; x++)
{
checku (x, y, ref r);
}
}
for (y = 0; y <6; y++)
{
for (x = 0; x <4; x++)
{
check2r (x, y, ref r);
}
}
for (y = 2; y> -1; y – )
{
for (x = 0; x <4; x++)
{
checkr (x, y, ref r);
}
}
for (y = 2; y> -1; y – )
{
for (x = 3; x <7; x++)
{
checkl (x, y, ref r);
}
}
return r;
}
public void checku (int x, int y, ref int r)
{
if ((arr [x, y] == 2) && (arr [x, y +1] == 2) &&
(arr [x, y +2] == 2) &&
(arr [x, y +3] == 2)) r = 2;
if ((arr [x, y] == 1) && (arr [x, y +1] == 1) &&
(arr [x, y +2] == 1) &&
(arr [x, y +3] == 1)) r = 1;
}
public void check2r (int x, int y, ref int r)
{
if ((arr [x, y] == 2) && (arr [x +1, y] == 2) &&
(arr [x +2, y] == 2) &&
(arr [x +3, y] == 2)) r = 2;
if ((arr [x, y] == 1) && (arr [x +1, y] == 1) &&
(arr [x +2, y] == 1) &&
(arr [x +3, y] == 1)) r = 1;
}
public void checkr (int x, int y, ref int r)
{
if ((arr [x, y] == 2) && (arr [x +1, y +1] == 2) &&
(arr [x +2, y +2] == 2) &&
(arr [x +3, y +3] == 2)) r = 2;
if ((arr [x, y] == 1) && (arr [x +1, y +1] == 1) &&
(arr [x +2, y +2] == 1) &&
(arr [x +3, y +3] == 1)) r = 1;
}
public void checkl (int x, int y, ref int r)
{
if ((arr [x, y] == 2) && (arr [x – 1, y +1] == 2) &&
(arr [x – 2, y +2] == 2) &&
(arr [x – 3, y +3] == 2)) r = 2;
if ((arr [x, y] == 1) && (arr [x – 1, y +1] == 1) &&
(arr [x – 2, y +2] == 1) && (
arr [x – 3, y +3] == 1)) r = 1;
}
}
}
После этого добавления в панели Solution Explorer появляется этот файл, как показано выше. Дважды щёлкая в SE по имени файла, любой файл можно открыть, изучить и редактировать.