/*
项目名称:五子棋
*/
#include <stdio.h> //C语言标准库
#include <graphics.h>//图形库头文件
#include <string.h> //字符串头文件
#include <windows.h> //键盘热键判断头文件
void GameInit();
int playChess(void);
int JudgeWin(int a,int b);
int ContLimit(int n); //用来限制二维数组a,b的值 其范围在1 - 19
int flag = 0; //用来记录轮到哪个人下棋
int board[21][21] = {0}; //0表示没有下棋
int main()
{
int i = 0; //判断是否退出游戏标志
while(1) //当检测i不等于0时退出游戏
{
GameInit(); //五子棋游戏初始化
i = playChess(); //鼠标下棋
if(i==0) //判断是否继续游戏
{
continue;
}
cleardevice(); //清屏函数
}
getchar(); //防止闪退
return 0;
}
void GameInit()
{
//利用图形库创建一个窗口
initgraph(500,440);
//添加背景图片,引号前加L是因为要将格式改成多字节字符集
loadimage(NULL,L"Background1.jpg");
setlinecolor(BLACK); //将棋盘线条颜色改为黑色
setlinestyle(PS_SOLID,2);//将线条加粗
//绘制棋盘
line(21,21,21+399,21); //横轴
for(int i=1;i<=20;i++)
{
line(i*21,21,i*21,399+21); //纵轴
line(21,21+i*21,21+399,21+i*21); //横轴
}
settextcolor(BLACK); //将背景字体设置为黑色
setbkmode(0); //将背景字体设置透明
/*显示下棋方*/
outtextxy(435,50,L"玩家1:"); //图形库文字函数(x,y,"显示字符")
outtextxy(465,70,L"黑棋");
outtextxy(435,120,L"玩家2:");
outtextxy(465,140,L"白棋");
outtextxy(435,220,L"Esc:"); //
outtextxy(435,240,L"退出游戏"); //
}
int playChess(void) //鼠标下棋函数
{
//鼠标右键点击
MOUSEMSG Mouse; //鼠标结构体变量
/*a,b为二维数组号,x,y为当前鼠标点击的坐标*/
int a = 0;
int b = 0;
int x = 0;
int y = 0;
HWND hwnd; //窗口句柄
hwnd = GetHWnd();//窗口置前
int ret = 0; //判断游戏是否结束标志
int KeyRet = 0; //键盘判断是否退出游戏
int Key = 0; //用作键盘热键判断的变量
while(1)
{
Mouse = GetMouseMsg(); //获取一个鼠标消息
Key = GetAsyncKeyState(VK_ESCAPE);//获取Esc键状态,若按下返回-127或-128
if(Key<0) //判断获取键盘的信息,若键盘按下Esc,Key值小于0,则退出游戏
{
KeyRet = MessageBox(hwnd,L"是否想退出游戏?",L"提示",MB_YESNO|MB_ICONINFORMATION); //MB_YESNO显示选项,MB_ICONINFORMATION为提示字前方图标
if(KeyRet==IDYES) //判断是否想重新开始一局游戏
{
exit(0); //退出程序
}
}
//下棋时鼠标点击横纵轴交点,用绝对值将点击的x,y坐标值取整,使鼠标点击规定的棋盘位置(向右向下偏移1格)
for(int i = 1;i<21; i++)
{
for(int j = 1;j<21; j++)
{
if(abs(Mouse.x-i*21)<11&&abs(Mouse.y-j*21)<11) //将点击的范围内的值取整
{
a = i; //行列号
b = j;
x = i*21; //坐标
y = j*21;
}
}
}
if(Mouse.uMsg == WM_LBUTTONDOWN) //判断当前鼠标左键是否按下
{
if(board[a][b]!=0) //有棋子
{
MessageBox(hwnd,L"此处已有棋子,请重新选择下棋点",L"五子棋",MB_OK); //MB_OK为确定键
//退出循环
continue;
}
if(flag % 2==0) //取余
{
setfillcolor(BLACK); //棋子颜色设置黑色
solidcircle(x,y,10); //画黑色棋子
board[a][b] = 1; //给数组赋值黑棋色号
}
else
{
setfillcolor(WHITE); //棋子颜色设置白色
solidcircle(x,y,10); //画白色棋子
board[a][b] = 2; //给数组赋值白棋色号
}
flag++; //下棋手判断
if(flag>=400) //当棋盘下满时,平局。(0 - 399)
{
MessageBox(hwnd,L"本局平局",L"游戏结束",MB_OK); //MB_OK为确定键
if(ret==IDYES) //判断是否想重新开始一局游戏
{
flag = 0; //用来记录轮到哪个人下棋
memset(board,0,sizeof(board)); //清空数组
break;
}
else //不重新开始,退出程序
{
exit(0); //退出程序
}
}
}
if(JudgeWin(a,b)) //找到了五子连成一条线
{
if(flag % 2 ==1)
{
MessageBox(hwnd,L"玩家1(黑棋)胜利",L"游戏结束",MB_OK); //MB_OK为确定键
}
else
{
MessageBox(hwnd,L"玩家2(白棋)胜利",L"游戏结束",MB_OK); //MB_OK为确定键
}
ret = MessageBox(hwnd,L"是否想重新开始一局游戏?",L"提示",MB_YESNO|MB_ICONINFORMATION); //MB_YESNO显示选项,MB_ICONINFORMATION为提示字前方图标
if(ret==IDYES) //判断是否想重新开始一局游戏
{
flag = 0; //用来记录轮到哪个人下棋
memset(board,0,sizeof(board)); //清空数组
break;
}
else //不重新开始,退出程序
{
exit(0); //退出程序
}
}
}
return 0;
}
//判断输赢
int JudgeWin(int a,int b)
{
/*
算法逻辑:以当前下棋点为原点,
1.以x轴(a - 4) - (a + 4),开始检测连续点,若连续点>=5,则判定win
2.以y轴a不变,(b - 4) - (b + 4),开始检测连续点,若连续点>=5,则判定win
3.以y = x轴,(a - 4) - (a + 4),(b - 4) - (b + 4),开始检测连续点,若连续点>=5,则判定win
4.以y = -x轴,(a - 4) - (a + 4),(b + 4) - (b - 4),开始检测连续点,若连续点>=5,则判定win
*/
int i = 0;
int j = 0;
int Cont_i = 0; //连续棋子数
int t = 2 - flag % 2; //判定此次所下棋子色号
//x轴判断
for(i = ContLimit(a - 4);i <= ContLimit(a + 4);i++) //i值范围:(a - 4)至(a + 4)
{
j = b;
if(board[i][j] != t) //若不是当前下的棋子色号
{
Cont_i = 0; //连续棋子数清零
}
else if(board[i][j] == t) //若是当前下的棋子色号
{
Cont_i+=1;
}
if(Cont_i>=5) //若连续棋子数大于等于5
{
return 1; //返回1,判定胜利
}
}
Cont_i = 0; //x轴判定未胜利,连续棋子数清零,进行y轴判定
//y轴判断
for(j = ContLimit(b - 4);j <= ContLimit(b + 4);j++) //j值范围:(b - 4)至(b + 4)
{
i = a;
if(board[i][j] != t) //若不是当前下的棋子色号
{
Cont_i = 0; //连续棋子数清零
}
else if(board[i][j] == t) //若是当前下的棋子色号
{
Cont_i+=1;
}
if(Cont_i>=5) //若连续棋子数大于等于5
{
return 1; //返回1,判定胜利
}
}
Cont_i = 0; //x轴判定未胜利,连续棋子数清零,进行y轴判定
//y = x判断
for(i = ContLimit(a - 4),j = ContLimit(b - 4);i <= ContLimit(a + 4) && j <= (b + 4);i++,j++) //i值范围:(a - 4)至(a + 4),j值范围:(b - 4)至(b + 4)
{
//i = a;
if(board[i][j] != t) //若不是当前下的棋子色号
{
Cont_i = 0; //连续棋子数清零
}
else if(board[i][j] == t) //若是当前下的棋子色号
{
Cont_i+=1;
}
if(Cont_i>=5) //若连续棋子数大于等于5
{
return 1; //返回1,判定胜利
}
}
Cont_i = 0; //x轴判定未胜利,连续棋子数清零,进行y轴判定
//y = -x判断
for(i = ContLimit(a - 4),j = ContLimit(b + 4);i <= ContLimit(a + 4) && j >= ContLimit(b - 4);i++,j--) //i值范围:(a - 4)至(a + 4),j值范围:(b + 4)至(b - 4)
{
//i = a;
if(board[i][j] != t) //若不是当前下的棋子色号
{
Cont_i = 0; //连续棋子数清零
}
else if(board[i][j] == t) //若是当前下的棋子色号
{
Cont_i+=1;
}
if(Cont_i>=5) //若连续棋子数大于等于5
{
return 1; //返回1,判定胜利
}
}
return 0;
}
int ContLimit(int n) //用来限制二维数组a,b的值 其范围在1 - 20
{
if(n>20) //若输入数据大于20
{
return 20; //返回20
}
else if(n<0) //若输入数据小于0
{
return 0; //返回0
}
else //若不满足以上条件,返回原值
{
return n;
}
return n;
}
- 1
- 2
- 3
- 4
- 5
- 6
前往页