五子棋实现悔棋功能的代码(五子棋作弊)
C/C++五子棋问题,高手请指教
#include?Windows.h
#include?string
#include?list
using?namespace?std;
//函数声明
LRESULT?CALLBACK?WindowProcedure(HWND,UINT,WPARAM,LPARAM);
void?InitChess(); //初始化棋盘
void?ComputerMove(); //电脑落子
bool?CheckChess(); //检查棋盘是否有空余位置
bool?WinCheck(); //胜利检查
int?P(int); //返回某点棋子
int?P(int,?int); //返回某点棋子
int?P2I(int,int); //转换二维索引为一维索引
int?GetN(int?i,int?d); //获取一个棋子的某一个方向上的棋子坐标。
char?ge(int?a,int?p); //判断是己方棋子(1)还是障碍(2,对方棋子或棋盘外围)还是空位(0),a为待判断棋子,p为己方棋子。
int?CountV(int?i,?int?d,?int?pl); //计数一个落子处某个方向上的权重值。
int?GetBest(); //获取最佳落子点
//定义变量
char?szClassName[]?=?"CFive"; //Class?Name
int?chess[225]; //1为玩家棋子,-1为电脑棋子,0为空。
listint?fallen; //已落棋子,用于后期添加悔棋功能。
listint?r; //列表用于保存所有拥有相同最大权值的点用于随机抽取
listint::iterator?it; //迭代器
int?state?=?1; //表示当前状态,1:玩家下棋,2:电脑下棋,3:胜利,4:失败
//画刷
HBRUSH?hbr?=?CreateSolidBrush(0x0000ff); //红色画刷(标记上次落子)
HBRUSH?hbw?=?CreateSolidBrush(0xffffff); //白色画刷(画白棋)
HBRUSH?hbb?=?CreateSolidBrush(0x000000); //黑色画刷(画黑棋)
HPEN?hp?=?CreatePen(PS_SOLID,?1,?0x000000); //1宽度黑色画笔(画棋盘,棋子边框)
HPEN?hp2?=?CreatePen(PS_SOLID,?2,?0x000000); //2宽度黑色画笔(画棋盘边框)
//核心数据,影响整个AI判断
//棋型列表
string?cl[]?=?{"11111",?"011110",?"11110",?"11101",?"11011",?"011100",?"011010",?"11100",?"10110",?"11010",?"10101",?"001100",?"011000",?"010100",?"01100",?"010010",?"11000",?"10100"};
//电脑对应棋型的权重
int?cv[]?=?{1000000,?100000,?2500,?2800,?2600,?3100,?3000,?550,?800,?550,?570,?650,?600,?450,?300,?200,?120,?120};
//玩家对应棋型的权重
int?pv[]?=?{900000,?90000,?2500,?2450,?2600,?2850,?2800,?450,?700,?460,?490,?600,?500,?350,?200,?40,?40,?40};
int?WINAPI?WinMain(HINSTANCE?hThisInstance,
???HINSTANCE?hPrevInstance,
???LPSTR?lpszArgument,
???int?nFunsterStil)
{
HWND?hwnd; //窗口句柄
MSG?messages;
WNDCLASSEX?wincl;
wincl.hInstance?=?hThisInstance;
wincl.lpszClassName?=?szClassName;
wincl.lpfnWndProc?=?WindowProcedure;
wincl.style?=?CS_DBLCLKS;
wincl.cbSize?=?sizeof(WNDCLASSEX);
wincl.hIcon?=?LoadIcon(NULL,?IDI_APPLICATION);
wincl.hIconSm?=?LoadIcon(NULL,?IDI_APPLICATION);
wincl.hCursor?=?LoadCursor(NULL,?IDC_ARROW);
wincl.lpszMenuName?=?NULL;
wincl.cbClsExtra?=?0;
wincl.cbWndExtra?=?0;
wincl.hbrBackground?=??(HBRUSH)COLOR_BACKGROUND; //窗体背景色
InitChess(); //初始化棋盘
if(!RegisterClassEx(wincl))
return?-1; //注册失败
hwnd?=?CreateWindowEx(
0,
szClassName, //窗体类名
"五子棋", //窗体标题
WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX, //窗体样式
CW_USEDEFAULT, //左坐标
CW_USEDEFAULT, //顶坐标
340, //宽
360, //高
HWND_DESKTOP, //父窗体
NULL, //菜单
hThisInstance, //实例句柄
NULL
);
ShowWindow(hwnd,?nFunsterStil);
//消息循环
while(GetMessage(messages,NULL,0,0)){
TranslateMessage(messages);
DispatchMessage(messages);
}
return?messages.wParam;
}
LRESULT?CALLBACK?WindowProcedure(HWND?hwnd,?UINT?message,?WPARAM?wParam,?LPARAM?lParam)
{
HDC?hdc; //设备上下文句柄
PAINTSTRUCT?ps;
char?str[3]; //坐标轴上的文字
//x,y分别为相对棋盘的坐标
int?x?=?(LOWORD(lParam)-15)/20;
int?y?=?(HIWORD(lParam)-15)/20;
switch(message)
{
case?WM_DESTROY:
PostQuitMessage(0);
break;
case?WM_PAINT:
hdc?=?BeginPaint(hwnd,?ps);
SetBkMode(hdc,TRANSPARENT);
SelectObject(hdc,hp2);
MoveToEx(hdc,21,21,NULL);
LineTo(hdc,21,308);
LineTo(hdc,308,308);
LineTo(hdc,308,21);
LineTo(hdc,21,21); //棋盘边框
SelectObject(hdc,hp);
SelectObject(hdc,hbb);
Ellipse(hdc,82,82,87,87);
Ellipse(hdc,242,82,247,87);
Ellipse(hdc,242,242,247,247);
Ellipse(hdc,82,242,87,247);
Ellipse(hdc,162,162,167,167);
for(int?i=0;i15;i++){
str[0]=i+65;
TextOut(hdc,i*20+20,5,str,1); //画出字母序号
_ltoa_s(i+1,str,10);
TextOut(hdc,i=9?1:10,i*20+20,str,(i+1)/10+1); //画出数字序号
MoveToEx(hdc,24,i*20+24,NULL);
LineTo(hdc,304,i*20+24);
MoveToEx(hdc,i*20+24,24,NULL);
LineTo(hdc,i*20+24,304); //画出棋盘
}
for(int?i=0;i15;i++) //遍历棋盘,画出棋子
for(int?j=0;j15;j++){
switch(P(i,j)){
case?1: //黑棋
SelectObject(hdc,hbb);
Ellipse(hdc,i*20+15,j*20+15,i*20+18+15,j*20+18+15);
break;
case?-1: //白棋
SelectObject(hdc,hbw);
Ellipse(hdc,i*20+15,j*20+15,i*20+18+15,j*20+18+15);
break;
}
if(!fallen.empty()fallen.back()==P2I(i,j)){
SelectObject(hdc,hbr);
Ellipse(hdc,i*20+19,j*20+19,i*20+10+19,j*20+10+19);
}
}
SelectObject(hdc,CreateFont(30,0,0,0,FW_BLACK,false,false,false,GB2312_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FIXED_PITCH,"宋体"));
if(state2)TextOut(hdc,100,30,state==3?"玩家获胜!":"电脑获胜!",10);
SelectObject(hdc,CreateFont(20,0,0,0,FW_BLACK,false,false,false,GB2312_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FIXED_PITCH,"宋体"));
if(state2)TextOut(hdc,105,60,"单击以继续...",13);
EndPaint(hwnd,ps); //结束绘制
if(state==2){ //轮到电脑落子
ComputerMove();
state=WinCheck()?4:1; //更新状态
InvalidateRect(hwnd,NULL,true); //重绘窗体
}
break;
case?WM_LBUTTONUP:
switch(state){
case?3:
case?4:
state=1; //单击以继续
InitChess(); //初始化
InvalidateRect(hwnd,NULL,true); //重绘
break;
case?1:
if(x=0x15y=0y15P(x,y)==0){
chess[x*15+y]=1; //更改棋盘
fallen.push_back(x*15+y); //加入已落棋子列表
state=WinCheck()?3:2;
InvalidateRect(hwnd,NULL,true);
}
}
break;
default:
return?DefWindowProc(hwnd,?message,?wParam,?lParam); //默认消息处理
}
return?0;
}
//初始化棋盘
void?InitChess()
{
for(int?i=0;i225;i++)chess[i]=0; //全部棋子置空
fallen.clear(); //清空已落棋子列表
}
//电脑走棋
void?ComputerMove()
{
int?r=GetBest();
chess[r]=-1;
fallen.push_back(r);
}
//检查棋盘是否有空位
bool?CheckChess()
{
for(int?i=0;i15*15;i++)if(!chess[i])return?true;
return?false;
}
//转换二维索引为一维索引
int?P2I(int?x,int?y)
{
if(x0||y0||x14||y14)return?255;
return?x*15+y;
}
//获取整数的符号
int?sign(int?n)
{
return?n0?1:n0?-1:0;
}
//获取一个棋子的某一个方向上的棋子坐标。方向:1-右;2-右下;3-下;4-左下。其它方向负数。
int?GetN(int?i,int?d) //比如(3,4)的右边为(4,4),不过本函数以一维坐标表示
{
????int?x?=?i?/?15;
????int?y?=?i?%?15;
????switch(abs(d)){
case?1:
return?P2I(x?+?sign(d),?y);
case?2:
????????return?P2I(x?+?sign(d),?y?+?sign(d));
case?3:
????????return?P2I(x,?y?+?sign(d));
case?4:
????????return?P2I(x?-?sign(d),?y?+?sign(d));
default:
????????return?P2I(x,?y);
}
}
//返回某点棋子
int?P(int?x,?int?y)
{
if(x0||y0||x14||y14)
return?3;
else?if(x==-1||x==15||y==-1||y==15)
return?2;
else
return?chess[x*15+y];
}
//返回某点棋子
int?P(int?n)
{
return?P(n?/?15,?n?%?15);
}
//判断是己方棋子(1)还是障碍(2,对方棋子或棋盘外围)还是空位(0),a为待判断棋子,p为己方棋子。
char?ge(int?a,int?p)
{
if(a==p)
return?'1';
else?if(a==-p)
return?'2';
else
return?(char)(a+48);
}
//计数一个落子处某个方向上的权重值。
int?CountV(int?i,?int?d,?int?pl)
{
string?str=""; //用于保存棋型
int?tmp?=?i;
for(int?j=1;j5;j++){ //前4格
tmp=GetN(tmp,-d);
str=ge(P(tmp),pl)+str;
if(P(tmp)==2)break; //遇到阻挡的就退出循环
}
str?+=?'1'; //自身
for(int?j=1;j5;j++){ //后4格
i=GetN(i,d);
str?+=?ge(P(i),pl);
if(P(tmp)==2)break;
}
for(int?j=0;j18;j++) //挨个比较棋型,藉此获得权重值
if(str.find(cl[j])!=str.npos||str.find(string(cl[j].rbegin(),cl[j].rend()))!=str.npos)
return?pl==1?pv[j]:cv[j];
return?0;
}
//计算一个落子处的价值
int?GetValue(int?i)
{
int?n=0;
for(int?j=1;j5;j++){
n+=CountV(i,j,1); //对玩家的价值
n+=CountV(i,j,-1); //对电脑的价值
}
return?n;
}
//获取最优落子点
int?GetBest()
{
int?n=0,tmp; //n保存最大值,tmp临时变量
r.clear();
for(int?i=0;i225;i++){
if(P(i)==0){
tmp=GetValue(i);
if(tmpn){ //如果比已存的数大,就清空列表,并替换值
r.clear();
r.push_back(i);
n=tmp;
}else?if(tmp==n) //如果相等,就添加
r.push_back(i);
if(r.front()=1000000)?return?r.front(); //如果遇到连成5子的就直接选它了
}
}
it=r.begin();
tmp=rand()%r.size();
for(int?i=1;itmp;i++)it++;
return?*it; //随机从列表中返回一个位置
}
//计数一个棋子某个方向上的连子数。i,棋子坐标。d,方向。1-右;2-右下;3-下;4-左下。其它方向负数。
int?Count(int?i,int?d)
{
int?n=i;
int?c=0;
while(P(n)==P(i)){
n=GetN(n,d);
c++;
}
return?c-1;
}
//检查是否连成五子
bool?WinCheck()
{
int?i=fallen.back(); //检查最后一个落子的周围即可
for(int?j=1;j=4;j++) //依次判断4个方向
if(Count(i,j)+Count(i,-j)=4)
return?true;
return?false;
}
上面是完整代码,请参考。
用C++编写双人五子棋游戏时,如何才能做到悔棋的功能啊(可悔多步),用动态链可以实现么?求高人指点啊!
每下一步,放棋的位置全压栈,悔几步就弹出几下。动态链是可以实现的。
C++MFC五子棋悔棋的功能怎么做
提示:你的棋局记录方法必须能够追溯行棋过程,这样才能实现悔棋(倒退)
如果你的棋局记录方法是只记录棋子位置的话,是不能实现悔棋的。
求五子棋c或c++代码
五子棋C原码
/*turboc2.0下编译通过*/
#i nclude graphics.h
#i nclude stdlib.h
#i nclude stdio.h
#i nclude conio.h
#define N 15
#define B 7
#define STOP -10000
#define OK 1
#define NO 0
#define UP 328
#define DOWN 336
#define LEFT 331
#define RIGHT 333
/*定义了两个数,n为棋盘的大小。b为背景颜色的数值*/
int a[N+1][N+1];
int zx,zy;
int write=1,biaoji=0;
struct zn{
long sum;
int y;
int x;
}w[N+1][N+1],max,max1;
void cbar(int i,int x,int y,int r);
void map(int a[][]);
int getkey();
int key();
void zuobiao(int x,int y,int i);
int tu(int a[][],int write);
int wtu(int a[][],int write);
int zhineng(int a[][]);
int zh5(int y,int x,int a[][]);
long zzh5(int b[][],int i);
main()
{
int i,j;
int gdriver=DETECT;
int gmode;
initgraph(gdriver,gmode,"");
zx=(N+1)/2;
zy=(N+1)/2;
for(i=1;i=N;i++)
for(j=1;j=N;j++)
a[i][j]=0;
map(a);
i=1;
while(i)
{
int k,n;
k=wtu(a,write);
if(k==STOP) goto end;
map(a);
n=zhineng(a);
if(n==STOP) goto end;
map(a);
}
end:
;
}
/* 实现对局的程序 ,计算全部N*N个格中,最应该填的格子 */
int zhineng(int a[N+1][N+1])
{
int i,j;
int k;
max.sum=-1;
for(i=0;i=N;i++)
for(j=0;j+N;j++)
{
w[i][j].sum=0;
w[i][j].x=i;
w[i][j].y=j;
}
for(i=1;i=N-4;i++)
for(j=1;j=N-4;j++)
{
k=zh5(i,j,a);
if(k==STOP) return (STOP);
}
for(i=1;i=N;i++)
for(j=1;j=N;j++)
{
if(max.sumw[i][j].sum)
{
max.sum=w[i][j].sum;
max.y=i;
max.x=j;
}
else if(max.sum==w[i][j].sum)
{
if(((max.y-zy)*(max.y-zy)+(max.x-zx)*(max.x-zx))((i-zy)*(i-zy)+(j-zx)*(j-zx)))
max.sum=w[i][j].sum;
max.y=i;
max.x=j;
}
}
if(a[max.y][max.x]==0)
{
a[max.y][max.x]=-1;
zy=max.y;
zx=max.x;
}
}
/* 转换成5*5的数组,计算出在二十五个格子中,最应该填的格 */
int zh5(int y,int x,int a[N+1][N+1])
{
int i,j;
int b[6][6];
long c[13];
long d[6][6];
long temp;
for(i=y;i=y+4;i++)
for(j=x;j=x+4;j++)
b[i+1-y][j+1-x]=a[i][j];
c[1]=b[1][1]+b[1][2]+b[1][3]+b[1][4]+b[1][5];
c[2]=b[2][1]+b[2][2]+b[2][3]+b[2][4]+b[2][5];
c[3]=b[3][1]+b[3][2]+b[3][3]+b[3][4]+b[3][5];
c[4]=b[4][1]+b[4][2]+b[4][3]+b[4][4]+b[4][5];
c[5]=b[5][1]+b[5][2]+b[5][3]+b[5][4]+b[5][5];
c[6]=b[1][1]+b[2][1]+b[3][1]+b[4][1]+b[5][1];
c[7]=b[1][2]+b[2][2]+b[3][2]+b[4][2]+b[5][2];
c[8]=b[1][3]+b[2][3]+b[3][3]+b[4][3]+b[5][3];
c[9]=b[1][4]+b[2][4]+b[3][4]+b[4][4]+b[5][4];
c[10]=b[1][5]+b[2][5]+b[3][5]+b[4][5]+b[5][5];
c[11]=b[1][1]+b[2][2]+b[3][3]+b[4][4]+b[5][5];
c[12]=b[1][5]+b[2][4]+b[3][3]+b[4][2]+b[5][1];
for(i=1;i=12;i++)
{
switch(c[i])
{
case 5:biaoji=1;return(STOP);
case -5:biaoji=-1;return(STOP);
case -4:c[i]=100000;break;
case 4:c[i]=100000;break;
case -3:c[i]=150;break;
case 3:c[i]=150;break;
case -2:c[i]=120;break;
case 2:c[i]=100;break;
case -1:c[i]=1;break;
case 1:c[i]=1;break;
default: c[i]=0;
}
}
for(i=1;i=12;i++)
{
if(c[i]==150)
c[i]+=zzh5(b,i);
}
for(i=1;i=5;i++)
for(j=1;j=5;j++)
d[i][j]=0;
for(i=1;i=5;i++)
for(j=1;j=5;j++)
{
if(i==j) d[i][j]+=c[11];
if((i+j)==6) d[i][j]+=c[12];
d[i][j]+=c[i]+c[j+5];
}
for(i=1;i=5;i++)
for(j=1;j=5;j++)
{
if(b[i][j]!=0)
d[i][j]=-2;
}
max1.sum=-1;
max1.y=0;
max1.x=0;
for(i=1;i=5;i++)
for(j=1;j=5;j++)
{
if(max1.sumd[i][j])
{
max1.sum=d[i][j];
max1.y=i;
max1.x=j;
w[i+y-1][j+x-1].sum+=max1.sum;
}
else if(max1.sum==d[i][j])
{
if(((i+y-1-zy)*(i+y-1-zy)+(j+x-1-zx)*(j+x-1-zx))((max1.y+y-1-zy)*(max1.y+y-1-zy)+(max1.x+x-1-zx)*(max1.x+x-1-zx)))
{
max1.sum=d[i][j];
max1.y=i;
max1.x=j;
}
}
}
}
long zzh5(int b[6][6],int n)
{
int i,j,k,l,m;
switch(n)
{
case 1:i=b[1][1];j=b[1][2];k=b[1][3];l=b[1][4];m=b[1][5];break;
case 2:i=b[2][1];j=b[2][2];k=b[2][3];l=b[2][4];m=b[2][5];break;
case 3:i=b[3][1];j=b[3][2];k=b[3][3];l=b[3][4];m=b[3][5];break;
case 4:i=b[4][1];j=b[4][2];k=b[4][3];l=b[4][4];m=b[4][5];break;
case 5:i=b[5][1];j=b[5][2];k=b[5][3];l=b[5][4];m=b[5][5];break;
case 6:i=b[1][1];j=b[2][1];k=b[3][1];l=b[4][1];m=b[5][1];break;
case 7:i=b[1][2];j=b[2][2];k=b[3][2];l=b[4][2];m=b[5][2];break;
case 8:i=b[1][3];j=b[2][3];k=b[3][3];l=b[4][3];m=b[5][3];break;
case 9:i=b[1][4];j=b[2][4];k=b[3][4];l=b[4][4];m=b[5][4];break;
case 10:i=b[1][5];j=b[2][5];k=b[3][5];l=b[4][5];m=b[5][5];break;
case 11:i=b[1][1];j=b[2][2];k=b[3][3];l=b[4][4];m=b[5][5];break;
case 12:i=b[1][5];j=b[2][4];k=b[3][3];l=b[4][2];m=b[5][1];break;
}
if((i==0j==1k==1l==1m==0))
return (900);
if((i==0j==-1k==-1l==-1m==0))
return(1000);
if((i==0j==0k==1l==1m==1)||(i==1j==1k==1l==0m==0))
return(20);
if((i==0j==0k==-1l==-1m==-1)||(i==-1j==-1k==-1l==0m==0))
return(20);
if((i==-1j==1k==1l==1m==1)||(i==1j==-1k==1l==1m==1)||(i==1j==1k==-1l==1m==1)||(i==1j==1k==1l==-1m==1)||(i==1j==1k==1l==1m==-1))
return(-60);
if((i==1j==-1k==-1l==-1m==-1)||(i==-1j==1k==-1l==-1m==-1)||(i==-1j==1k==-1l==-1m==-1)||(i==-1j==-1k==-1l==1m==-1)||(i==-1j==-1k==-1l==-1m==1))
return(-60);
}
/* 循环执行坐标的选择,直到按回车,空格或ESC键 */
int wtu(int a[N+1][N+1],int write)
{
int i=1;
map(a);
zuobiao(zx,zy,1);
while(i)
{
int k;
k=tu(a,write);
if(k==OK) i=0;
if(k==STOP) return (STOP);
}
}
/*从键盘获得输入的值*/
int getkey()
{
int key,lo,hi;
key=bioskey(0);
lo=key0x00ff;
hi=(key0xff00)8;
return((lo==0) ? hi+256:lo);
}
/*对获得的值进行判断*/
/*对应的码值分别如下*/
/* 上:328 下:336 左: 331 右: 333 */
/* 回车:13 ESC键: 27 */
int key()
{
int k;
k=getkey();
switch(k)
{
case 27: return (STOP);
case 13:
case ' ': return (OK);
case 328: return (UP);
case 336: return (DOWN);
case 331: return (LEFT);
case 333: return (RIGHT);
default: return (NO);
}
}
/*用来显示坐标的位置*/
void zuobiao(int x,int y,int i)
{
int r;
if(i!=0)
{
setcolor(GREEN);
for(r=1;r=5;r++)
circle(75+25*x,25+25*y,r);
}
else
{
if(a[zy][zx]==1)
{
setcolor(8);
for(r=1;r=5;r++)
circle(75+25*x,25+25*y,r);
}
else if(a[zy][zx]==-1)
{
setcolor(WHITE);
for(r=1;r=5;r++)
circle(75+25*x,25+25*y,r);
}
else
{
setcolor(B);
for(r=1;r=5;r++)
circle(75+25*x,25+25*y,r);
setcolor(RED); line(75+25*zx-5,25+25*zy,75+25*x+5,25+25*zy);
line(75+25*zx,25+25*zy-5,75+25*zx,25+25*zy+5);
}
}
}
/*从键盘获得的值进行判断,反映在显示的图上*/
int tu(int a[N+1][N+1],int write)
{
int k;
re:
k=key();
if(k==OK)
{
if(a[zy][zx]==0)
{
a[zy][zx]=write;
}
else
goto re;
}
if(k==STOP) return(STOP);
if(k==NO) goto re;
if(k==UP)
{
int i,j;
if(zy==1) j=zy;
else j=zy-1;
zuobiao(zx,zy,0);
zuobiao(zx,j,1);
zy=j;
goto re;
}
if(k==DOWN)
{
int i,j;
if(zy==N) j=zy;
else j=zy+1;
zuobiao(zx,zy,0);
zuobiao(zx,j,1);
zy=j;
goto re;
}
if(k==LEFT)
{
int i,j;
if(zx==1) i=zx;
else i=zx-1;
zuobiao(zx,zy,0);
zuobiao(i,zy,1);
zx=i;
goto re;
}
if(k==RIGHT)
{
int i,j;
if(zx==N) i=zx;
else i=zx+1;
zuobiao(zx,zy,0);
zuobiao(i,zy,1);
zx=i;
goto re;
}
}
/* 根据数组中(存储棋子位置)各位置的数,画实心圆(画出棋子)*/
void cbar(int i,int x,int y,int r)
{
if(i!=0)
{
if(i==1)
setcolor(8);
else if(i==-1)
setcolor(WHITE);
for(i=1;i=r;i++)
{
circle(x,y,i);
}
}
}
/*画出棋盘,和各个棋子*/
void map(int a[N+1][N+1])
{
int i,j;
cleardevice();
setbkcolor(B);
setcolor(RED);
for(i=0;iN;i++)
{
line(100,50+25*i,75+N*25,50+25*i);
line(100+25*i,50,100+25*i,25+N*25);
}
for(i=1;i=N;i++)
for(j=1;j=N;j++)
cbar(a[i][j],75+25*j,25+25*i,10);
}
在线等!求一个python 五子棋源代码,最好是有“人人对弈”和“人机对弈”功能的,不胜感谢!
试试这个吧。
import numpy as np
import pygame
import sys
import traceback
import copy
from pygame.locals import *
pygame.init()
pygame.mixer.init()
#颜色
background=(201,202,187)
checkerboard=(80,80,80)
button=(52,53,44)
#音乐
play_chess_sound = pygame.mixer.Sound("music/play_chess.wav")
play_chess_sound.set_volume(0.2)
button_sound = pygame.mixer.Sound("music/button.wav")
button_sound.set_volume(0.2)
victor_sound = pygame.mixer.Sound("music/victory.wav")
victor_sound.set_volume(0.2)
#绘制棋盘
def Draw_a_chessboard(screen):
#填充背景色
screen.fill(background)
Background=pygame.image.load("background.jpg").convert_alpha()
screen.blit(Background,(0,0))
#画棋盘
for i in range(21):
pygame.draw.line(screen, checkerboard, (40*i+3, 3), (40*i+3, 803))
pygame.draw.line(screen, checkerboard, (3, 40*i+3), (803, 40*i+3))
#画边线
pygame.draw.line(screen, checkerboard, (3, 3), (803, 3),5)
pygame.draw.line(screen, checkerboard, (3, 3), (3, 803),5)
pygame.draw.line(screen, checkerboard, (803, 3), (803, 803),5)
pygame.draw.line(screen, checkerboard, (3, 803), (803, 803),5)
#画定位点
pygame.draw.circle(screen, checkerboard, (163, 163), 6)
pygame.draw.circle(screen, checkerboard, (163, 643), 6)
pygame.draw.circle(screen, checkerboard, (643, 163), 6)
pygame.draw.circle(screen, checkerboard, (643, 643), 6)
pygame.draw.circle(screen, checkerboard, (403, 403), 6)
#画‘悔棋’‘重新开始’跟‘退出’按钮
pygame.draw.rect(screen,button,[900,350,120,100],5)
pygame.draw.rect(screen,button,[900,500,200,100],5)
pygame.draw.rect(screen,button,[900,650,200,100],5)
s_font=pygame.font.Font('font.ttf',40)
text1=s_font.render("悔棋",True,button)
text2=s_font.render("重新开始",True,button)
text3=s_font.render("退出游戏",True,button)
screen.blit(text1,(920,370))
screen.blit(text2,(920,520))
screen.blit(text3,(920,670))
#绘制棋子(横坐标,纵坐标,屏幕,棋子颜色(1代表黑,2代表白))
def Draw_a_chessman(x,y,screen,color):
if color==1:
Black_chess=pygame.image.load("Black_chess.png").convert_alpha()
screen.blit(Black_chess,(40*x+3-15,40*y+3-15))
if color==2:
White_chess=pygame.image.load("White_chess.png").convert_alpha()
screen.blit(White_chess,(40*x+3-15,40*y+3-15))
#绘制带有棋子的棋盘
def Draw_a_chessboard_with_chessman(map,screen):
screen.fill(background)
Draw_a_chessboard(screen)
for i in range(24):
for j in range(24):
Draw_a_chessman(i+1,j+1,screen,map[i][j])
#定义存储棋盘的列表,
#列表为24列24行是因为判断是否胜利函数里的索引会超出19
#列表大一点不会对游戏有什么影响
map=[]
for i in range(24):
map.append([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
#清零map列表
def clear():
global map
for i in range(24):
for j in range(24):
map[i][j]=0
#判断是否胜利
def win(i, j):
k = map[i][j]
p=[]
for a in range(20):
p.append(0)
for i3 in range(i-4,i+5):
for j3 in range(j-4,j+5):
if (map[i3][j3] == k and i3 - i == j3 - j and i3 = i and j3 = j):
p[0]+=1
if (map[i3][j3] == k and j3 == j and i3 = i and j3 = j):
p[1]+=1
if (map[i3][j3] == k and i3 == i and i3 = i and j3 = j):
p[2]+=1
if (map[i3][j3] == k and i3 - i == j3 - j and i3 = i and j3 = j):
p[3]+=1
if (map[i3][j3] == k and j3 == j and i3 = i and j3 = j):
p[4]+=1
if (map[i3][j3] == k and i3 == i and i3 = i and j3 = j):
p[5]+=1
if (map[i3][j3] == k and i - i3 == j3 - j and i3 = i and j3 = j):
p[6]+=1
if (map[i3][j3] == k and i3 - i == j - j3 and i3 = i and j3 = j):
p[7]+=1
if (map[i3][j3] == k and j - j3 == i - i3 and i3 = i + 1 and i3 = i - 3 and j3 = j + 1 and j3 = j - 3):
p[8]+=1
if (map[i3][j3] == k and j == j3 and i3 = i + 1 and i3 = i - 3 and j3 = j + 1 and j3 = j - 3):
p[9]+=1
if (map[i3][j3] == k and i == i3 and i3 = i + 1 and i3 = i - 3 and j3 = j + 1 and j3 = j - 3):
p[10]+=1
if (map[i3][j3] == k and j - j3 == i - i3 and i3 = i - 1 and i3 = i + 3 and j3 = j - 1 and j3 = j + 3):
p[11]+=1
if (map[i3][j3] == k and j == j3 and i3 = i - 1 and i3 = i + 3 and j3 = j - 1 and j3 = j + 3):
p[12]+=1
if (map[i3][j3] == k and i == i3 and i3 = i - 1 and i3 = i + 3 and j3 = j - 1 and j3 = j + 3):
p[13]+=1
if (map[i3][j3] == k and i - i3 == j3 - j and i3 = i + 1 and i3 = i - 3 and j3 = j - 1 and j3 = j + 3):
p[14]+=1
if (map[i3][j3] == k and i3 - i == j - j3 and i3 = i - 1 and i3 = i + 3 and j3 = j + 1 and j3 = j - 3):
p[15]+=1
if (map[i3][j3] == k and j - j3 == i - i3 and i3 = i + 2 and i3 = i - 2 and j3 = j + 2 and j3 = j - 2):
p[16]+=1
if (map[i3][j3] == k and j == j3 and i3 = i + 2 and i3 = i - 2 and j3 = j + 2 and j3 = j - 2):
p[17]+=1
if (map[i3][j3] == k and i == i3 and i3 = i + 2 and i3 = i - 2 and j3 = j + 2 and j3 = j - 2):
p[18]+=1
if (map[i3][j3] == k and i - i3 == j3 - j and i3 = i + 2 and i3 = i - 2 and j3 = j + 2 and j3 = j - 2):
p[19]+=1
for b in range(20):
if p[b]==5:
return True
return False
#绘制提示器(类容,屏幕,字大小)
def text(s,screen,x):
#先把上一次的类容用一个矩形覆盖
pygame.draw.rect(screen,background,[850,100,1200,100])
#定义字体跟大小
s_font=pygame.font.Font('font.ttf',x)
#定义类容,是否抗锯齿,颜色
s_text=s_font.render(s,True,button)
#将字放在窗口指定位置
screen.blit(s_text,(880,100))
pygame.display.flip()
#用于控制顺序
t=True
#用于结束游戏后阻止落子
running=True
#主函数
def main():
#将 t,map,running设置为可改的
global t,map,running,maps,r,h
#将map置零
clear()
#定义储存所有棋盘状态的列表(用于悔棋)
map2=copy.deepcopy(map)
maps=[map2]
#定义窗口
screen = pygame.display.set_mode([1200,806])
#定义窗口名字
pygame.display.set_caption("五子棋")
#在窗口画出棋盘,提示器以及按钮
Draw_a_chessboard(screen)
pygame.display.flip()
clock=pygame.time.Clock()
while True:
#只有running为真才能落子,主要用于游戏结束后防止再次落子
if running:
if t:
color=1
text('黑棋落子',screen,54)
else:
color=2
text('白棋落子',screen,54)
for event in pygame.event.get():
#点击x则关闭窗口
if event.type ==pygame.QUIT:
pygame.quit()
sys.exit()
#点击窗口里面类容则完成相应指令
elif event.type == MOUSEBUTTONDOWN:
if event.button == 1:
x,y=event.pos[0],event.pos[1]
for i in range(19):
for j in range(19):
#点击棋盘相应位置
if i*40+3+20xi*40+3+60 and j*40+3+20yj*40+3+60 and not map[i][j] and running:
#在棋盘相应位置落相应颜色棋子
Draw_a_chessman(i+1,j+1,screen,color)
#播放音效
play_chess_sound.play(0)
#在map里面记录落子位置
map[i][j]=color
#将map存入maps
map3=copy.deepcopy(map)
maps.append(map3)
#判断落子后是否有五子一线
if win(i,j):
if t:
text('黑棋胜利,请重新游戏',screen,30)
else:
text('白棋胜利,请重新游戏',screen,30)
#播放音效
victor_sound.play(0)
#阻止再往棋盘落子
running=False
pygame.display.flip()
t=not t
#如果点击‘重新开始’
if 900x1100 and 500y600:
#取消阻止
running=True
#播放音效
button_sound.play(0)
#重新开始
main()
#点击‘退出游戏’,退出游戏
elif 900x1100 and 650y750:
#播放音效
button_sound.play(0)
pygame.quit()
sys.exit()
#点击‘悔棋’
elif 900x1020 and 350y450 and len(maps)!=1:
#播放音效
button_sound.play(0)
#删除maps里最后一个元素
del maps[len(maps)-1]
#再将最后一个元素copy给map
map=copy.deepcopy(maps[len(maps)-1])
#切换顺序
t=not t
#将map显示出来
Draw_a_chessboard_with_chessman(map,screen)
#悔棋完成,阻止再次悔棋
x,y=0,0
clock.tick(60)
if __name__ == "__main__":
try:
main()
except SystemExit:
pass
except:
traceback.print_exc()
pygame.quit()
input()