C语言五子棋人机对战——Windows下基于EasyX且支持键盘操作有人人对战与人机对战模式
程序员文章站
2024-03-18 16:43:46
...
一、游戏窗口
PS:此游戏为c语言开发,因EasyX库需要.cpp文件才能编译,所以工程文件后缀为.cpp,并未使用cpp的语法。
VS2013工程百度云链接:
链接:https://pan.baidu.com/s/1MQClKFwONyLk0UW1yUE2QQ
提取码:qn9c
1.1选择游戏模式窗口图形
1.2游戏窗口图形
二、游戏源码
将chess.cpp、chess.h文件添加到工程里
2.1 chess.cpp
#include "chess.h"
#define width 560 //240
#define heigth 560 //320
#define p1 1 //玩家1
#define p2 2 //玩家2
#define Nochess 0 //空棋
#define N 15 //棋盘格数
#define Grid_wid (width/(N-1)) //网格宽度
#define Chess_R Grid_wid/2 //棋子半径
#define player_player 3 //人人
#define player_AI 4 //人机
int player = p1; //默认黑棋先手
int chess[N][N]; //棋盘地图
int chess_num; //总棋子数
char param = 0;
void Oninit()
{
setfillcolor(BLACK);
player = p1; //默认黑棋先手
for (int i = 0; i < N;i++)//棋盘清零
{
for (int j = 0; j < N; j++)
{
chess[i][j] = Nochess;
}
}
chess_num = 0; //总棋子数清零
}
int judge(int x, int y)
{
return chess[x][y] ? 0 : 1;
}
int judge_win(int x, int y)
{
int i, j, k;
const int step[4][2] = { { 1, 0 }, { 0, 1 }, { 1, 1 }, { 1, -1 } };
for (i = 0; i < 4; ++i)
{
const int d[2] = { -1, 1 };
int count = 1;
for (j = 0; j < 2; ++j)
for (k = 1; k <= 4; ++k){
int row = x + k*d[j] * step[i][0];
int col = y + k*d[j] * step[i][1];
if (row >= 1 && row <= N &&
col >= 1 && col <= N &&
chess[x][y] == chess[row][col])
count += 1;
else
break;
}
if (count >= 5)
return 1;
}
if (chess_num == N*N)
Msg_restart(2);
return 0;
}
int Chess_piece(int x1, int y1)//落子
{
if (x1 == -1 || y1 == -1)
{
return 0;
}
if (player == p1)
setfillcolor(BLACK);
else
setfillcolor(WHITE);
if (judge(x1, y1))
{
solidcircle(x1*Grid_wid, y1*Grid_wid, Chess_R);
chess[x1][y1] = player;
chess_num++;
if (judge_win(x1, y1))
{
Msg_restart(1);
}
changeplayer();
return 1;
}
return 0;
}
int mod_xy(int xy)
{
int res = (int)((double)xy / Grid_wid + 0.5);
if (res < N && res >= 0)
{
return res;
}
else
{
return -1;
}
}
void changeplayer()//玩家交换
{
player = p1 + p2 - player;
if (player == p1)
setfillcolor(BLACK);
else
setfillcolor(WHITE);
}
void draw_checkboard()
{
setlinecolor(BLACK);
int i;
for (i = 0; i < N; i++)//画地图
{
line(1 + i*Grid_wid, 1, 1 + i*Grid_wid, Grid_wid * (N - 1));
line(1, 1 + i*Grid_wid, Grid_wid * (N - 1), 1 + i*Grid_wid);
}
}
int scorejudge(int row,int col)
{
if ((row >= 0 && row < N) && (col >= 0 && col < N))
{
return 1;
}
else
{
return 0;
}
}
int chessscore(int x, int y, int worb) //棋盘权值函数
{
int sumscore = 0;
char u, d, l, r, lu, ld, ru, rd;//u上 d下 l左 r右 lu左上 ld左下 ru右上 rd右下
int row, col, count1, count2, count3, count4; //1横 2竖 3斜上 4斜下
count1 = count2 = count3 = count4 = 1;
l = r = u = d = lu = ld = ru = rd = 0;
chess[x][y] = worb; //模拟下棋
//横向
row = x, col = y + 1;
while (chess[row][col] == worb && scorejudge(row,col))
{
count1++;
col++;
}
while (chess[row][col] == 0 && scorejudge(row, col))
{
r++;
col++;
}
row = x, col = y - 1;
while (chess[row][col] == worb && scorejudge(row, col))
{
count1++;
col--;
}
while (chess[row][col] == 0 && scorejudge(row, col))
{
l++;
col--;
}
//竖向
row = x + 1, col = y;
while (chess[row][col] == worb && scorejudge(row, col))
{
count2++;
row++;
}
while (chess[row][col] == 0 && scorejudge(row, col))
{
d++;
row++;
}
row = x - 1, col = y;
while (chess[row][col] == worb && scorejudge(row, col))
{
count2++;
row--;
}
while (chess[row][col] == 0 && scorejudge(row, col))
{
u++;
row--;
}
//斜上
row = x - 1, col = y + 1;
while (chess[row][col] == worb && scorejudge(row, col))
{
count3++;
col++;
row--;
}
while (chess[row][col] == 0 && scorejudge(row, col))
{
ru++;
col++;
row--;
}
row = x + 1, col = y - 1;
while (chess[row][col] == worb && scorejudge(row, col))
{
count3++;
col--;
row++;
}
while (chess[row][col] == 0 && scorejudge(row, col))
{
ld++;
col--;
row++;
}
//斜下
row = x + 1, col = y + 1;
while (chess[row][col] == worb && scorejudge(row, col))
{
count4++;
col++;
row++;
}
while (chess[row][col] == 0 && scorejudge(row, col))
{
rd++;
col++;
row++;
}
row = x - 1, col = y - 1;
while (chess[row][col] == worb && scorejudge(row, col))
{
count4++;
col--;
row--;
}
while (chess[row][col] == 0 && scorejudge(row, col))
{
lu++;
col--;
row--;
}
chess[x][y] = Nochess;
if (count1 >= 5 || count2 >= 5 || count3 >= 5 || count4 >= 5)//成五
{
return sumscore = 5000000;
}
if ((count1 == 4 && count2 == 4 && l >= 1 && r >= 1 && u >= 1 && d >= 1) ||
(count1 == 4 && count3 == 4 && l >= 1 && r >= 1 && ru >= 1 && ld >= 1) ||
(count1 == 4 && count4 == 4 && l >= 1 && r >= 1 && rd >= 1 && lu >= 1) ||
(count2 == 4 && count3 == 4 && u >= 1 && d >= 1 && ru >= 1 && ld >= 1) ||
(count2 == 4 && count4 == 4 && u >= 1 && d >= 1 && lu >= 1 && rd >= 1) ||
(count3 == 4 && count4 == 4 && ru >= 1 && ld >= 1 && lu >= 1 && rd >= 1))
//双活四
{
return sumscore = 4000000;
}
if ((count1 == 4 && l >= 1 && r >= 1) || (count2 == 4 && u >= 1 && d >= 1) ||
(count3 == 4 && ru >= 1 && ld >= 1) || (count4 == 4 && lu >= 1 && rd >= 1))
//活四
{
return sumscore = 800000;
}
if ((count1 == 4 && ((l == 0 && r >= 1) || (l >= 1 && r == 0)))
|| (count2 == 4 && ((u == 0 && d >= 1) || (u >= 1 && d == 0)))
||(count3 == 4 && ((ld == 0 && ru >= 1) || (ld >= 1 && ru == 0)))
|| (count4 == 4 && ((lu == 0 && rd >= 1) || (lu >= 1 && rd == 0))))
{
sumscore = sumscore + 35000; //成四
}
if ((count1 == 3 && count2 == 3 && l >= 1 && r >= 1 && u >= 1 && d >= 1) ||
(count1 == 3 && count3 == 3 && l >= 1 && r >= 1 && ru >= 1 && ld >= 1) ||
(count1 == 3 && count4 == 3 && l >= 1 && r >= 1 && rd >= 1 && lu >= 1) ||
(count2 == 3 && count3 == 3 && u >= 1 && d >= 1 && ru >= 1 && ld >= 1) ||
(count2 == 3 && count4 == 3 && u >= 1 && d >= 1 && lu >= 1 && rd >= 1) ||
(count3 == 3 && count4 == 3 && ru >= 1 && ld >= 1 && lu >= 1 && rd >= 1))
//双活三
{
return sumscore + 400000;
}
if ((count1 == 3 && l >= 1 && r >= 1) || (count2 == 3 && u >= 1 && d >= 1) ||
(count3 == 3 && ru >= 1 && ld >= 1) || (count4 == 3 && lu >= 1 && rd >= 1))
//活三
{
sumscore = sumscore + 60000;
return sumscore;
}
if ((count1 == 2 && count2 == 2 && l >= 1 && r >= 1 && u >= 1 && d >= 1) ||
(count1 == 2 && count3 == 2 && l >= 1 && r >= 1 && ru >= 1 && ld >= 1) ||
(count1 == 2 && count4 == 2 && l >= 1 && r >= 1 && rd >= 1 && lu >= 1) ||
(count2 == 2 && count3 == 2 && u >= 1 && d >= 1 && ru >= 1 && ld >= 1) ||
(count2 == 2 && count4 == 2 && u >= 1 && d >= 1 && lu >= 1 && rd >= 1) ||
(count3 == 2 && count4 == 2 && ru >= 1 && ld >= 1 && lu >= 1 && rd >= 1))
//双活二
{
sumscore = sumscore + 20000;
}
if ((count1 == 2 && l >= 1 && r >= 1) || (count2 == 2 && u >= 1 && d >= 1) ||
(count3 == 2 && ru >= 1 && ld >= 1) || (count4 == 2 && lu >= 1 && rd >= 1))
//单活二
{
sumscore = sumscore + 10000;
}
if ((count1 == 3 && ((l == 0 && r >= 1) || (l >= 1 && r == 0)))
|| (count2 == 3 && ((u == 0 && d >= 1) || (u >= 1 && d == 0)))
|| (count3 == 3 && ((ld == 0 && ru >= 1) || (ld >= 1 && ru == 0)))
|| (count4 == 3 && ((lu == 0 && rd >= 1) || (lu >= 1 && rd == 0))))
{
sumscore = sumscore + 5000; //成三
}
return sumscore;
}
void Msg_restart(int par)
{
int res;
if (par == 1)
{
if (player == p1)
{
res = MessageBoxA(0, "黑棋胜,是否重开?", "五子棋", MB_YESNO | MB_SYSTEMMODAL);
if (res == IDYES)
restart();
else
exitgame();
}
else
{
res = MessageBoxA(0, "白棋胜,是否重开?", "五子棋", MB_YESNO | MB_SYSTEMMODAL);
if (res == IDYES)
restart();
else
exitgame();
}
}
else
{
res = MessageBoxA(0, "平局,是否重开?", "五子棋", MB_YESNO | MB_SYSTEMMODAL);
if (res == IDYES)
restart();
else
exitgame();
}
}
void chesscomputer()
{
int i, j, cscore, cscorel, pscore, pscorel, row1, col1, row2, col2;
cscore = pscore = 0; row1 = row2 = col1 = col2 = -1;
//寻找最优落子位置
if (chess_num <= 1)
{
srand((unsigned)time(NULL));
do
{
row1 = rand() % 2 + 6;
col1 = rand() % 2 + 6;
} while (!judge(row1, col1));
Chess_piece(row1, col1);
}
else
{
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
{
if (judge(i, j))
{
cscorel = chessscore(i, j, p1);
if (cscorel > cscore)
{
cscore = cscorel;
row1 = i;
col1 = j;
}
pscorel = chessscore(i, j, p2);
if (pscorel > pscore)
{
pscore = pscorel;
row2 = i;
col2 = j;
}
}
}
}
if (row1 == -1 && col1 == -1 && row2 == -1 && col2 == -1)//没找到最优解 平局
{
Msg_restart(2);
}
else
{
if (chess_num == 3)
{
Chess_piece(row2, col2);
}
else
{
if (cscore > pscore)
{
Chess_piece(row1, col1);
}
else
{
Chess_piece(row2, col2);
}
}
}
}
}
void Mouse()//鼠标移动
{
if (param == player_player)
{
if (MouseHit())
{
MOUSEMSG msg = GetMouseMsg();
switch (msg.uMsg)
{
case WM_LBUTTONDOWN://左键按下
int x1 = mod_xy(msg.x);
int y1 = mod_xy(msg.y);
Chess_piece(x1, y1);
break;
}
}
}
else
{
if (MouseHit())
{
MOUSEMSG msg = GetMouseMsg();
switch (msg.uMsg)
{
case WM_LBUTTONDOWN://左键按下
int x1 = mod_xy(msg.x);
int y1 = mod_xy(msg.y);
if (Chess_piece(x1, y1))
{
chesscomputer();
}
break;
}
}
}
}
void Start_Game()
{
initgraph(width, heigth);//初始化窗口
setbkcolor(RGB(249,214,91));//设置背景色
cleardevice();
draw_checkboard();
Oninit();
int res = MessageBoxA(0, "人机模式", "模式", MB_YESNO | MB_SYSTEMMODAL);
if (res==IDYES)
{
param = player_AI;
}
else
{
param = player_player;
}
}
void restart()
{
Oninit();
cleardevice();
draw_checkboard();
while (1)
{
//chesscomputer();
Mouse();
}
}
void exitgame()
{
closegraph();
exit(0);
}
void main()
{
Start_Game();
while (1)
{
Mouse();
}
}
2.2 chess.h
#include <stdio.h>
#include <conio.h>
#include <time.h>
#include <Windows.h>
#include <graphics.h>
int judge(int x, int y);
int judge_win(int x, int y);
int Chess_piece(int x, int y);
int mod_xy(int xy);
void changeplayer();
void draw_checkboard();
int chessscore(int x, int y, int worb);
void chesscomputer();
void Mouse();
void Start_Game();
void restart();
void exitgame();
void Msg_restart(int par);
由 LiangJian 写于 2019 年 10 月 15 日