五子棋元素为黑白两种棋子和棋盘,为此设置棋盘结构体和枚举类型设置棋子。
以二维数组的形式设置,黑棋为1,白棋为-1.初始值设置为0。判断点击位置是否有效判断无效位置——如果点击位置不在方格处无效,点击位置所在位置有棋子则点击无效。点击位置如果点击到方格中,则鼠标点击位置的像素举例该方格四个角(落子位置)最近的位置放置棋子。
如果黑棋或白棋中一方五子连成一线则游戏结束,如何判断五子连成一线——以横向为例,以落子处为起点先向左开始遍历,碰到方格纸外或碰到棋子与所下棋子不一样停止,遍历一颗棋子计数器+1,然后向右遍历,如果遍历完计数器大于5等于则游戏结束,如果小于5则换另一方落子。
#pragma once
#include
#include
#include
//棋盘格子 行列数
#define BOARD_SIZE 20
#define BOARD_LENGTH 700
//棋盘距离左边距离
#define M_X 90
//棋盘距离上边界距离
#define M_Y 140
//棋盘小格子 边长(正方形) 棋子大小
#define CHESS_SIZE 25.7
//鼠标点击 模糊距离上限
#define POS_OFFSET CHESS_SIZE * 0.4
typedef enum CHESS_TYPE {
CHESS_WHITE = -1,
CHESS_BLACK = 1
}chess_kind;
typedef struct ChessBoard {
int chessborad[BOARD_SIZE][BOARD_SIZE]; //-1 0 1
//bool playflag; // 白棋false 黑棋true
}ChessBoard;
void initchessboard(ChessBoard* pboard);//初始化棋盘
int Man_Go(int xPos, int yPos);//黑棋下棋
bool ClickBoard(MOUSEMSG msg, int* xPPos, int* yPPos);//鼠标点击位置是否在有效位置,如果有效得到鼠标点击所在数组下标
bool CheckOver(int xPos, int yPos, chess_kind kind);//是否连成五子
void init();//初始化
int AI_GO(int xPos, int yPos);//白棋下棋
#include "chess.h"
#include "string.h"
void initchessboard(ChessBoard* pboard) {
if (!pboard) //if(pboard == NULL) return;
return;
memset(pboard->chessborad, 0, sizeof(pboard->chessborad));
}
//#define BOARD_LENGTH 800
ChessBoard board;
int Man_Go(int xPos, int yPos) { //xPos yPos 有效点的像素
//黑棋放图片 putimage()
if (board.chessborad[xPos][yPos] == 0) {
board.chessborad[xPos][yPos] = CHESS_BLACK;
IMAGE img;
loadimage(&img, "黑棋子.jpg", CHESS_SIZE, CHESS_SIZE);
putimage(yPos * CHESS_SIZE + M_X - (CHESS_SIZE / 2), xPos * CHESS_SIZE + M_Y - (CHESS_SIZE / 2), &img);
return 1;
}
return -1;
}
int AI_GO(int xPos, int yPos) {
//白棋图片
if (board.chessborad[xPos][yPos] == 0) {
board.chessborad[xPos][yPos] = CHESS_WHITE;
IMAGE img;
loadimage(&img, "白棋子.jpg", CHESS_SIZE, CHESS_SIZE);
putimage(yPos * CHESS_SIZE + M_X - (CHESS_SIZE / 2), xPos * CHESS_SIZE + M_Y - (CHESS_SIZE / 2), &img);
return 1;
}
return -1;
}
//是否是有效点击位置,xPPos -> 二维数组行下标 yPPos -> 二维数组的列下标
bool ClickBoard(MOUSEMSG msg, int* xPos, int* yPos) {
if (msg.x > M_X && msg.y > M_Y&&msg.x<(BOARD_LENGTH-M_X)&&msg.y<(BOARD_LENGTH - 70)) {
int x = msg.x, y = msg.y;// 获取鼠标点击的位置像素
int row = (y / CHESS_SIZE - M_Y / CHESS_SIZE);
int col = (x / CHESS_SIZE - M_X / CHESS_SIZE);
if (((y - (M_Y + row * CHESS_SIZE)) > (CHESS_SIZE / 2)) &&
((x - (M_X + col * CHESS_SIZE)) > (CHESS_SIZE / 2))) {
*xPos = row + 1;
*yPos = col + 1;
}
else
if (((y - (M_Y + row * CHESS_SIZE)) < (CHESS_SIZE / 2)) &&
((x - (M_X + col * CHESS_SIZE)) < (CHESS_SIZE / 2))) {
*xPos = row;
*yPos = col;
}
else
if (((y - (M_Y + row * CHESS_SIZE)) > (CHESS_SIZE / 2)) &&
((x - (M_X + col * CHESS_SIZE)) < (CHESS_SIZE / 2))) {
*xPos = row + 1;
*yPos = col;
}
else
if (((y - (M_Y + row * CHESS_SIZE)) < (CHESS_SIZE / 2)) &&
((x - (M_X + col * CHESS_SIZE)) > (CHESS_SIZE / 2))) {
*xPos = row;
*yPos = col + 1;
}
return true;
}
else return false;
}
bool CheckOver(int xPos, int yPos, chess_kind kind) {
int count = 0;
//横向 ---x,y----
//横向左边
for (int i = xPos, j = yPos; j >= 0 && board.chessborad[i][--j] == kind; ) {
count++;
}
//横向右边
for (int i = xPos, j = yPos; j < BOARD_SIZE && board.chessborad[i][++j] == kind; ) {
count++;
}
if (count >= 4) {
return true;
}
//正斜向 / 斜上
count = 0;
for (int i = xPos, j = yPos; i >= 0 && j < BOARD_SIZE && board.chessborad[--i][++j] == kind;) {
count++;
}
//斜下
for (int i = xPos, j = yPos; j >= 0 && i < BOARD_SIZE && board.chessborad[++i][--j] == kind;) {
count++;
}
if (count >= 4) {
return true;
}
count = 0;
//纵向
//向上
for (int i = xPos, j = yPos; i >= 0 && board.chessborad[--i][j] == kind; ) {
count++;
}
//向下
for (int i = xPos, j = yPos; i < BOARD_SIZE && board.chessborad[++i][j] == kind; ) {
count++;
}
if (count >= 4) {
return true;
}
//反斜方向
count = 0;
//斜上
for (int i = xPos, j = yPos; i >= 0 && j >= 0 && board.chessborad[--i][--j] == kind;) {
count++;
}
//斜下
for (int i = xPos, j = yPos; j < BOARD_SIZE && i < BOARD_SIZE && board.chessborad[++i][++j] == kind;) {
count++;
}
if (count >= 4) {
return true;
}
return false;
}
void init() { // 展示初始界面 鼠标左键点击 播放音乐& 界面棋盘
initgraph(BOARD_LENGTH, BOARD_LENGTH, SHOWCONSOLE);
IMAGE image1;
loadimage(&image1, "初始界面.jpg", BOARD_LENGTH, BOARD_LENGTH, true);
putimage(0, 0, &image1);
while (1) {
MOUSEMSG msg = GetMouseMsg();
if (msg.uMsg == WM_LBUTTONDOWN) { //左键点击开始播放音乐,切换界面
mciSendString("open 背景音乐.mp3 alias music", 0, 0, 0);
mciSendString("play music repeat", 0, 0, 0);
IMAGE image2;
loadimage(&image2, "棋盘.jpg", BOARD_LENGTH, BOARD_LENGTH, true);
putimage(0, 0, &image2);
break;
}
}
}
#include
#include
#include
#include "chess.h"
#pragma comment(lib,"winmm.lib")
void start() {
MOUSEMSG msg; //监听鼠标事件
int xPos, yPos; //记录棋子即将放的位置
init(); //初始化主界面
bool flag = false; //交替黑白
//监听鼠标消息,左键点击下棋,黑棋和白棋交叉进行
while (1) {
msg = GetMouseMsg(); //获取鼠标消息
//ClickBoard-> 判断点击位置是否是有效位置,是,需要在有效位置下棋子
//(msg,&xPos,&yPos) 第二个参数和第三个参数 需要吧棋子所下位置坐标带出来
if (msg.uMsg == WM_LBUTTONDOWN && ClickBoard(msg, &xPos, &yPos)) {
if (flag == false) {
if (Man_Go(xPos, yPos) == 1) { //先下黑,再下白
if (CheckOver(xPos, yPos, CHESS_BLACK)) { //棋子成功连城5子
//提示是否继续新游戏--> MessageBox
//是:start();
mciSendString("close music", 0, 0, 0);
if (MessageBox(0, "黑棋胜利,是否开始新游戏", "五子棋", MB_OKCANCEL) ==IDCANCEL) {
exit(0);
}
else {
start();
}
}
else {
flag = true;
}
}
}
else {
if (AI_GO(xPos, yPos) == 1) {
if (CheckOver(xPos, yPos, CHESS_WHITE)) { //棋子连城5子
mciSendString("close music", 0, 0, 0);
//提示信息
if (MessageBox(0, "白棋胜利,是否开始新游戏", "五子棋", MB_OKCANCEL) == IDCANCEL) {
exit(0);
}
else {
start();
}
}
flag = false;
}
}
}
}
}
int main() {
start();
system("pause");
closegraph();
return 0;
}