Đầu tiên, mở eclipse và tạo một Java project tên là Gomoku
Lần lượt tạo các file CComputer.java, CGoban.java, CPiece.java, GPos.java và Gomoku.java với nội dung như sau:
CComputer.java
int Dx[];
int Dy[];
static final int D_UP = 0;
static final int D_UPRIGHT = 1;
static final int D_RIGHT = 2;
static final int D_DOWNRIGHT= 3;
static final int D_DOWN = 4;
static final int D_DOWNLEFT = 5;
static final int D_LEFT = 6;
static final int D_UPLEFT = 7;
public CComputer(CGoban goban) {
Goban = goban;
Dx = new int[8];
Dy = new int[8];
Dx[0] = 0; Dy[0] = -1;
Dx[1] = 1; Dy[1] = -1;
Dx[2] = 1; Dy[2] = 0;
Dx[3] = 1; Dy[3] = 1;
Dx[4] = 0; Dy[4] = 1;
Dx[5] = -1; Dy[5] = 1;
Dx[6] = -1; Dy[6] = 0;
Dx[7] = -1; Dy[7] = -1;
}
public int Think(int color,GPos Best) {
int x,y;
int BestScore = 0;
int eBestScore = 0;
int eBestX = 0;
int eBestY = 0;
int ecolor = (color==WHITE)? BLACK : WHITE;
Best.x = 0;
Best.y = 0;
for(x=0;x<CGoban.BOARDSIZE;x++){
for(y=0;y<CGoban.BOARDSIZE;y++){
if( Goban.Pieces[x][y].State == CPiece.EMPTY && Goban.Area[x][y] > 0 ){
Goban.Put(color,x,y);
if(GetScore(color,x,y) == ILL_NOT){
if(Score > BestScore) {
BestScore = Score;
Best.x = x;
Best.y = y;
}
}
Goban.Remove(x,y);
Goban.Put(ecolor,x,y);
if(GetScore(ecolor,x,y) == ILL_NOT){
if(Score > eBestScore) {
eBestScore = Score;
eBestX = x;
eBestY = y;
}
}
Goban.Remove(x,y);
}
}
}
if(BestScore >= SC_WIN){
Goban.Put(color,Best.x,Best.y);
Goban.Draw();
return THINK_WIN;
}
if(eBestScore >= SC_WIN){
Best.x = eBestX;
Best.y = eBestY;
} else if(eBestScore >= SC_WIN2) {
if(BestScore < SC_WIN2) {
Best.x = eBestX;
Best.y = eBestY;
}
} else if(BestScore < SC_WIN2 && Goban.numPiece > 3 && Goban.Sakiyomi) {
Best.x=-2; Best.y=-2;
Perspective(color,ecolor,Best);
} else {
if(eBestScore > BestScore){
Best.x=eBestX;
Best.y=eBestY;
}
}
Goban.Put(color,Best.x,Best.y);
Goban.Draw();
if(Goban.numPiece == Goban.MAXPIECENUM)
return THINK_FILLED;
return THINK_OK;
}
void Perspective(int color,int ecolor,GPos Best) {
int x,y;
int score=0;
int BestScore = 0;
numRecursion = 0;
Best.x = 0;
Best.y = 0;
for(x=0;x<CGoban.BOARDSIZE;x++){
for(y=0;y<CGoban.BOARDSIZE;y++){
if( Goban.Pieces[x][y].State == CPiece.EMPTY && Goban.Area[x][y] > 0 ){
Goban.Put(color,x,y);
;score = GetGlobalScore(color);
score += PerspectiveIter( color,ecolor);
if(score > BestScore) {
BestScore = score;
Best.x = x; Best.y = y;
}
Goban.Remove(x,y);
}
}
}
}
int PerspectiveIter(int color,int ecolor) {
int score = 0;
int num = 0;
int x,y,x2,y2;
for(x=0;x<CGoban.BOARDSIZE;x++){
for(y=0;y<CGoban.BOARDSIZE;y++){
if(Goban.Pieces[x][y].State == CPiece.EMPTY && Goban.Area[x][y] > 0 ){
Goban.Put(ecolor,x,y);
for(x2=0;x2<CGoban.BOARDSIZE;x2++){
for(y2=0;y2<CGoban.BOARDSIZE;y2++){
if(Goban.Pieces[x2][y2].State == CPiece.EMPTY && Goban.Area[x2][y2] > 0 ){
Goban.Put(color,x2,y2);
GetScore(color,x2,y2);
if(Score > 20){
score += GetGlobalScore(color) - GetGlobalScore(ecolor);
num++;
}
Goban.Remove(x2,y2);
}
}
}
Goban.Remove(x,y);
}
}
}
if(num == 0)
return 0;
return score / num;
}
final int SC_WIN = 10000000;
final int SC_WIN2 = 1000000;
int GetScore(int color,int x,int y) {
int d1,d2;
int check2open=0;
int check3open=0;
int check3close=0;
int check4open=0;
int check4close=0;
int check5 = 0;
int checklong=0;
int num;
boolean space1;
Score = 0;
for(d1=D_UP,d2=D_DOWN; d1 <= D_DOWNRIGHT; d1++,d2++) {
num = GetSequence(color,x,y,d1);
space1 = Space;
num += GetSequence(color,x,y,d2) - 1 ;
switch (num) {
case 2:
if( space1 && Space )
check2open++;
break;
case 3:
if( space1 && Space )
check3open++;
else if( space1 || Space )
check3close++;
break;
case 4:
if( space1 && Space )
check4open++;
else if (space1 || Space )
check4close++;
break;
case 5:
check5++;
break;
default:
if( num > 5 )
checklong++;
break;
}
}
if( color == CPiece.BLACK && Goban.Kinjite){
if(check3open >= 2)
return ILL_33;
if(check4open + check4close >= 2)
return ILL_44;
if(checklong > 0)
return ILL_CHOUREN;
}
if(check5 + checklong > 0) {
Score = SC_WIN;
} else if(check4open > 0) {
Score = SC_WIN2;
} else if(check4close >= 2) {
Score = SC_WIN2;
} else if( (check4open + check4close) > 0 && check3open > 0) {
Score = SC_WIN2;
} else if( check3open >= 2) {
Score = 30000;
} else if( check4close > 0 ) {
Score = 100;
} else if( check3open + check3close >= 2 ){
Score = 1200;
} else if( check3open > 0 ){
Score = 1000*check3open;
} else if( check3close >= 2 ){
Score = 120;
} else if( check2open > 0 ) {
Score = 100*check2open;
} else if( x==7 && y==7){
Score = 10;
} else {
Score = 1;
}
return ILL_NOT;
}
public int CheckIllegal(int color,int x,int y) {
if(color != CPiece.BLACK || Goban.Kinjite)
return ILL_NOT;
int d1,d2;
int check33=0;
int check44=0;
int checklong=0;
int num;
boolean space1;
for(d1=D_UP,d2=D_DOWN; d1 <= D_DOWNRIGHT; d1++,d2++) {
num = GetSequence(CPiece.BLACK,x,y,d1);
space1 = Space;
num += GetSequence(CPiece.BLACK,x,y,d2) - 1 ;
if( num == 3 && space1 && Space)
check33++;
if( num == 4 && ( space1 || Space ) )
check44++;
if( num > 5 )
checklong++;
}
if(check33 >= 2)
return ILL_33;
if(check44 >= 2)
return ILL_44;
if(checklong > 0)
return ILL_CHOUREN;
return ILL_NOT;
}
public int Find5Block(int color,int x,int y) {
int max,a;
max = GetSequence(color,x,y,D_UP) + GetSequence(color,x,y,D_DOWN) - 1 ;
a =GetSequence(color,x,y,D_LEFT) + GetSequence(color,x,y,D_RIGHT) - 1 ;
max = Math.max(max,a);
a = GetSequence(color,x,y,D_UPLEFT) + GetSequence(color,x,y,D_DOWNRIGHT) -1 ;
max = Math.max(max,a);
a = GetSequence(color,x,y,D_UPRIGHT) + GetSequence(color,x,y,D_DOWNLEFT) - 1 ;
max = Math.max(max,a);
if( max >= 5)
return OK5;
return NOT5;
}
public int GetSequence(int color,int x,int y,int direction) {
int num = 0;
int dx = Dx[direction];
int dy = Dy[direction];
Space = false;
while( Goban.Pieces[x][y].State == color) {
num++;
x += dx; y += dy;
if( x < 0 || x >= Goban.BOARDSIZE || y < 0 || y >= Goban.BOARDSIZE ) break;
if(Goban.Pieces[x][y].State == CPiece.EMPTY) {
Space = true;
break;
}
}
return num;
}
int num2open,num3open,num3close,num4open,num4close,num5;
public int GetGlobalScore(int color) {
int x,y;
boolean spacecheck;
num2open=0;
num3open=0;
num3close=0;
num4open=0;
num4close=0;
num5=0;
for(x=0; x < CGoban.BOARDSIZE; x++){
y=0; spacecheck=false;
do {
if(Goban.Pieces[x][y].State == EMPTY) {
spacecheck=true;
y++;
} else {
y += GetGlobalSequence(color,x,y,D_DOWN,spacecheck);
spacecheck=false;
}
} while(y < CGoban.BOARDSIZE);
}
for(y=0; y < CGoban.BOARDSIZE; y++){
x=0; spacecheck=false;
do {
if(Goban.Pieces[x][y].State == EMPTY) {
spacecheck=true;
x++;
} else {
x += GetGlobalSequence(color,x,y,D_RIGHT,spacecheck);
spacecheck=false;
}
} while(x < CGoban.BOARDSIZE);
}
for(int i=0; i < CGoban.BOARDSIZE*2-1; i++){
int ret;
if(i < CGoban.BOARDSIZE){
x = 0; y = i;
} else {
x = i-CGoban.BOARDSIZE+1; y=0;
}
spacecheck = false;
do {
if(Goban.Pieces[x][y].State == EMPTY) {
spacecheck=true;
x++; y++;
} else {
ret = GetGlobalSequence(color,x,y,D_DOWNRIGHT,spacecheck);
x+=ret; y+=ret;
spacecheck=false;
}
} while(x < CGoban.BOARDSIZE && y < CGoban.BOARDSIZE );
}
for(int i=0; i < CGoban.BOARDSIZE*2-1; i++){
int ret;
if(i < CGoban.BOARDSIZE){
x = 0; y = i;
} else {
x = i-CGoban.BOARDSIZE+1; y = CGoban.BOARDSIZE-1;
}
spacecheck = false;
do {
if(Goban.Pieces[x][y].State == EMPTY) {
spacecheck=true;
x++; y--;
} else {
ret = GetGlobalSequence(color,x,y,D_UPRIGHT,spacecheck);
x+=ret; y-=ret;
spacecheck=false;
}
} while(x < CGoban.BOARDSIZE && y >= 0 );
}
int score = num5 * 10000 + num4open * 5000 + num3open * 500
+ num3close * 10 + num2open * 20 + 1;
if(num4close >= 2)
score += 4000;
else
score += num4close * 400;
return score;
}
int GetGlobalSequence(int color,int x,int y,int direction,boolean spacecheck) {
int num = GetSequence(color,x,y,direction);
if(num==0)
return 1;
if(num==2){
if(Space && spacecheck)
num2open++;
} else if(num==3) {
if(Space && spacecheck)
num3open++;
else if(Space || spacecheck)
num3close++;
} else if(num==4){
if(Space && spacecheck)
num4open++;
else if(Space || spacecheck)
num4close++;
} else if(num >= 5) {
num5++;
}
return num;
}
}
CGoban.java
import java.applet.*;
import java.awt.*;
public class CGoban extends Canvas {
static final int TOP = 10;
static final int LEFT = 10;
static final int BOARDSIZE = 15;
static final int PIECESIZE = 20;
static final int MAXPIECENUM = BOARDSIZE * BOARDSIZE;
static final int GC_OK = 0;
static final int GC_ILLEGAL = 1;
static final int GC_CANNOT = 2;
static final int GC_FILLED = 3;
static final int GC_WIN = 4;
public boolean Sakiyomi;
public boolean Kinjite;
CPiece Pieces[][];
public int Area[][];
static final int AREASIZE = 2;
public int numPiece;
CComputer Computer;
public CGoban() {
resize(310,310);
Pieces = new CPiece[BOARDSIZE][BOARDSIZE];
for(int i=0; i < BOARDSIZE; i++){
for(int j=0; j < BOARDSIZE; j++){
Pieces[i][j] = new CPiece();
}
}
Area = new int[BOARDSIZE][BOARDSIZE];
}
public void Initialize(CComputer com) {
Computer = com;
for(int x=0; x < BOARDSIZE; x++){
for(int y=0; y < BOARDSIZE; y++){
Pieces[x][y].State = CPiece.EMPTY;
Area[x][y] = 0;
}
}
numPiece = 0;
}
public void Put(int color,int x,int y) {
if(Pieces[x][y].State == CPiece.EMPTY) {
Pieces[x][y].State = color;
numPiece++;
int x1,x2,y1,y2;
x1 = (x-AREASIZE < 0) ? 0 : x-AREASIZE ;
x2 = (x+AREASIZE >= BOARDSIZE) ? BOARDSIZE-1 : x+AREASIZE;
y1 = (y-AREASIZE < 0) ? 0 : y-AREASIZE ;
y2 = (y+AREASIZE >= BOARDSIZE) ? BOARDSIZE-1 : y+AREASIZE;
for( ; x1 <= x2; x1++){
for(y = y1 ; y <= y2; y++) {
Area[x1][y]++;
}
}
}
}
public void Remove(int x,int y) {
if(Pieces[x][y].State != CPiece.EMPTY) {
Pieces[x][y].State = CPiece.EMPTY;
numPiece--;
int x1,x2,y1,y2;
x1 = (x-AREASIZE < 0) ? 0 : x-AREASIZE ;
x2 = (x+AREASIZE >= BOARDSIZE) ? BOARDSIZE-1 : x+AREASIZE;
y1 = (y-AREASIZE < 0) ? 0 : y-AREASIZE ;
y2 = (y+AREASIZE >= BOARDSIZE) ? BOARDSIZE-1 : y+AREASIZE;
for( ; x1 <= x2; x1++){
for( y = y1; y <= y2; y++) {
Area[x1][y]--;
}
}
}
}
public int Check(int color,int x,int y) {
int ret;
if(Pieces[x][y].State != CPiece.EMPTY)
return GC_CANNOT;
Put(color,x,y);
ret = Computer.CheckIllegal(color,x,y);
if(ret != Computer.ILL_NOT){
Remove(x,y);
return GC_ILLEGAL;
}
ret = Computer.Find5Block(color,x,y);
Draw();
if(ret == Computer.OK5)
return GC_WIN;
if(numPiece == MAXPIECENUM)
return GC_FILLED;
return GC_OK;
}
public boolean GetPos(int x,int y,GPos pos) {
if(x < LEFT-(PIECESIZE/2) || x > LEFT+(PIECESIZE*(BOARDSIZE-1))+(PIECESIZE/2) )
return false;
if(y < TOP-(PIECESIZE/2) || y > TOP+(PIECESIZE*(BOARDSIZE-1))+(PIECESIZE/2) )
return false;
pos.x = ( x-(LEFT-(PIECESIZE/2)) ) / PIECESIZE;
pos.y = ( y-(TOP -(PIECESIZE/2)) ) / PIECESIZE;
return true;
}
public void Draw() {
repaint();
}
public void paint(Graphics g) {
int x,y;
g.setColor(Color.black);
for(x = 0; x < BOARDSIZE; x++) {
g.drawLine(x*PIECESIZE+LEFT,TOP,x*PIECESIZE+LEFT,TOP+(BOARDSIZE-1)*PIECESIZE);
}
for(y = 0; y < BOARDSIZE; y++) {
g.drawLine(LEFT,y*PIECESIZE+TOP,LEFT+(BOARDSIZE-1)*PIECESIZE,y*PIECESIZE+TOP);
}
for(x = 0; x < BOARDSIZE; x++) {
for(y = 0; y < BOARDSIZE; y++) {
switch(Pieces[x][y].State) {
case CPiece.WHITE:
g.setColor(Color.white);
g.fillOval(x*PIECESIZE,y*PIECESIZE,PIECESIZE-2,PIECESIZE-2);
g.setColor(Color.black);
g.drawOval(x*PIECESIZE,y*PIECESIZE,PIECESIZE-2,PIECESIZE-2);
break;
case CPiece.BLACK:
g.setColor(Color.black);
g.fillOval(x*PIECESIZE,y*PIECESIZE,PIECESIZE-2,PIECESIZE-2);
break;
}
}
}
}
}
CPiece.java
public class CPiece {
public int State;
static final int EMPTY = 0;
static final int WHITE = 1;
static final int BLACK = 2;
}
GPos.java
public class GPos {
int x;
int y;
}
File giao diện chính của chương trình: Gomoku.java
import java.applet.*;
import java.awt.*;
public class Gomoku extends Applet {
Panel ButtonArea;
Button Buttons[];
Label MessageLabel;
Checkbox Check1,Check2;
CGoban Goban;
CComputer Computer;
int Player[];
final int HUMAN = 1;
final int COMPUTER = 2;
int CurrentPlayer;
final int WHITE = 1;
final int BLACK = 2;
int GameState;
final int GS_END = 0;
final int GS_PLAYUSER = 1;
final int GS_PLAYCOM = 2;
final int GS_READY = 3;
public void init() {
ButtonArea = new Panel();
setLayout(new BorderLayout());
add("South",ButtonArea);
MessageLabel = new Label("Welcome to Gomoku-Narabe Game !");
add("Center",MessageLabel);
Goban = new CGoban();
add("North",Goban);
Buttons = new Button[4];
Buttons[0] = new Button("First");
Buttons[1] = new Button("Second");
Buttons[2] = new Button("Clear");
;Buttons[3] = new Button("Check");
ButtonArea.setLayout(new FlowLayout());
for(int i=0;i<3;i++)
ButtonArea.add(Buttons[i]);
Check1 = new Checkbox("Sakiyomi");
Check2 = new Checkbox("Kinjite");
ButtonArea.add(Check1);
ButtonArea.add(Check2);
Check1.setState(true);
Check2.setState(true);
Goban.Sakiyomi = true;
Goban.Kinjite=true;
Computer = new CComputer(Goban);
Player = new int[3];
}
public void start() {
InitGame();
}
public boolean action(Event e,Object o) {
String label = o.toString();
if(e.target instanceof Button){
if(label.equals("First")){
StartGame(HUMAN);
} else if (label.equals("Second")) {
StartGame(COMPUTER);
} else if (label.equals("Clear")) {
InitGame();
}
} else if(e.target instanceof Checkbox) {
Goban.Sakiyomi = Check1.getState();
Goban.Kinjite = Check2.getState();
}
return true;
}
void InitGame() {
Goban.Initialize(Computer);
Goban.Draw();
repaint();
GameState = GS_READY;
for(int i=0;i<2;i++)
Buttons[i].enable();
PutMessage("Click 'First' or 'Second' to start game.");
}
void StartGame(int FirstPlayer) {
if(GameState!=GS_READY)
return;
Player[BLACK] = FirstPlayer;
Player[WHITE] = (FirstPlayer==COMPUTER) ? HUMAN : COMPUTER;
CurrentPlayer = BLACK;
for(int i=0;i<2;i++)
Buttons[i].disable();
if(FirstPlayer==COMPUTER){
Goban.Area[7][7] = 1;
PlayComputer();
} else {
GameState = GS_PLAYUSER;
}
}
public boolean mouseDown(Event evt,int x,int y) {
if(GameState==GS_PLAYUSER && Player[CurrentPlayer]==HUMAN) {
GPos pos = new GPos();
if( !Goban.GetPos(x,y,pos) )
return true;
switch(Goban.Check(CurrentPlayer, pos.x, pos.y)) {
case CGoban.GC_OK:
CurrentPlayer = (CurrentPlayer == WHITE) ? BLACK : WHITE;
if(Player[CurrentPlayer] == COMPUTER){
GameState = GS_PLAYCOM;
}
break;
case CGoban.GC_ILLEGAL:
PutMessage("Illegal postion ! Can't put");
break;
case CGoban.GC_CANNOT:
PutMessage("Aleady exist! Can't put");
break;
case CGoban.GC_FILLED:
PutMessage("Board is filled ! Draw game.");
GameState = GS_END;
break;
case CGoban.GC_WIN:
PutMessage("You Win !!!");
GameState = GS_END;
break;
}
}
return true;
}
public boolean mouseUp(Event evt,int x,int y) {
if(GameState == GS_PLAYCOM){
PlayComputer();
}
return true;
}
void PlayComputer() {
GPos pos = new GPos();
PutMessage("Computer now thinking...");
switch(Computer.Think(CurrentPlayer,pos)) {
case CComputer.THINK_OK:
PutMessage("It's now your turn.");
CurrentPlayer = (CurrentPlayer == WHITE) ? BLACK : WHITE;
if(Player[CurrentPlayer] == COMPUTER){
PlayComputer();
} else {
GameState = GS_PLAYUSER;
}
break;
case CComputer.THINK_FILLED:
PutMessage("Board is filled ! Draw game.");
GameState = GS_END;
break;
case CComputer.THINK_WIN:
PutMessage("Computer Win !!!");
GameState = GS_END;
break;
}
}
public void PutMessage(String s) {
MessageLabel.setText(s);
}
public void paint(Graphics g) {
Goban.Draw();
}
}
Bây giờ, Build và chạy chương trình các bạn sẽ thấy giao diện như sau
Bắt đầu chơi nhé
Lần lượt tạo các file CComputer.java, CGoban.java, CPiece.java, GPos.java và Gomoku.java với nội dung như sau:
CComputer.java
import java.applet.*;
import java.awt.*;
public class CComputer {
CGoban Goban;
static final int EMPTY = 0;
static final int WHITE = 1;
static final int BLACK = 2;
public boolean Space;
public int Score;
int numRecursion;
static final int MAXRECURSION = 2;
static final int THINK_OK = 0;
static final int THINK_FILLED = 1;
static final int THINK_WIN = 2;
static final int NOT5 = 0;
static final int OK5 = 1;
static final int ILL_CHOUREN= 2;
static final int ILL_33 = 3;
static final int ILL_44 = 4;
static final int ILL_NOT = 5;
int Dx[];
int Dy[];
static final int D_UP = 0;
static final int D_UPRIGHT = 1;
static final int D_RIGHT = 2;
static final int D_DOWNRIGHT= 3;
static final int D_DOWN = 4;
static final int D_DOWNLEFT = 5;
static final int D_LEFT = 6;
static final int D_UPLEFT = 7;
public CComputer(CGoban goban) {
Goban = goban;
Dx = new int[8];
Dy = new int[8];
Dx[0] = 0; Dy[0] = -1;
Dx[1] = 1; Dy[1] = -1;
Dx[2] = 1; Dy[2] = 0;
Dx[3] = 1; Dy[3] = 1;
Dx[4] = 0; Dy[4] = 1;
Dx[5] = -1; Dy[5] = 1;
Dx[6] = -1; Dy[6] = 0;
Dx[7] = -1; Dy[7] = -1;
}
public int Think(int color,GPos Best) {
int x,y;
int BestScore = 0;
int eBestScore = 0;
int eBestX = 0;
int eBestY = 0;
int ecolor = (color==WHITE)? BLACK : WHITE;
Best.x = 0;
Best.y = 0;
for(x=0;x<CGoban.BOARDSIZE;x++){
for(y=0;y<CGoban.BOARDSIZE;y++){
if( Goban.Pieces[x][y].State == CPiece.EMPTY && Goban.Area[x][y] > 0 ){
Goban.Put(color,x,y);
if(GetScore(color,x,y) == ILL_NOT){
if(Score > BestScore) {
BestScore = Score;
Best.x = x;
Best.y = y;
}
}
Goban.Remove(x,y);
Goban.Put(ecolor,x,y);
if(GetScore(ecolor,x,y) == ILL_NOT){
if(Score > eBestScore) {
eBestScore = Score;
eBestX = x;
eBestY = y;
}
}
Goban.Remove(x,y);
}
}
}
if(BestScore >= SC_WIN){
Goban.Put(color,Best.x,Best.y);
Goban.Draw();
return THINK_WIN;
}
if(eBestScore >= SC_WIN){
Best.x = eBestX;
Best.y = eBestY;
} else if(eBestScore >= SC_WIN2) {
if(BestScore < SC_WIN2) {
Best.x = eBestX;
Best.y = eBestY;
}
} else if(BestScore < SC_WIN2 && Goban.numPiece > 3 && Goban.Sakiyomi) {
Best.x=-2; Best.y=-2;
Perspective(color,ecolor,Best);
} else {
if(eBestScore > BestScore){
Best.x=eBestX;
Best.y=eBestY;
}
}
Goban.Put(color,Best.x,Best.y);
Goban.Draw();
if(Goban.numPiece == Goban.MAXPIECENUM)
return THINK_FILLED;
return THINK_OK;
}
void Perspective(int color,int ecolor,GPos Best) {
int x,y;
int score=0;
int BestScore = 0;
numRecursion = 0;
Best.x = 0;
Best.y = 0;
for(x=0;x<CGoban.BOARDSIZE;x++){
for(y=0;y<CGoban.BOARDSIZE;y++){
if( Goban.Pieces[x][y].State == CPiece.EMPTY && Goban.Area[x][y] > 0 ){
Goban.Put(color,x,y);
;score = GetGlobalScore(color);
score += PerspectiveIter( color,ecolor);
if(score > BestScore) {
BestScore = score;
Best.x = x; Best.y = y;
}
Goban.Remove(x,y);
}
}
}
}
int PerspectiveIter(int color,int ecolor) {
int score = 0;
int num = 0;
int x,y,x2,y2;
for(x=0;x<CGoban.BOARDSIZE;x++){
for(y=0;y<CGoban.BOARDSIZE;y++){
if(Goban.Pieces[x][y].State == CPiece.EMPTY && Goban.Area[x][y] > 0 ){
Goban.Put(ecolor,x,y);
for(x2=0;x2<CGoban.BOARDSIZE;x2++){
for(y2=0;y2<CGoban.BOARDSIZE;y2++){
if(Goban.Pieces[x2][y2].State == CPiece.EMPTY && Goban.Area[x2][y2] > 0 ){
Goban.Put(color,x2,y2);
GetScore(color,x2,y2);
if(Score > 20){
score += GetGlobalScore(color) - GetGlobalScore(ecolor);
num++;
}
Goban.Remove(x2,y2);
}
}
}
Goban.Remove(x,y);
}
}
}
if(num == 0)
return 0;
return score / num;
}
final int SC_WIN = 10000000;
final int SC_WIN2 = 1000000;
int GetScore(int color,int x,int y) {
int d1,d2;
int check2open=0;
int check3open=0;
int check3close=0;
int check4open=0;
int check4close=0;
int check5 = 0;
int checklong=0;
int num;
boolean space1;
Score = 0;
for(d1=D_UP,d2=D_DOWN; d1 <= D_DOWNRIGHT; d1++,d2++) {
num = GetSequence(color,x,y,d1);
space1 = Space;
num += GetSequence(color,x,y,d2) - 1 ;
switch (num) {
case 2:
if( space1 && Space )
check2open++;
break;
case 3:
if( space1 && Space )
check3open++;
else if( space1 || Space )
check3close++;
break;
case 4:
if( space1 && Space )
check4open++;
else if (space1 || Space )
check4close++;
break;
case 5:
check5++;
break;
default:
if( num > 5 )
checklong++;
break;
}
}
if( color == CPiece.BLACK && Goban.Kinjite){
if(check3open >= 2)
return ILL_33;
if(check4open + check4close >= 2)
return ILL_44;
if(checklong > 0)
return ILL_CHOUREN;
}
if(check5 + checklong > 0) {
Score = SC_WIN;
} else if(check4open > 0) {
Score = SC_WIN2;
} else if(check4close >= 2) {
Score = SC_WIN2;
} else if( (check4open + check4close) > 0 && check3open > 0) {
Score = SC_WIN2;
} else if( check3open >= 2) {
Score = 30000;
} else if( check4close > 0 ) {
Score = 100;
} else if( check3open + check3close >= 2 ){
Score = 1200;
} else if( check3open > 0 ){
Score = 1000*check3open;
} else if( check3close >= 2 ){
Score = 120;
} else if( check2open > 0 ) {
Score = 100*check2open;
} else if( x==7 && y==7){
Score = 10;
} else {
Score = 1;
}
return ILL_NOT;
}
public int CheckIllegal(int color,int x,int y) {
if(color != CPiece.BLACK || Goban.Kinjite)
return ILL_NOT;
int d1,d2;
int check33=0;
int check44=0;
int checklong=0;
int num;
boolean space1;
for(d1=D_UP,d2=D_DOWN; d1 <= D_DOWNRIGHT; d1++,d2++) {
num = GetSequence(CPiece.BLACK,x,y,d1);
space1 = Space;
num += GetSequence(CPiece.BLACK,x,y,d2) - 1 ;
if( num == 3 && space1 && Space)
check33++;
if( num == 4 && ( space1 || Space ) )
check44++;
if( num > 5 )
checklong++;
}
if(check33 >= 2)
return ILL_33;
if(check44 >= 2)
return ILL_44;
if(checklong > 0)
return ILL_CHOUREN;
return ILL_NOT;
}
public int Find5Block(int color,int x,int y) {
int max,a;
max = GetSequence(color,x,y,D_UP) + GetSequence(color,x,y,D_DOWN) - 1 ;
a =GetSequence(color,x,y,D_LEFT) + GetSequence(color,x,y,D_RIGHT) - 1 ;
max = Math.max(max,a);
a = GetSequence(color,x,y,D_UPLEFT) + GetSequence(color,x,y,D_DOWNRIGHT) -1 ;
max = Math.max(max,a);
a = GetSequence(color,x,y,D_UPRIGHT) + GetSequence(color,x,y,D_DOWNLEFT) - 1 ;
max = Math.max(max,a);
if( max >= 5)
return OK5;
return NOT5;
}
public int GetSequence(int color,int x,int y,int direction) {
int num = 0;
int dx = Dx[direction];
int dy = Dy[direction];
Space = false;
while( Goban.Pieces[x][y].State == color) {
num++;
x += dx; y += dy;
if( x < 0 || x >= Goban.BOARDSIZE || y < 0 || y >= Goban.BOARDSIZE ) break;
if(Goban.Pieces[x][y].State == CPiece.EMPTY) {
Space = true;
break;
}
}
return num;
}
int num2open,num3open,num3close,num4open,num4close,num5;
public int GetGlobalScore(int color) {
int x,y;
boolean spacecheck;
num2open=0;
num3open=0;
num3close=0;
num4open=0;
num4close=0;
num5=0;
for(x=0; x < CGoban.BOARDSIZE; x++){
y=0; spacecheck=false;
do {
if(Goban.Pieces[x][y].State == EMPTY) {
spacecheck=true;
y++;
} else {
y += GetGlobalSequence(color,x,y,D_DOWN,spacecheck);
spacecheck=false;
}
} while(y < CGoban.BOARDSIZE);
}
for(y=0; y < CGoban.BOARDSIZE; y++){
x=0; spacecheck=false;
do {
if(Goban.Pieces[x][y].State == EMPTY) {
spacecheck=true;
x++;
} else {
x += GetGlobalSequence(color,x,y,D_RIGHT,spacecheck);
spacecheck=false;
}
} while(x < CGoban.BOARDSIZE);
}
for(int i=0; i < CGoban.BOARDSIZE*2-1; i++){
int ret;
if(i < CGoban.BOARDSIZE){
x = 0; y = i;
} else {
x = i-CGoban.BOARDSIZE+1; y=0;
}
spacecheck = false;
do {
if(Goban.Pieces[x][y].State == EMPTY) {
spacecheck=true;
x++; y++;
} else {
ret = GetGlobalSequence(color,x,y,D_DOWNRIGHT,spacecheck);
x+=ret; y+=ret;
spacecheck=false;
}
} while(x < CGoban.BOARDSIZE && y < CGoban.BOARDSIZE );
}
for(int i=0; i < CGoban.BOARDSIZE*2-1; i++){
int ret;
if(i < CGoban.BOARDSIZE){
x = 0; y = i;
} else {
x = i-CGoban.BOARDSIZE+1; y = CGoban.BOARDSIZE-1;
}
spacecheck = false;
do {
if(Goban.Pieces[x][y].State == EMPTY) {
spacecheck=true;
x++; y--;
} else {
ret = GetGlobalSequence(color,x,y,D_UPRIGHT,spacecheck);
x+=ret; y-=ret;
spacecheck=false;
}
} while(x < CGoban.BOARDSIZE && y >= 0 );
}
int score = num5 * 10000 + num4open * 5000 + num3open * 500
+ num3close * 10 + num2open * 20 + 1;
if(num4close >= 2)
score += 4000;
else
score += num4close * 400;
return score;
}
int GetGlobalSequence(int color,int x,int y,int direction,boolean spacecheck) {
int num = GetSequence(color,x,y,direction);
if(num==0)
return 1;
if(num==2){
if(Space && spacecheck)
num2open++;
} else if(num==3) {
if(Space && spacecheck)
num3open++;
else if(Space || spacecheck)
num3close++;
} else if(num==4){
if(Space && spacecheck)
num4open++;
else if(Space || spacecheck)
num4close++;
} else if(num >= 5) {
num5++;
}
return num;
}
}
CGoban.java
import java.applet.*;
import java.awt.*;
public class CGoban extends Canvas {
static final int TOP = 10;
static final int LEFT = 10;
static final int BOARDSIZE = 15;
static final int PIECESIZE = 20;
static final int MAXPIECENUM = BOARDSIZE * BOARDSIZE;
static final int GC_OK = 0;
static final int GC_ILLEGAL = 1;
static final int GC_CANNOT = 2;
static final int GC_FILLED = 3;
static final int GC_WIN = 4;
public boolean Sakiyomi;
public boolean Kinjite;
CPiece Pieces[][];
public int Area[][];
static final int AREASIZE = 2;
public int numPiece;
CComputer Computer;
public CGoban() {
resize(310,310);
Pieces = new CPiece[BOARDSIZE][BOARDSIZE];
for(int i=0; i < BOARDSIZE; i++){
for(int j=0; j < BOARDSIZE; j++){
Pieces[i][j] = new CPiece();
}
}
Area = new int[BOARDSIZE][BOARDSIZE];
}
public void Initialize(CComputer com) {
Computer = com;
for(int x=0; x < BOARDSIZE; x++){
for(int y=0; y < BOARDSIZE; y++){
Pieces[x][y].State = CPiece.EMPTY;
Area[x][y] = 0;
}
}
numPiece = 0;
}
public void Put(int color,int x,int y) {
if(Pieces[x][y].State == CPiece.EMPTY) {
Pieces[x][y].State = color;
numPiece++;
int x1,x2,y1,y2;
x1 = (x-AREASIZE < 0) ? 0 : x-AREASIZE ;
x2 = (x+AREASIZE >= BOARDSIZE) ? BOARDSIZE-1 : x+AREASIZE;
y1 = (y-AREASIZE < 0) ? 0 : y-AREASIZE ;
y2 = (y+AREASIZE >= BOARDSIZE) ? BOARDSIZE-1 : y+AREASIZE;
for( ; x1 <= x2; x1++){
for(y = y1 ; y <= y2; y++) {
Area[x1][y]++;
}
}
}
}
public void Remove(int x,int y) {
if(Pieces[x][y].State != CPiece.EMPTY) {
Pieces[x][y].State = CPiece.EMPTY;
numPiece--;
int x1,x2,y1,y2;
x1 = (x-AREASIZE < 0) ? 0 : x-AREASIZE ;
x2 = (x+AREASIZE >= BOARDSIZE) ? BOARDSIZE-1 : x+AREASIZE;
y1 = (y-AREASIZE < 0) ? 0 : y-AREASIZE ;
y2 = (y+AREASIZE >= BOARDSIZE) ? BOARDSIZE-1 : y+AREASIZE;
for( ; x1 <= x2; x1++){
for( y = y1; y <= y2; y++) {
Area[x1][y]--;
}
}
}
}
public int Check(int color,int x,int y) {
int ret;
if(Pieces[x][y].State != CPiece.EMPTY)
return GC_CANNOT;
Put(color,x,y);
ret = Computer.CheckIllegal(color,x,y);
if(ret != Computer.ILL_NOT){
Remove(x,y);
return GC_ILLEGAL;
}
ret = Computer.Find5Block(color,x,y);
Draw();
if(ret == Computer.OK5)
return GC_WIN;
if(numPiece == MAXPIECENUM)
return GC_FILLED;
return GC_OK;
}
public boolean GetPos(int x,int y,GPos pos) {
if(x < LEFT-(PIECESIZE/2) || x > LEFT+(PIECESIZE*(BOARDSIZE-1))+(PIECESIZE/2) )
return false;
if(y < TOP-(PIECESIZE/2) || y > TOP+(PIECESIZE*(BOARDSIZE-1))+(PIECESIZE/2) )
return false;
pos.x = ( x-(LEFT-(PIECESIZE/2)) ) / PIECESIZE;
pos.y = ( y-(TOP -(PIECESIZE/2)) ) / PIECESIZE;
return true;
}
public void Draw() {
repaint();
}
public void paint(Graphics g) {
int x,y;
g.setColor(Color.black);
for(x = 0; x < BOARDSIZE; x++) {
g.drawLine(x*PIECESIZE+LEFT,TOP,x*PIECESIZE+LEFT,TOP+(BOARDSIZE-1)*PIECESIZE);
}
for(y = 0; y < BOARDSIZE; y++) {
g.drawLine(LEFT,y*PIECESIZE+TOP,LEFT+(BOARDSIZE-1)*PIECESIZE,y*PIECESIZE+TOP);
}
for(x = 0; x < BOARDSIZE; x++) {
for(y = 0; y < BOARDSIZE; y++) {
switch(Pieces[x][y].State) {
case CPiece.WHITE:
g.setColor(Color.white);
g.fillOval(x*PIECESIZE,y*PIECESIZE,PIECESIZE-2,PIECESIZE-2);
g.setColor(Color.black);
g.drawOval(x*PIECESIZE,y*PIECESIZE,PIECESIZE-2,PIECESIZE-2);
break;
case CPiece.BLACK:
g.setColor(Color.black);
g.fillOval(x*PIECESIZE,y*PIECESIZE,PIECESIZE-2,PIECESIZE-2);
break;
}
}
}
}
}
CPiece.java
public class CPiece {
public int State;
static final int EMPTY = 0;
static final int WHITE = 1;
static final int BLACK = 2;
}
GPos.java
public class GPos {
int x;
int y;
}
File giao diện chính của chương trình: Gomoku.java
import java.applet.*;
import java.awt.*;
public class Gomoku extends Applet {
Panel ButtonArea;
Button Buttons[];
Label MessageLabel;
Checkbox Check1,Check2;
CGoban Goban;
CComputer Computer;
int Player[];
final int HUMAN = 1;
final int COMPUTER = 2;
int CurrentPlayer;
final int WHITE = 1;
final int BLACK = 2;
int GameState;
final int GS_END = 0;
final int GS_PLAYUSER = 1;
final int GS_PLAYCOM = 2;
final int GS_READY = 3;
public void init() {
ButtonArea = new Panel();
setLayout(new BorderLayout());
add("South",ButtonArea);
MessageLabel = new Label("Welcome to Gomoku-Narabe Game !");
add("Center",MessageLabel);
Goban = new CGoban();
add("North",Goban);
Buttons = new Button[4];
Buttons[0] = new Button("First");
Buttons[1] = new Button("Second");
Buttons[2] = new Button("Clear");
;Buttons[3] = new Button("Check");
ButtonArea.setLayout(new FlowLayout());
for(int i=0;i<3;i++)
ButtonArea.add(Buttons[i]);
Check1 = new Checkbox("Sakiyomi");
Check2 = new Checkbox("Kinjite");
ButtonArea.add(Check1);
ButtonArea.add(Check2);
Check1.setState(true);
Check2.setState(true);
Goban.Sakiyomi = true;
Goban.Kinjite=true;
Computer = new CComputer(Goban);
Player = new int[3];
}
public void start() {
InitGame();
}
public boolean action(Event e,Object o) {
String label = o.toString();
if(e.target instanceof Button){
if(label.equals("First")){
StartGame(HUMAN);
} else if (label.equals("Second")) {
StartGame(COMPUTER);
} else if (label.equals("Clear")) {
InitGame();
}
} else if(e.target instanceof Checkbox) {
Goban.Sakiyomi = Check1.getState();
Goban.Kinjite = Check2.getState();
}
return true;
}
void InitGame() {
Goban.Initialize(Computer);
Goban.Draw();
repaint();
GameState = GS_READY;
for(int i=0;i<2;i++)
Buttons[i].enable();
PutMessage("Click 'First' or 'Second' to start game.");
}
void StartGame(int FirstPlayer) {
if(GameState!=GS_READY)
return;
Player[BLACK] = FirstPlayer;
Player[WHITE] = (FirstPlayer==COMPUTER) ? HUMAN : COMPUTER;
CurrentPlayer = BLACK;
for(int i=0;i<2;i++)
Buttons[i].disable();
if(FirstPlayer==COMPUTER){
Goban.Area[7][7] = 1;
PlayComputer();
} else {
GameState = GS_PLAYUSER;
}
}
public boolean mouseDown(Event evt,int x,int y) {
if(GameState==GS_PLAYUSER && Player[CurrentPlayer]==HUMAN) {
GPos pos = new GPos();
if( !Goban.GetPos(x,y,pos) )
return true;
switch(Goban.Check(CurrentPlayer, pos.x, pos.y)) {
case CGoban.GC_OK:
CurrentPlayer = (CurrentPlayer == WHITE) ? BLACK : WHITE;
if(Player[CurrentPlayer] == COMPUTER){
GameState = GS_PLAYCOM;
}
break;
case CGoban.GC_ILLEGAL:
PutMessage("Illegal postion ! Can't put");
break;
case CGoban.GC_CANNOT:
PutMessage("Aleady exist! Can't put");
break;
case CGoban.GC_FILLED:
PutMessage("Board is filled ! Draw game.");
GameState = GS_END;
break;
case CGoban.GC_WIN:
PutMessage("You Win !!!");
GameState = GS_END;
break;
}
}
return true;
}
public boolean mouseUp(Event evt,int x,int y) {
if(GameState == GS_PLAYCOM){
PlayComputer();
}
return true;
}
void PlayComputer() {
GPos pos = new GPos();
PutMessage("Computer now thinking...");
switch(Computer.Think(CurrentPlayer,pos)) {
case CComputer.THINK_OK:
PutMessage("It's now your turn.");
CurrentPlayer = (CurrentPlayer == WHITE) ? BLACK : WHITE;
if(Player[CurrentPlayer] == COMPUTER){
PlayComputer();
} else {
GameState = GS_PLAYUSER;
}
break;
case CComputer.THINK_FILLED:
PutMessage("Board is filled ! Draw game.");
GameState = GS_END;
break;
case CComputer.THINK_WIN:
PutMessage("Computer Win !!!");
GameState = GS_END;
break;
}
}
public void PutMessage(String s) {
MessageLabel.setText(s);
}
public void paint(Graphics g) {
Goban.Draw();
}
}
Bây giờ, Build và chạy chương trình các bạn sẽ thấy giao diện như sau
Chúng ta có thể bắt đầu chơi, nếu muốn chơi lượt đầu thì bấm nút First, nếu muốn chơi sau thì nhấn Second
Bắt đầu chơi nhé
Chúc các bạn thành công
thanks anh nhưng anh mà giải thích chi tiết hơn thì tốt quá( nếu mỗi hàm, lớp giaiar thích tại sai lại sử dụng đấy)
Trả lờiXóatại sao anh tạo ra các nút trắng đen được vậy anh ?
Trả lờiXóaĐăng nhận xét