Игра в Крестики-Нолики как известно уже бородатая задача для ИИ. Надо получить некоторую шустрость, но оставить игроку возможность выиграть. Я нашел прототип в инете (без поиска) и потерял ссылку, у кого увел графику:)) Перебор в общем идет на три полухода, оценка случайная в пределах разумного - каждая клетка имеет оценку как функцию от количества линий которые можно замкнуть с данного поля. Ссылка на исходник:
https://disk.yandex.ru/d/rnc8CABdtIXSUQ
/***
* Простая игра в крестики-нолики
* с графическим интерфейсом и выбором хода
* с элементом случайности
* evgeniy-korniloff@yandex.ru
***/
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
public class TicTacToeGame {
public static void main(String args[]) {
Gui gui = new Gui();
}
}
class TicTacToe {
public static int count = 0;
public boolean test = true;
public Gui gui;
////////////////////
Random random;
public static String[][] board = new String[3][3];
public static XYS tbl[]=new XYS[5];
final int KREST=0,NIL=1,EMPTY=2,INF=1000;
public int xboard[][]=new int[3][3];
public int side=KREST;
public int score_board[][]=new int[3][3];
public static int score_board_max[][]={
{ 3, 2, 3},
{ 2, 4, 2},
{ 3, 2, 3}
};
public static int full_line[][]={
{0,1,2},
{3,4,5},
{6,7,8},
{0,3,6},
{1,4,7},
{2,5,8},
{0,4,8},
{6,4,2}
};
Boolean is_full_line(int side){
for(int j=0;j<8;j++){
int i;
for(i=0;i<3;i++){
int y=full_line[j][i]/3;
int x=full_line[j][i]%3;
if(xboard[y][x]!=side)
break;
}
if(i==3) return true;
}
return false;
}
int Evaluate(int c,int depth){
if(is_full_line(c))return INF+depth;
if(is_full_line(c^1)) return -INF - depth;
int s[]={0,0};
int cnt=0;
for(int y=0;y<3;y++)
for(int x=0;x<3;x++)
if(xboard[y][x]!=EMPTY){
s[xboard[y][x]] += score_board[y][x];
cnt++;
}
return cnt==9? -1+random.nextInt(3):s[c] - s[c^1];
}
Boolean Draw(){
int cnt=0;
for(int y=0;y<3;y++)
for(int x=0;x<3;x++)
if(xboard[y][x]!=EMPTY){
cnt++;
}
return cnt==9? true:false;
}
void init_score(){
for(int y=0;y<3;y++)
for(int x=0;x<3;x++)
score_board[y][x]=
random.nextInt(score_board_max[y][x]*3);
}
class XYS{
public int x,y,score;
void Clear(){x=-1;y=-1;score=-INF-10;}
XYS(){Clear();}
Boolean Empty(){return x==-1 || y==-1;}
};
public void call_search(){
random = new Random(System.nanoTime());
init_score();
XYS z = new XYS();
int t = search(side,3,z);
if(z.Empty()==false){
xboard[z.y][z.x]=side;
if(side==KREST)
gui.gboard[z.y][z.x].setText("X");
else if(side==NIL)
gui.gboard[z.y][z.x].setText("o");
side ^= 1;
}
}
public int search(int c,int depth,XYS z){
z.Clear();
XYS tmp = tbl[depth];
int t = Evaluate(c,depth);
if(depth<=0 || t<=-INF || t>=INF || Draw()) return t;
for(int y=0;y<3;y++)
for(int x=0;x<3;x++)
if(xboard[y][x]==EMPTY)
{
xboard[y][x]=c;
int e = -search(c^1,depth-1,tmp);
if(e>z.score){
z.score = e;
z.x=x;
z.y=y;
}
xboard[y][x]=EMPTY;
}
return z.score;
}
void new_game(){
for(int y=0;y<3;y++)
for(int x=0;x<3;x++)
{
xboard[y][x]=EMPTY;
}
side=KREST;
init_score();
}
/// /////////////////////
public TicTacToe(Gui i){
gui=i;
random = new Random(System.nanoTime());
new_game();
for(int j=0;j<5;j++)
tbl[j]=new XYS();
//if(random.nextInt(2)==1)
// call_search();
}
public int get_button_index_on_board(JButton button){
for(int y=0;y<3;y++)
for(int x=0;x<3;x++)
if(gui.gboard[y][x]==button)
return y*3+x;
return -1;
}
public void buttonClicked(JButton button) {
if(side==KREST) {
int i = get_button_index_on_board(button);
if(i!=-1) {
int y = i/3;
int x = i%3;
if(xboard[y][x]==EMPTY){
xboard[y][x]=KREST;
side=NIL;
button.setText("X");
}
}
}else if(side==NIL){
int i = get_button_index_on_board(button);
if(i!=-1) {
int y = i/3;
int x = i%3;
if(xboard[y][x]==EMPTY){
xboard[y][x]=NIL;
side=KREST;
button.setText("O");
}
}
}
call_search();
/**
if(test) {
if(button.getText().equals("")) {
count++;
if(count % 2 == 1) {
button.setText("X");
}
if(count % 2 == 0) {
button.setText("O");
}
}
}
**/
}
public void gameRules(JButton button) {
if(is_full_line(KREST) ||
is_full_line(NIL)){
JOptionPane.showMessageDialog(null, " won.");
}else if(Draw()){
JOptionPane.showMessageDialog(null, " draw.");
}
/***
if(test) {
// if(false){
//"X" or "O"?
String string = button.getText();
//Gives coordinates of the button
int x = Character.getNumericValue(button.getName().charAt(0));
int y = Character.getNumericValue(button.getName().charAt(1));
board[x][y] = string;
if(board[0][0] != null && board[0][0].equals(board[1][1]) && board[1][1].equals(board[2][2])) {
JOptionPane.showMessageDialog(null,string + " won.");
test = false;
}
else if(board[0][2] != null && board[0][2].equals(board[1][1]) && board[1][1].equals(board[2][0])) {
JOptionPane.showMessageDialog(null,string + " won.");
test = false;
}
else if(count == 9) {
JOptionPane.showMessageDialog(null, "draw.");
test = false;
}
else {
for (int i = 0; i < 3; i++) {
if (board[i][0] != null && board[i][0].equals(board[i][1]) && board[i][0].equals(board[i][2])) {
JOptionPane.showMessageDialog(null, string + " won.");
test = false;
break;
}
if (board[0][i] != null && board[0][i].equals(board[1][i]) && board[0][i].equals(board[2][i])) {
JOptionPane.showMessageDialog(null, string + " won.");
test = false;
break;
}
}
}
}
*/
}
}
class Gui {
public JButton[][] gboard = new JButton[3][3];
public Gui() {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
TicTacToe ticTacToe = new TicTacToe(this);
panel.setLayout(new java.awt.GridLayout(3, 3));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
for (int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++) {
final JButton button = new JButton();
gboard [j][i]=button;
String string = i + "" + j;
button.setText("");
button.setName(string);
button.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
ticTacToe.buttonClicked(button);
ticTacToe.gameRules(button);
}
}
);
button.setFont(new Font("Arial", Font.PLAIN, 40));
button.setBorder(BorderFactory.createLineBorder(Color.BLACK));
panel.add(button);
}
}
frame.add(panel);
frame.setSize(400,400);
frame.setVisible(true);
}
}
Комментариев нет:
Отправить комментарий